Contiki Ctimer模塊

Ctimer 提供和Etimer相似的功能,只是Ctimer是在一段時間後調用回調函數,沒有和特定進程相關聯。node

而Etimer是在一段時間後發送PROCESS_EVENT_TIMER事件給特定的進程。數據結構

 

1、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來實現鏈表的各類操做。spa

 

2、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函數剛啓動時,就得調用這個函數。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;
}

 

3、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.blog

相關文章
相關標籤/搜索