导读:
本文通过分析Contiki的源码,梳理Contiki的process-event模型中的event机制。
通过前文的阐述我们知道了Contiki的事件处理机制,本文梳理Contiki的事件产生机制。
Contiki中的事件产生方式主要有2种:
etimer定时器到期产生事件调用内核函数process_post_synch或者process_post产生事件
1)etimer定时器到期事件
etimer定时器是Contiki中5个定时器的一种,也可以说是最重要的一种,它通过硬件定时器,产生ms级的系统时基。在Contiki中,存在着一个etimer的链表,用来链接所有etimer。并设置了接下来的最近一次的某个etimer的到期时间,这样当某个etimer到期,可以迅速得到响应。每个etimer在创建时都会绑定某个process,在etimer到期时,将会产生event,进而Contiki去执行到期etimer绑定的process。给出etimer的类型定义。
struct etimer {
struct timer timer; //基本timer
struct etimer *next; //链接域
struct process *p; //etimer绑定的process
};
etimer使用了Contiki中5个定时器的最基本定时器struct timer。struct timer只提供了基本的tick计数,到期检查等功能。
我们先给出etimer的典型用法,再去剖析etimer的工作原理。下面以看门狗为例,设置etimer每2s执行一次喂狗任务。
PROCESS(dog,"dog");//看门狗任务
PROCESS_THREAD(dog, ev, dataa)
{
static struct etimer et;
PROCESS_BEGIN();
etimer_set(&et,CLOCK_SECOND*2);//初始化etimer,并设置延时为2s
while(1)
{
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));//等待etimer过期
spin_watchdog_clear();//喂狗
etimer_restart(&et);//重启etimer
}
PROCESS_END();
}
上面这段看门狗process函数,使用了etimer的3个函数etimer_set,etimer_expired,etimer_restart。我们接下来分析这3个函数。
etimer_set
void
etimer_set(struct etimer *et, clock_time_t interval)
{
timer_set(&et->timer, interval);
add_timer(et);
}
函数设置了etimer中的struct timer的参数,在Contiki中,用开始时间+时间间隔>=到期时间的方式,判定某个内核定时器是否到期。而时间间隔就是interval,我们设置这个值时,一般是以CLOCK_SECOND宏为基准的,因为CLOCK_SECOND宏代表了内核每CLOCK_SECOND个间隔是1s。重点看add_timer。
static void
add_timer(struct etimer *timer)
{