Ctimer 提供和Etimer相似的功能,只是Ctimer是在一段時間後調用回調函數,沒有和特定進程相關聯。node
而Etimer是在一段時間後發送PROCESS_EVENT_TIMER事件給特定的進程。數據結構
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來實現鏈表的各類操做。spa
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函數剛啓動時,就得調用這個函數。rest
/** * \brief Initialize the callback timer library. * * This function initializes the callback timer library and * should be called from the system boot up code. */
如下是各個函數的源代碼: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\n", 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; }
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.blog