Chinaunix首页 | 论坛 | 博客
  • 博客访问: 27276
  • 博文数量: 12
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 82
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-30 14:36
文章分类

全部博文(12)

文章存档

2016年(7)

2015年(5)

我的朋友

分类: 嵌入式

2016-09-12 13:46:49

代码下载地址:,工程目录contiki_stm32\platform\stm32test\MDK_5,使用的是MDK5,硬件环境STM32F0

点击(此处)折叠或打开

  1. #include "app_uart_fifo.h"
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <sys/process.h>
  5. #include <sys/procinit.h>
  6. #include <etimer.h>
  7. #include <sys/autostart.h>
  8. #include <clock.h>
  9. #include "bsp_imp.h"

  10. static void CtimerTest_Callback(void *p)
  11. {
  12.         printf("Ctimer Callback running\r\n");
  13. }



  14. static process_event_t event_data_ready;

  15. PROCESS(print_hello_process, "Hello");
  16. PROCESS(print_world_process, "world");

  17. AUTOSTART_PROCESSES(&print_hello_process, &print_world_process);


  18. PROCESS_THREAD(print_hello_process, ev, data)
  19. {
  20.         PROCESS_BEGIN();
  21.         static struct etimer timer;
  22.         
  23.         etimer_set(&timer, CLOCK_CONF_SECOND*5);
  24.         printf("***print hello process start***\r\n");

  25.         event_data_ready = process_alloc_event();
  26.         while (1)
  27.         {
  28.                 
  29.                 PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);

  30.                 printf("Hello\r\n");

  31.                 process_post(&print_world_process, event_data_ready, NULL);

  32.                 etimer_reset(&timer);
  33.         }

  34.         PROCESS_END();
  35. }

  36. PROCESS_THREAD(print_world_process, ev, data)
  37. {
  38.         PROCESS_BEGIN();

  39.         printf("***print world process start***\r\n");
  40.         

  41.         while (1)
  42.         {
  43.                 PROCESS_WAIT_EVENT_UNTIL(ev == event_data_ready);
  44.                 printf("world\r\n");
  45.         }

  46.         PROCESS_END();
  47. }


  48. unsigned int idle_count = 0;

  49. int main()
  50. {
  51.         Bsp_Init();
  52.         printf("Initialising\r\n");

  53.         clock_init();
  54.         
  55.         ctimer_init();
  56.         
  57.         process_init();
  58.         process_start(&etimer_process, NULL);
  59.         autostart_start(autostart_processes);
  60.         printf("Processes running\r\n");
  61.         
  62.         while(1) {
  63.                 do {
  64.                         
  65.                 } while(process_run() > 0);
  66.                 idle_count++;
  67.         }
  68. }

执行流程

程序启动,contiki中定时器运行,定时时间到,执行流程如下:SysTick_Handler() -> etimer_request_poll() .> process_run() -> do_poll() -> etimer_process() -> process_post() ..> do_event() -> print_hello_process(),到此运行打印hello的线程。打印world的线程和上面类似,print_hello_process传递一个事件到world线程,通知其打印world。

进程挂起

上述程序执行到etimer_process()进程时是如何挂起自己的呢?该进程的源码如下:

点击(此处)折叠或打开

  1. PROCESS_THREAD(etimer_process, ev, data)
  2. {
  3.   struct etimer *t, *u;
  4.     
  5.   PROCESS_BEGIN();//进程每次得到CPU使用权均要从这里运行,详见分析

  6.   timerlist = NULL;
  7.   
  8.   while(1) {
  9.     PROCESS_YIELD();//使进程挂起,详见下面分析

  10.     if(ev == PROCESS_EVENT_EXITED) {
  11.       struct process *p = data;

  12.       while(timerlist != NULL && timerlist->p == p) {
  13.     timerlist = timerlist->next;
  14.       }

  15.       if(timerlist != NULL) {
  16.     t = timerlist;
  17.     while(t->next != NULL) {
  18.      if(t->next->p == p) {
  19.      t->next = t->next->next;
  20.      } else
  21.      t = t->next;
  22.     }
  23.       }
  24.       continue;
  25.     } else if(ev != PROCESS_EVENT_POLL) {
  26.       continue;
  27.     }

  28.   again:
  29.     
  30.     u = NULL;
  31.     
  32.     for(t = timerlist; t != NULL; t = t->next) {
  33.       if(timer_expired(&t->timer)) {
  34.     if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
  35.     
  36.      /* Reset the process ID of the event timer, to signal that the
  37.      etimer has expired. This is later checked in the
  38.      etimer_expired() function. */
  39.      t->p = PROCESS_NONE;
  40.      if(u != NULL) {
  41.      u->next = t->next;
  42.      } else {
  43.      timerlist = t->next;
  44.      }
  45.      t->next = NULL;
  46.      update_time();
  47.      goto again;
  48.     } else {
  49.      etimer_request_poll();
  50.     }
  51.       }
  52.       u = t;
  53.     }
  54.     
  55.   }
  56.   
  57.   PROCESS_END();//进程退出
  58. }

重要宏定义


点击(此处)折叠或打开

  1. PROCESS_BEGIN();

  2. #define PROCESS_BEGIN() PT_BEGIN(process_pt)

  3. #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} LC_RESUME((pt)->lc)
  4. #define LC_RESUME(s) switch(s) { case 0:
PROCESS_BEGIN()线程每次均要从这里启动,并根据(pt)->lc实现跳转,这里类似与操作系统中保护现场,这里如果线程被挂起,也需要保护现场,这里保存本次运行的行数,下次在运行根据上次保存的行数实现跳转。因此该宏定义有两个作用:实现线程启动(该宏将置PT_YIELD_FLAG1,后面会有说明);跳转到上次运行的位置。

点击(此处)折叠或打开

  1. #define PROCESS_END() PT_END(process_pt)
  2. #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
  3.                    PT_INIT(pt); return PT_ENDED; }
PROCESS_END()结束线程的运行,和PROCESS_BEGIN()成对使用。


点击(此处)折叠或打开

  1. #define PROCESS_YIELD() PT_YIELD(process_pt)
  2. #define PT_YIELD(pt)                \
  3.   do {                        \
  4.     PT_YIELD_FLAG = 0;                \
  5.     LC_SET((pt)->lc);                \
  6.     if(PT_YIELD_FLAG == 0) {            \
  7.       return PT_YIELDED;            \
  8.     }                        \
  9.   } while(0)

PROCESS_YIELD()这个宏定义实现了进程挂起,并保护了现场。将其与PROCESS_BEGIN()和在一起看看执行流程。
开始执行etimer进程,一直执行到
PROCESS_YIELD(),保存现场,并实现进程挂起。第二次运行时,PROCESS_BEGIN将PT_YIELD_FLAG置1(让进程可以运行),并跳转到开始运行保护现场的位置。此时即实现了进程挂起和启动进程的功能。






阅读(566) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~