本帖最后由 dvd1478 于 2016-1-16 08:20 编辑
contiki-2.5\core\sys\etimer.c
1 etimer结构体
etimer提供一种timer机制产生timed events,可以理解成etimer是Contiki特殊的一种事件。当etimer到期时,会给相应的进程传递事件PROCESS_EVENT_TIMER,从而使该进程启动 。etimer结构体源码如下: struct etimer
{
struct timer timer;
struct etimer *next;
struct process *p;
};
| struct etimer 继承了struct timer
/*****timer定义*****/
struct timer
{
clock_time_t start;
clock_time_t interval;
};
typedef unsigned int clock_time_t;
|
timer仅包含起始时刻和间隔时间,所以timer只记录到期时间。通过比较到到期时间和新的当前时钟,从而判断该定时器是不是到期。 1.2 timerlist 全局静态变量timerlist,指向系统第一个etimer,图示timerlist如下: static struct etimer *timerlist;//etimer 链表队列
|
具体的操作如下:
如下图显示了一个etimer定时器插入前、插入后和超时调用后,这三种情况下etimer链表数据结构。很容易看出,当一个etimer超时并处理后它将从链表中摘除,如果用户需要再次使用该定时器则需要继续调用etimer_set()函数。
Etimer的调用时序如下图(etimer调用时序)所示,call_process调用etimer_set()添加一个etimer定时器后,经过interval时长该定时器超时,这里etimer_process向call_process发送超时消息,当call_process接收到超时消息后执行对应的逻辑动作
2、etimer 代码分析 Functions called from application programs
| void | etimer_set (struct etimer *et, clock_time_t interval) |
| Set an event timer.
| void | etimer_reset (struct etimer *et) |
| Reset an event timer with the same interval as was previously set.
| void | etimer_restart (struct etimer *et) |
| Restart an event timer from the current point in time.
| void | etimer_adjust (struct etimer *et, int td) |
| Adjust the expiration time for an event timer.
| clock_time_t | etimer_expiration_time (struct etimer *et) |
| Get the expiration time for the event timer.
| clock_time_t | etimer_start_time (struct etimer *et) |
| Get the start time for the event timer.
| int | etimer_expired (struct etimer *et) |
| Check if an event timer has expired.
| void | etimer_stop (struct etimer *et) |
| Stop a pending event timer.
|
| Functions called from timer interrupts, by the system
| void | etimer_request_poll (void) |
| Make the event timer aware that the clock has changed.
| int | etimer_pending (void) |
| Check if there are any non-expired event timers.
| clock_time_t | etimer_next_expiration_time (void) |
| Get next event timer expiration time. |
在
[EVAL-WSN]操作系统篇——Contiki最简单的实例
https://www.cirmall.com/bbs/forum.php?mod=viewthread&tid=46018&fromuid=23447
在process_init初始化后就调用process_start(&etimer_process, NULL);//设置etimer_process 进程
但关键的分析etimer_process 这个进程,就能明白其原理- <span style="background-color: white;">/*---------------------------------------------------------------------------*/
- PROCESS_THREAD(etimer_process, ev, data)
- {
- /*
- 进程退出时,需向所有进程(当然也包括etimer_process)发送事件PROCESS_EVENT_EXITED。
- etimer_process收到该事件,就会遍历timerlist,并把与该退出进程相关的etimer从timerlist删除。
- 紧接着,遍历timerlist,检查etimer是否有到期的,凡有timer到期就把事件PROCESS_EVENT_TIMER
- 加入到事件队列中,并将该etimer成员变量p指向PROCESS_NONE。在这里,PROCESS_NONE用于标识
- 该etimer是否到期,即由etimer_expired函数根据etimer的p是否指向PROCESS_NONE来判断该etimer是否到期
- */
- struct etimer *t, *u;
-
- PROCESS_BEGIN();
-
- timerlist = NULL;
-
- while(1) {
- PROCESS_YIELD();/*进程主动让出执行权 : 首次运行,或者已经处理所有工作*/
- /* 进程退出时,需向所有进程(当然也包括etimer_process)发送事件PROCESS_EVENT_EXITED。
- etimer_process收到该事件,就会遍历timerlist,并把与该退出进程相关的etimer从timerlist删除 */
- if(ev == PROCESS_EVENT_EXITED) {
- struct process *p = data;/* 此时通过data传递将要退出的进程,data是void *类型 */
-
- /* 遍历timerlist,查找是否有etimer绑定该退出进程 */
- while(timerlist != NULL && timerlist->p == p) {
- timerlist = timerlist->next;
- }
-
- /* 有etimer绑定该退出进程,将etimer从timerlist删除 */
- if(timerlist != NULL) {
- t = timerlist;
- while(t->next != NULL) {
- if(t->next->p == p) {
- t->next = t->next->next;
- } else
- t = t->next;
- }
- }
- continue;/* 删除所有与退出进程绑定的etimer */
- } else if(ev != PROCESS_EVENT_POLL) {
- continue;
- }
-
- again:
-
- u = NULL;
- /*遍历timerlist*/
- for(t = timerlist; t != NULL; t = t->next) {
- if(timer_expired(&t->timer)) {/* 检查该etimer的timer是不是到期,返回1表示过期 */
- if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
- /* 把事件PROCESS_EVENT_TIMER加入到事件队列 */
- /* 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; /*如果etimer的p指向的是PROCESS_NONE,则表示该etimer已到期。用于后续etimer_expired()函数判断该etimer是否到期,etimer_expired() */
- if(u != NULL) {
- u->next = t->next;
- } else {
- timerlist = t->next;
- }
- t->next = NULL;
- update_time();/* 求出下一个到期时间next_expiration (全局静态变量),即还有next_expiration时间,就有timer到期 */
- goto again;
- } else {
- etimer_request_poll(); /* 若加入事件PROCESS_EVENT_TIMER出错(可能是事件队列已满),执行etimer_request_poll(),即process_poll(&etimer_process),使其有更高的优先级 */
- }
- }
- u = t;
- }
-
- }
-
- PROCESS_END();
- }</span>
复制代码 |