struct process {
struct process *next;
#if PROCESS_CONF_NO_PROCESS_NAMES
#define PROCESS_NAME_STRING(process) ""
#else
const char *name;
#define PROCESS_NAME_STRING(process) (process)->name
#endif
PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));
struct pt pt;
unsigned char state, needspoll;
};
至此我们至少可以CTRL+C/CTRL+V写出自己的小的测试程序,我们不管是学习TinyOS或者Contiki实际并不是只是make然后下载,验证结果就完事了,应该掌握代码的编写;鱼和渔的基本区别是我写这些文档的意义所在;
TinyOS和Contiki都是event驱动;RIOT在Contiki介绍完后会重点去介绍;个人还是比较喜欢他的风格一点;
回忆TinyOS的event是很简单的,采用signal抛出事件,使用者处理;
Contiki的event咱们慢慢来看;我们现在在test_null基础上再编写一次,达到事件处理的目的;
首先在:core/sys/process.h中:typedef unsigned char process_event_t;
typedef void * process_data_t;
typedef unsigned char process_num_events_t;
我们这次需要用到的函数为:
process_post
在core/sys/process.c中
int
process_post(struct process *p, process_event_t ev, process_data_t data)
{
static process_num_events_t snum;
if(PROCESS_CURRENT() == NULL) {
PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n",
ev,PROCESS_NAME_STRING(p), nevents);
} else {
PRINTF("process_post: Process '%s' posts event %d to process '%s', nevents %d\n",
PROCESS_NAME_STRING(PROCESS_CURRENT()), ev,
p == PROCESS_BROADCAST? "<broadcast>": PROCESS_NAME_STRING(p), nevents);
}
if(nevents == PROCESS_CONF_NUMEVENTS) {
#if DEBUG
if(p == PROCESS_BROADCAST) {
printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current));
} else {
printf("soft panic: event queue is full when event %d was posted to %s from %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current));
}
#endif /* DEBUG */
return PROCESS_ERR_FULL;
}
snum = (process_num_events_t)(fevent + nevents) % PROCESS_CONF_NUMEVENTS;
events[snum].ev = ev;
events[snum].data = data;
events[snum].p = p;
++nevents;
#if PROCESS_CONF_STATS
if(nevents > process_maxevents) {
process_maxevents = nevents;
}
#endif /* PROCESS_CONF_STATS */
return PROCESS_ERR_OK;
}
下面修改test_null.c文件
#include "contiki.h"
#include "dev/leds.h"
static process_event_t event_xxoo;
PROCESS(test_null, "我是菜鸟");
PROCESS(test_event, "我还是菜鸟");
AUTOSTART_PROCESSES(&test_null, &test_event);
PROCESS_THREAD(test_null, ev, data)
{
PROCESS_BEGIN();
event_xxoo = process_alloc_event();
process_post(&test_event, event_xxoo, NULL);
PROCESS_END();
}
PROCESS_THREAD(test_event, ev, data)
{
PROCESS_BEGIN();
PROCESS_WAIT_EVENT_UNTIL(ev == event_xxoo);
leds_on(LEDS_ALL);
PROCESS_END();
}
看到不认识的家伙了 process_alloc_event();
在core/sys/process.c中:
process_event_t
process_alloc_event(void)
{
return lastevent++;
}
PROCESS_WAIT_EVENT_UNTIL在core/sys/process.h中:
#define PROCESS_YIELD_UNTIL(c) PT_YIELD_UNTIL(process_pt, c)
#define PROCESS_WAIT_EVENT_UNTIL(c) PROCESS_YIELD_UNTIL(c)
PT_TIELD_UNTIL在core/sys/pt.h中:
<pre name="code" class="cpp">#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)
我们的设计思想是,test_null抛出事件,test_event获取该事件后亮灯,编译烧写到板子进行一下测试:
烧写到cc2538cb节点后,contiki-main先将三个led灯fade,流水灯效果;然后咱们发现三个led灯点亮了
说明test_event的leds_on(LEDS_ALL);得到了执行,事件的测试OK;貌似现在也只是最基础的写法测试
在此大家可以再去想一下Contiki的thread模型,PROCESS_WAIT_EVENT_UNTIL到底干了什么?
Contiki是否支持咱们回溯事件的抛出者是谁?
有一个例程我们最好去学习参考,以便以后写出自己的应用,那就是er_timer;可以参考2530的代码或者cc2538cb目录下的blink_hello.c
#include "contiki.h"
#include "dev/leds.h"
#include <stdio.h> /* For printf() */
/*---------------------------------------------------------------------------*/
static struct etimer et_hello;
static struct etimer et_blink;
static uint16_t count;
static uint8_t blinks;
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
PROCESS(blink_process, "LED blink process");
AUTOSTART_PROCESSES(&hello_world_process, &blink_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
etimer_set(&et_hello, CLOCK_SECOND * 4);
count = 0;
while(1) {
PROCESS_WAIT_EVENT();
if(ev == PROCESS_EVENT_TIMER) {
printf("Sensor says #%u\n", count);
count++;
etimer_reset(&et_hello);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(blink_process, ev, data)
{
PROCESS_BEGIN();
blinks = 0;
while(1) {
etimer_set(&et_blink, CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
leds_off(LEDS_ALL);
leds_on(blinks & LEDS_ALL);
blinks++;
printf("Blink... (state %0.2X)\n", leds_get());
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
其中的代码可以自己去阅读,参考process阅读;我们看到两种事件等待的写法:
1;
PROCESS_WAIT_EVENT();
if(ev == PROCESS_EVENT_TIMER){
...
}
2;
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
PROCESS_THREAD(etimer_process, ev, data)
{
struct etimer *t, *u;
PROCESS_BEGIN();
timerlist = NULL;
while(1) {
PROCESS_YIELD();
if(ev == PROCESS_EVENT_EXITED) {
struct process *p = data;
while(timerlist != NULL && timerlist->p == p) {
timerlist = timerlist->next;
}
if(timerlist != NULL) {
t = timerlist;
while(t->next != NULL) {
if(t->next->p == p) {
t->next = t->next->next;
} else
t = t->next;
}
}
continue;
} else if(ev != PROCESS_EVENT_POLL) {
continue;
}
again:
u = NULL;
for(t = timerlist; t != NULL; t = t->next) {
if(timer_expired(&t->timer)) {
if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
/* Reset the process ID of the event timer, to signal that the
etimer has expired. This is later checked in the
etimer_expired() function. */
t->p = PROCESS_NONE;
if(u != NULL) {
u->next = t->next;
} else {
timerlist = t->next;
}
t->next = NULL;
update_time();
goto again;
} else {
etimer_request_poll();
}
}
u = t;
}
}
PROCESS_END();
}
貌似有了PROCESS_EVENT_TIMER的影子,大家可以自己去思考一下,do_poll和do_event
PROCESS_EVENT_TIMER的定义在core/sys/process.h中
#define PROCESS_EVENT_TIMER 0x88
在这里我们基本上能够总算接触到了Contiki的event,更多的自己去看代码理解,也许你需要一个sourceinghit来阅读代码,而不用像我一样一个一个文件打开查看;
虽然还是觉得有点模棱两可;只能说再此我并没有感觉到C语言的Contiki的优势!并不是我黑Contiki,我移植TinyOS很多地方也是参考的Contiki;现在能体会到的就是编写应用还是相对要复杂;可以自己结合前面几篇文档对照代码形成自我的理解;现在的作者也只是Contiki的菜鸟;但是应用神马的就得从基础做起;
不得不说的是cc2538dk平台本质是TI的SmartRF06EB板子,我的cc2538cb的代码(驱动部分)主要是参考他修改而来,3.0代码和2.7代码部分在底层变动较大;高手们可以互相印证,至少我比较喜欢2.7的启动文件的写法;

本文介绍了在Contiki3.0操作系统中处理事件的原理,通过对比TinyOS的事件机制,详细讲解了PROCESS_WAIT_EVENT_UNTIL和PT_YIELD_UNTIL的用法,并探讨了Contiki是否支持追溯事件源。同时,推荐学习er_timer例程以深入理解Contiki的事件处理。虽然作者认为Contiki的C语言实现可能较为复杂,但强调了从基础开始构建应用的重要性。
1551

被折叠的 条评论
为什么被折叠?



