摘要:
本文旨在剖析main函数,从更高层次理解Contiki系统。先是给出源码,接着总结功能,最后深入源码分析。
一、main函数源码
- //filename:contiki-main.c
-
#include <stm32f10x.h>
-
#include <stm32f10x_dma.h>
-
#include <stdint.h>
-
#include <stdio.h>
-
#include <debug-uart.h>
-
#include <sys/process.h>
-
#include <sys/procinit.h>
-
#include <etimer.h>
-
#include <sys/autostart.h>
-
#include <clock.h>
-
-
int main()
-
{
-
dbg_setup_uart(); //串口初始化,与硬件相关(注1)
-
usart_puts("Initialising\n"); //向串口打印字符串"Initialising"
-
-
clock_init();//时钟初始化,与硬件相关,见3.3
-
process_init(); //进程初始化,详情见3.1
- process_start(&etimer_process, NULL); //启动etimer_process,详情见3.2
-
autostart_start(autostart_processes); //启动指针数组autostart_processes[]里的所有进程,详情见3.2
-
-
while (1)
-
{
-
/*执行完所有needspoll为1的进程及处理完所有队列,详情见3.2*/
-
do
-
{
-
}
-
while (process_run() > 0);
-
}
-
return 0;
- }
注1:
串口初始化和时钟初始化与硬件相关(我用的MCU是STM32F103RBT6),不深入讨论,主要基于以下两个原因:其一,这部分对理解系统影响不大;其二,我对硬件不是很熟。
二、程序解读
系统先进行一系列初始化(串口、时钟、进程),接着启动系统进程etimer_process和指针数组autostart_processes[]里的所有进程,到这里就启动了所有的系统进程(当然,后续的操作还可能动态产生新进程)。接下来的工作,就是系统反复处理所有needspoll标记为1的进程及事件队列中所有事件。而处理事件过程中(典型情况是让某些进程继续执行)又可能产生新的事件,再处理事件,系统如此反复运行。
三、源码详解
3.1 进程初始化
- /****进程初始化****/
-
void process_init(void)
-
{
-
/*初始化事件队列*/
-
lastevent = PROCESS_EVENT_MAX;
-
nevents = fevent = 0;
-
-
#if PROCESS_CONF_STATS
-
process_maxevents = 0;
-
#endif
-
-
process_current = process_list = NULL; //初始化进程链表
- }
3.2 注明
有关etimer_process参考博文《Contiki学习笔记:系统进程etimer_process 》
有关process_start参考博文《Contiki学习笔记:启动一个进程process_start》
有关process_run参考博文《Contiki学习笔记:深入理解process_run函数》
- //autostart_start(autostart_processes);
- void autostart_start(struct process *const processes[])
- {
- int i;
- for(i = 0; processes[i] != NULL; ++i)
- {
- process_start(processes[i], NULL);
- PRINTF("autostart_start: starting process '%s'\n", processes[i]->name);
- }
- }
- #define AUTOSTART_PROCESSES(...) \
- struct process * const autostart_processes[] = {__VA_ARGS__, NULL}
3.3 时钟初始化
clock_init用于配置系统产生嘀嗒的间隔,即每隔72000000/CLOCK_SECOND产生一次系统嘀嗒(72000000是指1s可以产生最大的嘀嗒数),也就是说1秒钟可以产生CLOCK_SECOND次时钟中断。
- void clock_init()
-
{
-
SysTick_Config(72000000 / CLOCK_SECOND);
-
}
-
-
/*CLOCK_SECOND宏定义*/
-
#define CLOCK_CONF_SECOND 10
-
-
#ifdef CLOCK_CONF_SECOND
-
#define CLOCK_SECOND CLOCK_CONF_SECOND
-
#else
-
#define CLOCK_SECOND (clock_time_t)32
- #endif
SysTick_Config函数展开如下,与硬件相关(我用的MCU是STM32F103RBT6):
- /**
-
* @brief Initialize and start the SysTick counter and its interrupt.
-
*
-
* @param ticks number of ticks between two interrupts
-
* @return 1 = failed, 0 = successful
-
*
-
* Initialise the system tick timer and its interrupt and start the
-
* system tick timer / counter in free running mode to generate
-
* periodical interrupts.
-
*/
-
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
-
{
-
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
-
-
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
-
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
-
SysTick->VAL = 0; /* Load the SysTick Counter Value */
-
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
-
SysTick_CTRL_TICKINT_Msk |
-
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
-
return (0); /* Function successful */
- }