contiki中etimer定时器事件

时间:2022-04-09 00:16:08

etimer

1、定时器

Contiki 内核是基于事件驱动和Protothreads 机制,事件既可以是外部事件(比如按键,数据到达),也可以是内部事件(如时钟中断)。定时器的重要性不言而喻,Contiki 提供了 5 种定时器模型,即 timer(描述一段时间,以系统时钟嘀嗒数为单位)、stimer(描述一段时间,以秒为单位)、ctime(定时器到期,调用某函数,用于Rime 协议栈)、etime(定时器到期,触发一个事件)、rtimer(实时定时器,在一个精确的时间调用函数)。鉴于 etimer 在 Contiki 使用的广泛性,管理这些 etimer 由系统进程etimer_process 管理,本小节详细简单 etimer 相关技术细节。

(1)etimer 组织结构

etimer 作为一类特殊事件存在,也是跟进程绑定。除此之外,还需变量描述定时器属性,etimer 结构体定义如下:

structetimer

{

structtimer timer;     //包含起始时刻和间隔两成员变量

structetimer *next;    //指向下一个 etimer

structprocess *p;

};

成员变量 timer 用于描述定时器属性,包含起始时刻及间隔,将起始时刻与间隔相加与当前时钟对比,便可知道是否到期。变量 p 指向所绑定的进程(p 为 NULL则表示该定时器与所有进程绑定)。成员变量 next,指向下一个 etimer,系统所有etimer 被链接成一个链表,如下图所示:

contiki中etimer定时器事件

图1:timerlist结构图

(2)添加 etimer

定义一个 etimer 结构体,调用etimer_set 函数将 etimer 添加到 timerlist,函数

etimer_set流程图如下:

contiki中etimer定时器事件

图2:设置定时器事件的流程图

etimer_set首先设置 etimer 成员变量 timer 的值(由 timer_set 函数完成),即用当前时间初始化 start,并设置间隔 interval,接着调用 add_timer 函数,该函数首先将管理 etimer 系统进程 etimer_process 优先级提升,以便定时器时间到了可以得到更快的响应。接着确保欲加入的etimer不在timerlist中(通过遍历timerlist实现),若该etimer已经在etimer 链表,则无须将 etimer 加入链表,仅更新时间。否则将该 etimer 插入到 timerlist 链表头位置,并更新时间(update_time)。这里更新时间的意思是求出 etimer 链表中,还需要多长 next_expiration(全局静态变量)时间,就会有 etimer 到期。

(3)etimer 管理

Contiki 用一个系统进程etimer_process 管理所有 etimer 定时器。进程退出时,会向所有进程发送事件 PROCESS_EVENT_EXITED,当然也包括 etimer 系统进程etimer_process。当 etimer_process 拥有执行权的时候,便查看是否有相应的 etimer绑定到该进程,若有就删除这些 etimer。除此之外,etimer_process 还会处理到期的 etimer,etimer_process 的 thread 函数流程图如下:

contiki中etimer定时器事件

图3:etimer_process进程处理函数过程

etimer_process获得执行权时,若传递的是退出事件,遍历整个timerlist,将与该进程(通过参数data传递)相关的etimer从timerlist删除,而后转去处理所有到期的etimer。通过遍历整个etimer查看到期的etimer,若有到期的定时器事件,向绑定的进程触发事件 PROCESS_EVENT_TIMER,并将etimer的进程指针设为空(事件已加入事件队列,处理完毕),接着删除该etimer,求出下一次etimer到期时间,继续检查是否还有etimer到期。提升etimer_process 优先级,若接下来都没有etimer到期了,就退出。总之,遍历 timerlist,只要etimer到期,处理之后重头遍历整个链表,直到timerlist没有到期的 etimer就退出。

 

注意点:1、进程间的通信也是通过传递事件进行的

 

2、为了etimer的事件及时得到处理,在添加etimer之前,会把etimer的系统管理进程etimer-process提升为高优先级

 

3、当etimer到期后,会产生PROCESS_EVENT_TIMER事件

 

4、不管是在添加事件·进程还是定时器事件,第一步都是先遍历事件链表或是进程链表,以确保要添加的事件或是进程没有被重复添加