• Contiki Ctimer模块


    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.

  • 相关阅读:
    (转载)Android mac 真机调试
    Google Map SDK for iOS
    autolayout under navigation bar
    Xamarin Mono For Android、Monotouch 安装
    不错的ORM调试查看SQL插件
    在Windows 8.1系统上配置免安装版mysql-5.6.21-winx64
    VS2013 EF6连接MySql
    安卓离线SDK Windows版 资源包下载地址全集
    WndProc函数参数列表
    反射创建对象
  • 原文地址:https://www.cnblogs.com/songdechiu/p/5956932.html
Copyright © 2020-2023  润新知