Contiki学习笔记:main函数剖析

8607阅读 0评论2011-10-26 Jelline
分类:嵌入式

摘要:

    本文旨在剖析main函数,从更高层次理解Contiki系统。先是给出源码,接着总结功能,最后深入源码分析。


一、main函数源码

  1. //filename:contiki-main.c
  2. #include <stm32f10x.h>
  3. #include <stm32f10x_dma.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <debug-uart.h>
  7. #include <sys/process.h>
  8. #include <sys/procinit.h>
  9. #include <etimer.h>
  10. #include <sys/autostart.h>
  11. #include <clock.h>

  12. int main()
  13. {
  14.   dbg_setup_uart(); //串口初始化,与硬件相关(注1)
  15.   usart_puts("Initialising\n"); //向串口打印字符串"Initialising"

  16.   clock_init();//时钟初始化,与硬件相关,见3.3

  17.   process_init(); //进程初始化,详情见3.1
  18.   process_start(&etimer_process, NULL); //启动etimer_process,详情见3.2
  19.   autostart_start(autostart_processes); //启动指针数组autostart_processes[]里的所有进程,详情见3.2

  20.   while (1)
  21.   {
  22.     /*执行完所有needspoll为1的进程及处理完所有队列,详情见3.2*/
  23.     do
  24.     {
  25.     }
  26.     while (process_run() > 0);
  27.   }
  28.   return 0;
  29. }

注1:

    串口初始化和时钟初始化与硬件相关(我用的MCU是STM32F103RBT6),不深入讨论,主要基于以下两个原因:其一,这部分对理解系统影响不大;其二,我对硬件不是很熟。

二、程序解读

    系统先进行一系列初始化(串口、时钟、进程),接着启动系统进程etimer_process和指针数组autostart_processes[]里的所有进程,到这里就启动了所有的系统进程(当然,后续的操作还可能动态产生新进程)。接下来的工作,就是系统反复处理所有needspoll标记为1的进程及事件队列中所有事件。而处理事件过程中(典型情况是让某些进程继续执行)又可能产生新的事件,再处理事件,系统如此反复运行。

三、源码详解

3.1 进程初始化

  1. /****进程初始化****/
  2. void process_init(void)
  3. {
  4.   /*初始化事件队列*/
  5.   lastevent = PROCESS_EVENT_MAX;
  6.   nevents = fevent = 0;

  7.   #if PROCESS_CONF_STATS
  8.     process_maxevents = 0;
  9.   #endif

  10.   process_current = process_list = NULL; //初始化进程链表
  11. }

3.2 注明

有关etimer_process参考博文《Contiki学习笔记:系统进程etimer_process

有关process_start参考博文《Contiki学习笔记:启动一个进程process_start

有关process_run参考博文《Contiki学习笔记:深入理解process_run函数

autostart_start函数用于启动autostart_processes指针数组里的进程,源代码如下:
  1. //autostart_start(autostart_processes);
  2. void autostart_start(struct process *const processes[])
  3. {
  4.   int i;

  5.   for(i = 0; processes[i] != NULL; ++i)
  6.   {
  7.     process_start(processes[i], NULL);
  8.     PRINTF("autostart_start: starting process '%s'\n", processes[i]->name);
  9.   }
  10. }
    autostart_processes由宏AUTOSTART_PROCESSES定义,详情参见博文《Contiki学习笔记:实例hello_world剖析》第三部分。其源代码如下:
  1. #define AUTOSTART_PROCESSES(...)                    \
  2. struct process * const autostart_processes[] = {__VA_ARGS__, NULL}

3.3 时钟初始化

    clock_init用于配置系统产生嘀嗒的间隔,即每隔72000000/CLOCK_SECOND产生一次系统嘀嗒(72000000是指1s可以产生最大的嘀嗒数),也就是说1秒钟可以产生CLOCK_SECOND次时钟中断。

  1. void clock_init()
  2. {
  3.   SysTick_Config(72000000 / CLOCK_SECOND);
  4. }

  5. /*CLOCK_SECOND宏定义*/
  6. #define CLOCK_CONF_SECOND 10

  7. #ifdef CLOCK_CONF_SECOND
  8.   #define CLOCK_SECOND CLOCK_CONF_SECOND
  9. #else
  10.   #define CLOCK_SECOND (clock_time_t)32
  11. #endif

SysTick_Config函数展开如下,与硬件相关(我用的MCU是STM32F103RBT6):

  1. /**
  2.  * @brief Initialize and start the SysTick counter and its interrupt.
  3.  *
  4.  * @param ticks number of ticks between two interrupts
  5.  * @return 1 = failed, 0 = successful
  6.  *
  7.  * Initialise the system tick timer and its interrupt and start the
  8.  * system tick timer / counter in free running mode to generate
  9.  * periodical interrupts.
  10.  */
  11. static __INLINE uint32_t SysTick_Config(uint32_t ticks)
  12. {
  13.   if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);            /* Reload value impossible */
  14.                                                                
  15.   SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  16.   NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
  17.   SysTick->VAL = 0;   /* Load the SysTick Counter Value */
  18.   SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  19.                    SysTick_CTRL_TICKINT_Msk |
  20.                    SysTick_CTRL_ENABLE_Msk;   /* Enable SysTick IRQ and SysTick Timer */
  21.   return (0);   /* Function successful */
  22. }

上一篇:Contiki学习笔记:目录
下一篇:Contiki学习笔记:时钟中断处理程序Systick_isr