Ctimer 提供和Etimer类似的功能,只是Ctimer是在一段时间后调用回调函数,没有和特定进程相关联。
而Etimer是在一段时间后发送PROCESS_EVENT_TIMER事件给特定的进程。
一、Ctimer数据结构
struct ctimer { struct ctimer *next;//使用LIST时,要求第一个一定是指向本类型的指针 struct etimer etimer;//etimer作为底层通知 struct process *p;//对应的process void (*f)(void *);//回调函数 void *ptr;//回调函数数据 };
全局变量ctimer_list:
LIST(ctimer_list);
采用库LIST来实现链表的各种操作。
二、Ctimer API
void ctimer_init(void);//Initialize the callback timer library. void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr); // Start the timer. void ctimer_reset(struct ctimer *t); // Restart the timer from the previous expiration time. void ctimer_restart(struct ctimer *t); // Restart the timer from current time. void ctimer_stop(struct ctimer *t); // Stop the timer. int ctimer_expired(struct ctimer *t); // Check if the timer has expired.
这些API基本和之前讨论的差不多,只是数据结构更改了。
这里多了一个ctimer_init,在main函数刚启动时,就得调用这个函数。
/** * rief Initialize the callback timer library. * * This function initializes the callback timer library and * should be called from the system boot up code. */
以下是各个函数的源代码:
void ctimer_init(void) { initialized = 0;//初始化为0 list_init(ctimer_list);//ctimer_list初始化 process_start(&ctimer_process, NULL);//启动ctimer_process进程 }
void ctimer_set(struct ctimer *c, clock_time_t t, void (*f)(void *), void *ptr) { PRINTF("ctimer_set %p %u ", c, (unsigned)t); c->p = PROCESS_CURRENT();//设置对应的p为process_current c->f = f;//设置回调函数 c->ptr = ptr;//设置回调函数的参数 if(initialized) {//如果ctimer_process初始化完成 PROCESS_CONTEXT_BEGIN(&ctimer_process);//更改process_current为ctimer_process,因为etimer需要通知ctimer_process而不是调用ctimer_set的process etimer_set(&c->etimer, t);//设置etimer,底层通知机制 PROCESS_CONTEXT_END(&ctimer_process);//恢复process_current } else {//如果还没,则先设置etimer.timer.iinterval //等ctimer_process初始化时,会etimer_set这些 c->etimer.timer.interval = t; } list_remove(ctimer_list, c);//先从list中移出 list_add(ctimer_list, c);//添加到list的尾部 }
void ctimer_reset(struct ctimer *c) { if(initialized) {//ctimer_process初始化完成 PROCESS_CONTEXT_BEGIN(&ctimer_process);//更改process_current etimer_reset(&c->etimer); PROCESS_CONTEXT_END(&ctimer_process);//恢复 } list_remove(ctimer_list, c); list_add(ctimer_list, c); }
void ctimer_restart(struct ctimer *c) { if(initialized) { PROCESS_CONTEXT_BEGIN(&ctimer_process); etimer_restart(&c->etimer); PROCESS_CONTEXT_END(&ctimer_process); } list_remove(ctimer_list, c); list_add(ctimer_list, c); }
void ctimer_stop(struct ctimer *c) { if(initialized) { etimer_stop(&c->etimer); } else { c->etimer.next = NULL; c->etimer.p = PROCESS_NONE; } list_remove(ctimer_list, c); }
int ctimer_expired(struct ctimer *c) { struct ctimer *t; if(initialized) {//如果初始化完 return etimer_expired(&c->etimer);//判断是否处理过? } //还没初始化完,则判断是否在list中,是,返回0 //没在list中,返回1 for(t = list_head(ctimer_list); t != NULL; t = t->next) { if(t == c) { return 0; } } return 1; }
三、ctimer_process
PROCESS(ctimer_process, "Ctimer process"); PROCESS_THREAD(ctimer_process, ev, data) { struct ctimer *c; PROCESS_BEGIN(); //处理在initialized之前,就ctimer_set的ctimer for(c = list_head(ctimer_list); c != NULL; c = c->next) { etimer_set(&c->etimer, c->etimer.timer.interval); } initialized = 1;//标志ctimer_process已经初始化完成了 while(1) { //等待PROCESS_EVENT_TIMER事件 //ctimer到期时,是由etimer触发,发送一个PROCESS_EVENT_TIMER事件给ctimer_process //ctimer_process再进行处理(调用相应的回调函数) PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_TIMER); for(c = list_head(ctimer_list); c != NULL; c = c->next) {//遍历 if(&c->etimer == data) {//etimer匹配 list_remove(ctimer_list, c);//从ctimer_list中移出 PROCESS_CONTEXT_BEGIN(c->p);//改变当前进程process_current为c->p,因为要开始调用回调函数了 if(c->f != NULL) {//回调函数不空 #if WITH_GUARD if (memcmp(ctimer_token, &node_UID[4], 4) == 0) c->f(c->ptr); #else c->f(c->ptr);//调用 #endif } PROCESS_CONTEXT_END(c->p);//恢复当前进程process_current break;//跳出循环 } } } PROCESS_END(); }
The Ctimer library cannot safely be used from interrupts.