Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1679969
  • 博文数量: 124
  • 博客积分: 4078
  • 博客等级: 中校
  • 技术积分: 3943
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 11:28
个人简介

新博客:http://sparkandshine.net/

文章分类

全部博文(124)

分类: 嵌入式

2011-10-30 18:57:14

摘要:

    本文先给出Contiki编程的代码框架,接着,介绍了用宏实现三种程序基本结构(即顺序、选择、循环)的基本框架,最后介绍了挂起进程相关的API。


一、代码框架

    Contiki实际编程通常只需替代Hello world的内容,main函数内容甚至无需修改,大概的代码框架如下(以两个进程为例):

  1. /*步骤1:包含需要的头文件*/
  2. #include "contiki.h"
  3. #include "debug-uart.h"

  4. /*步骤2:用PROCESS宏声明进程执行主体,并定义进程*/
  5. PROCESS(example_1_process, "Example 1"); //PROCESS(name, strname)    
  6. PROCESS(example_2_process, "Example 1");

  7. /*步骤3:用AUTOSTART_PROCESSES宏让进程自启动*/
  8. AUTOSTART_PROCESSES(&example_1_process, &example_2_process); //AUTOSTART_PROCESSES(...)    

  9. /*步骤4:定义进程执行主体thread*/
  10. PROCESS_THREAD(example_1_process, ev, data) //PROCESS_THREAD(name, ev, data)
  11. {
  12.   PROCESS_BEGIN();  /*代码总是以宏PROCESS_BEGIN开始*/

  13.   /*example_1_process的代码*/

  14.   PROCESS_END();  /*代码总是以宏PROCESS_END结束*/
  15. }

  16. PROCESS_THREAD(example_2_process, ev, data)
  17. {
  18.   PROCESS_BEGIN();

  19.   /*example_2_process的代码*/

  20.   PROCESS_END();
  21. }

    可参考博文《Contiki学习笔记:实例hello_world剖析》以获得更直观的认识,接下来给出三种程序基本结构(即顺序、选择、循环)的模式。

二、顺序&选择&循环

2.1 顺序

  1. PROCESS_BEGIN();
  2. (*...*)
  3. PROCESS_WAIT_UNTIL(cond1); //注1
  4. (*...*)
  5. PROCESS_END();

2.2 循环

  1. PROCESS_BEGIN();
  2. (*...*)
  3. while (cond1)
  4.   PROCESS_WAIT_UNTIL(cond1 or cond2); //注1
  5. (*...*)
  6. PROCESS_END();

2.3 选择

  1. PROCESS_BEGIN();
  2. (*...*)
  3. if (condtion)
  4.   PROCESS_WAIT_UNTIL(cond2a); //注1
  5. else
  6.   PROCESS_WAIT_UNTIL(cond2b); //注1
  7. (*...*)
  8. PROCESS_END();

    注1:这里不一定非得用宏PROCESS_WAIT_UNTIL,事实上有很多选择,比如宏PROCESS_WAIT_EVENT_UNTIL(c)、宏PROCESS_WAIT_EVENT()、宏PROCESS_YIELD_UNTIL(c)等(请参见本文第三部分),实际编程应根据实际情况加以选择。

三、挂起进程相关API

3.1 概述

    表1给出挂起进程相关API的功能描述,事实上,实际编程所关心的是,什么时候继续执行宏后面的内容,3.2~3.6给出了详见分析。

表1 Contiki挂起进程相关API[1]

PROCESS_WAIT_EVENT()

Wait for an event to be posted to the process.

PROCESS_YIELD()

Yield the currently running process.

PROCESS_WAIT_EVENT_UNTIL(c)

Wait for an event to be posted to the process, with an extra condition.

PROCESS_YIELD_UNTIL(c)

Yield the currently running process until a condition occurs.

PROCESS_WAIT_UNTIL(c)

Wait for a condition to occur.

PROCESS_WAIT_WHILE(c)

Block and wait while condition is true.

PROCESS_PT_SPAWN(pt, thread)

Spawn a protothread from the process.

PROCESS_PAUSE()

Yield the process for a short while.

3.2 PROCESS_WAIT_EVENT和PROCESS_YIELD

    从代码展开来看,宏PROCESS_WAIT_EVENT和宏PROCESS_YIELD实现的功能是一样的(或者说PROCESS_WAIT_EVENT只是PROCESS_YIELD的一个别名),只是两种不同的描述。也就是说当PT_YIELD_FLAG为1时(即该进程再次被调度的时候,想想PROCESS_BEGIN宏包含语句PT_YIELD_FLAG=1),才执行宏后面的代码,否则返回。代码展开如下:

  1. #define PROCESS_WAIT_EVENT() PROCESS_YIELD()
  2. #define PROCESS_YIELD() PT_YIELD(process_pt)

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

3.3 PROCESS_WAIT_EVENT_UNTIL和PROCESS_YIELD_UNTIL

    根3.2类似,宏PROCESS_WAIT_EVENT_UNTIL和宏PROCESS_YIELD_UNTIL是一组,在3.2的基础是增加了额外的一个条件,也就是说当PT_YIELD_FLAG为1且条件为true时(即进程再次被调度的时候,条件为true,因为PROCESS_BEGIN宏已包含语句PT_YIELD_FLAG),才执行宏后面的代码,否则返回。代码展开如下:

  1. #define PROCESS_WAIT_EVENT_UNTIL(c) PROCESS_YIELD_UNTIL(c)
  2.   #define PROCESS_YIELD_UNTIL(c) PT_YIELD_UNTIL(process_pt, c)

  3.   #define PT_YIELD_UNTIL(pt, cond)        \
  4.   do
  5.   {                        \
  6.     PT_YIELD_FLAG = 0;                \
  7.     LC_SET((pt)->lc);                \
  8.     if((PT_YIELD_FLAG == 0) || !(cond))
  9.     {    \
  10.       return PT_YIELDED;            \
  11.     }                        \
  12.   } while(0)

3.4 PROCESS_WAIT_UNTIL和PROCESS_WAIT_WHILE

    从代码展开来看,宏PROCESS_WAIT_UNTIL和宏PROCESS_WAIT_WHILE判断的条件相反,PROCESS_WAIT_UNTIL宏当条件为真时(即某个事件发生),执行宏后面的内容。而PROCESS_WAIT_WHILE宏当条件为假时,执行宏后面的内容(即当条件为真时,阻塞该进程)。

  1. /*PROCESS_WAIT_UNTIL宏展开*/
  2. #define PROCESS_WAIT_UNTIL(c) PT_WAIT_UNTIL(process_pt, c)

  3. /*PROCESS_WAIT_WHILE宏展开*/
  4. #define PROCESS_WAIT_WHILE(c) PT_WAIT_WHILE(process_pt, c)
  5. #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))

  6. /*PT_WAIT_UNTIL宏展开*/
  7. #define PT_WAIT_UNTIL(pt, condition)     \
  8.   do
  9.   {                        \
  10.     LC_SET((pt)->lc);                \
  11.     if(!(condition))
  12.     {                \
  13.       return PT_WAITING;            \
  14.     }                        \
  15.   } while(0)

3.5 PROCESS_PT_SPAWN

    PROCESS_PT_SPAWN用于产生一个子protothread,若执行完thread并退出PT_EXITED,则继续执行宏PROCESS_PT_SPAWN后面的内容。宏一层层展开如下:

  1. #define PROCESS_PT_SPAWN(pt, thread) PT_SPAWN(process_pt, pt, thread)
  2. #define PT_SPAWN(pt, child, thread)        \
  3.   do
  4.   {                        \
  5.     PT_INIT((child));                \
  6.     PT_WAIT_THREAD((pt), (thread));        \
  7.   } while(0)
  8.   
  9. #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))

  10. #define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))

  11. #define PT_SCHEDULE(f) ((f) < PT_EXITED)

3.6 PROCESS_PAUSE

    宏PROCESS_PAUSE用于向进程传递事件PROCESS_EVENT_CONTINUE,并等到任一事件发生,即被挂起了(但我并没有看到哪个地方对事件PROCESS_EVENT_CONTINUE优先处理了)。宏展开如下如下:

  1. #define PROCESS_PAUSE()
  2. do
  3. {                \
  4.   process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL);    \
  5.   PROCESS_WAIT_EVENT();                            \
  6. } while(0)

3.7 PROCESS_WAIT_EVENT_UNTIL与PROCESS_WAIT_UNTIL区别

    从上述3.3和3.4代码展开可以看出,宏PROCESS_WAIT_EVENT_UNTIL和宏PROCESS_WAIT_UNTIL的区别在于:前者除了要判断条件外,还需判断PT_YIELD_FLAG;而后者只需判断条件。并且返回值也不一样。


参考资料:

[1]

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

ManyHong2016-01-31 22:18:39

3.7是前者判断标志和条件,后者只需要判断标志无论什么事件吧

ManyHong2016-01-31 22:18:38

3.7是前者判断标志和条件,后者只需要判断标志无论什么事件吧