什么是contiki?
Contiki is an open source operating system for the Internet of Things. Contiki connects tiny low-cost, low-power microcontrollers to the Internet.
contiki的主要特点:
- Open Source Software
- Full IP Networking( with standard IP protocols such as UDP, TCP, and HTTP, in addition to the new low-power standards like 6lowpan, RPL, and CoAP. )
- Dynamic Module Loading(he Contiki module loader can load, relocate, and link standard ELF files that can optionally be stripped off their debugging symbols to keep their size down.)
- Protothreads(Protothreads is a mixture of the event-driven and the multi-threaded programming mechanisms. With protothreads, event-handlers can be made to block, waiting for events to occur.)
http://muneebali.com/pubs/dunkels06protothreads.pdf
protothread中文学习资料:
contiki代码学习之一:浅探protothread进程控制模型【1】
zhuangxiu.ganji.com/ask/2587821.htm
zhuangxiu.ganji.com/ask/2587822.htm
zhuangxiu.ganji.com/ask/2587823.htm
http://zhuangxiu.ganji.com/ask/2587821.htm
http://zhuangxiu.ganji.com/ask/2587822.htm
http://zhuangxiu.ganji.com/ask/2587823.htm
http://contikistudio.smeshlink.com/forum.php?mod=viewthread&tid=274&extra=page%3D1
http://blog.chinaunix.net/uid-9112803-id-2898026.html
Contiki的任务调度机制
Protothreads给嵌入式带来了很大的方面,且与多线程相比非常节省RAM资源,每个Protothread只保存1个字节。缺点就是程序如果想保存上一次调用的状态,需要使用全局变量。还有一个特殊的问题是protothread引入了一些宏:PROCESS_BEGIN(),PROCESS_END()等,这些宏使得代码的执行顺序和c语言的通常代码的执行顺序不同。
从我遇到的一个问题说起,原本的问题来自一个协议栈,设计随机数的产生,为了突出重点,只保留问题相关部分(每秒产生一个随机数)。发现随机数每次都不变!代码如下:
#include "contiki.h"
#include <stdio.h>
#include "lib/random.h"
/*---------------------------------------------------------------------------*/
PROCESS(pt_test_process, "pt test process");
AUTOSTART_PROCESSES(&pt_test_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(pt_test_process, ev, data)
{
static struct etimer et;
random_init(0);
PROCESS_BEGIN();
while(1){
etimer_set(&et, CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
printf("random number is:%d\n",random_rand());
etimer_set(&et, CLOCK_SECOND);
}
PROCESS_END();
}
编译:make pt_test TARGET=native
执行:./pt_test.native
输出:
contiki started
Rime started with address 2.1
MAC nullmac RDC nullrdc NETWORK Rime
random number is:17767
random number is:17767
random number is:17767
经检查不是random相关函数的问题,而是random_init(0);的位置没有写对,每秒时间触发后都会执行一次random_init(0);所以random_rand()的结果就不随机了
将 random_init(0);和PROCESS_BEGIN();的位置颠倒一下就好了。
输出结果为:
contiki started
Rime started with address 2.1
MAC nullmac RDC nullrdc NETWORK Rime
random number is:17767
random number is:9158
random number is:39017
random number is:18547
random number is:56401
从这个例子可以看出,该protothread被系统调用并不是直接跳转到PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));那一行,而是从程序入口执行到PROCESS_BEGIN();再跳转到PROCESS_WAIT_EVENT_UNTIL那一行。为了更形象的说明protothread的执行顺序,看下面的代码:
#include "contiki.h"
#include <stdio.h>
#include "lib/random.h"
/*---------------------------------------------------------------------------*/
PROCESS(pt_test_process, "pt test process");
AUTOSTART_PROCESSES(&pt_test_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(pt_test_process, ev, data)
{
static struct etimer et;
printf("before BEGIN\n");
PROCESS_BEGIN();
printf("after BEGIN\n");
while(1){
printf("before PROCESS_WAIT_EVENT_UNTIL\n");
etimer_set(&et, CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
etimer_set(&et, CLOCK_SECOND);
printf("after PROCESS_WAIT_EVENT_UNTIL\n");
}
printf("before END\n");
PROCESS_END();
printf("after END\n");
}
/*---------------------------------------------------------------------------*/
结果输出如下:
contiki started
Rime started with address 2.1
MAC nullmac RDC nullrdc NETWORK Rime
before BEGIN
after BEGIN
before PROCESS_WAIT_EVENT_UNTIL
before BEGIN
after PROCESS_WAIT_EVENT_UNTIL
before PROCESS_WAIT_EVENT_UNTIL
before BEGIN
after PROCESS_WAIT_EVENT_UNTIL
before PROCESS_WAIT_EVENT_UNTIL
before BEGIN
after PROCESS_WAIT_EVENT_UNTIL
before PROCESS_WAIT_EVENT_UNTIL
^C
after BEGIN部分只执行了一遍,before BEGIN,after PROCESS_WAIT_EVENT_UNTIL,before PROCESS_WAIT_EVENT_UNTIL部分每次时间触发都会执行,请注意上面的顺序。
小结:在protothread编程中,程序初始化的部分(只执行一次的)放在after BEGIN部分,每次事件触发的处理放在after PROCESS_WAIT_EVENT_UNTIL。