摘要:
本文先给出Contiki编程的代码框架,接着,介绍了用宏实现三种程序基本结构(即顺序、选择、循环)的基本框架,最后介绍了挂起进程相关的API。
一、代码框架
Contiki实际编程通常只需替代Hello world的内容,main函数内容甚至无需修改,大概的代码框架如下(以两个进程为例):
- /*步骤1:包含需要的头文件*/
-
#include "contiki.h"
-
#include "debug-uart.h"
-
-
/*步骤2:用PROCESS宏声明进程执行主体,并定义进程*/
-
PROCESS(example_1_process, "Example 1"); //PROCESS(name, strname)
-
PROCESS(example_2_process, "Example 1");
-
-
/*步骤3:用AUTOSTART_PROCESSES宏让进程自启动*/
-
AUTOSTART_PROCESSES(&example_1_process, &example_2_process); //AUTOSTART_PROCESSES(...)
-
-
/*步骤4:定义进程执行主体thread*/
-
PROCESS_THREAD(example_1_process, ev, data) //PROCESS_THREAD(name, ev, data)
- {
- PROCESS_BEGIN(); /*代码总是以宏PROCESS_BEGIN开始*/
-
-
/*example_1_process的代码*/
- PROCESS_END(); /*代码总是以宏PROCESS_END结束*/
-
}
-
-
PROCESS_THREAD(example_2_process, ev, data)
-
{
-
PROCESS_BEGIN();
-
-
/*example_2_process的代码*/
-
-
PROCESS_END();
- }
可参考博文《Contiki学习笔记:实例hello_world剖析》以获得更直观的认识,接下来给出三种程序基本结构(即顺序、选择、循环)的模式。
二、顺序&选择&循环
2.1 顺序
- PROCESS_BEGIN();
-
(*...*)
-
PROCESS_WAIT_UNTIL(cond1); //注1
-
(*...*)
- PROCESS_END();
2.2 循环
- PROCESS_BEGIN();
-
(*...*)
-
while (cond1)
-
PROCESS_WAIT_UNTIL(cond1 or cond2); //注1
-
(*...*)
- PROCESS_END();
2.3 选择
- PROCESS_BEGIN();
-
(*...*)
-
if (condtion)
-
PROCESS_WAIT_UNTIL(cond2a); //注1
-
else
-
PROCESS_WAIT_UNTIL(cond2b); //注1
-
(*...*)
- 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),才执行宏后面的代码,否则返回。代码展开如下:
- #define PROCESS_WAIT_EVENT() PROCESS_YIELD()
-
#define PROCESS_YIELD() PT_YIELD(process_pt)
-
-
#define PT_YIELD(pt) \
-
do
-
{ \
-
PT_YIELD_FLAG = 0; \
-
LC_SET((pt)->lc); \
-
if(PT_YIELD_FLAG == 0)
-
{ \
-
return PT_YIELDED; \
-
} \
- } 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),才执行宏后面的代码,否则返回。代码展开如下:
- #define PROCESS_WAIT_EVENT_UNTIL(c) PROCESS_YIELD_UNTIL(c)
-
#define PROCESS_YIELD_UNTIL(c) PT_YIELD_UNTIL(process_pt, c)
-
-
#define PT_YIELD_UNTIL(pt, cond) \
-
do
-
{ \
-
PT_YIELD_FLAG = 0; \
-
LC_SET((pt)->lc); \
-
if((PT_YIELD_FLAG == 0) || !(cond))
-
{ \
-
return PT_YIELDED; \
-
} \
- } while(0)
3.4 PROCESS_WAIT_UNTIL和PROCESS_WAIT_WHILE
从代码展开来看,宏PROCESS_WAIT_UNTIL和宏PROCESS_WAIT_WHILE判断的条件相反,PROCESS_WAIT_UNTIL宏当条件为真时(即某个事件发生),执行宏后面的内容。而PROCESS_WAIT_WHILE宏当条件为假时,执行宏后面的内容(即当条件为真时,阻塞该进程)。
- /*PROCESS_WAIT_UNTIL宏展开*/
-
#define PROCESS_WAIT_UNTIL(c) PT_WAIT_UNTIL(process_pt, c)
-
/*PROCESS_WAIT_WHILE宏展开*/
-
#define PROCESS_WAIT_WHILE(c) PT_WAIT_WHILE(process_pt, c)
-
#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
-
-
/*PT_WAIT_UNTIL宏展开*/
-
#define PT_WAIT_UNTIL(pt, condition) \
-
do
-
{ \
-
LC_SET((pt)->lc); \
-
if(!(condition))
-
{ \
-
return PT_WAITING; \
-
} \
- } while(0)
3.5 PROCESS_PT_SPAWN
PROCESS_PT_SPAWN用于产生一个子protothread,若执行完thread并退出PT_EXITED,则继续执行宏PROCESS_PT_SPAWN后面的内容。宏一层层展开如下:
- #define PROCESS_PT_SPAWN(pt, thread) PT_SPAWN(process_pt, pt, thread)
-
#define PT_SPAWN(pt, child, thread) \
-
do
-
{ \
-
PT_INIT((child)); \
-
PT_WAIT_THREAD((pt), (thread)); \
-
} while(0)
-
-
#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
-
-
#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
-
- #define PT_SCHEDULE(f) ((f) < PT_EXITED)
3.6 PROCESS_PAUSE
宏PROCESS_PAUSE用于向进程传递事件PROCESS_EVENT_CONTINUE,并等到任一事件发生,即被挂起了(但我并没有看到哪个地方对事件PROCESS_EVENT_CONTINUE优先处理了)。宏展开如下如下:
- #define PROCESS_PAUSE()
-
do
-
{ \
-
process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL); \
-
PROCESS_WAIT_EVENT(); \
- } 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]