当前位置: 首页 > news >正文

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函数刚启动时,就得调用这个函数。

/**
* \brief 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\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;
}

 

三、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.

转载于:https://www.cnblogs.com/songdechiu/p/5956932.html

相关文章:

  • 人生的抉择
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • phalcon模型查询几种方法
  • 在DotNetNuke中通过修改ascx文件源码自定义界面
  • day10---paramiko ssh ftp
  • ArcSDE9.2
  • 如何删除mspcidrv.sys病毒
  • js循环生成多个easyui datagrid数据网格时,初始化表格
  • 双绞线 (Twist-Pair)
  • jquery cookie插件轻松实现切换背景颜色
  • 我儿小乐乐
  • asp.net中使用modal window的问题
  • Python--命令行参数解析Demo
  • 股票基本名词概念
  • CSS3动画特效——transform详解
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • AWS实战 - 利用IAM对S3做访问控制
  • CSS魔法堂:Absolute Positioning就这个样
  • eclipse的离线汉化
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • Java新版本的开发已正式进入轨道,版本号18.3
  • KMP算法及优化
  • Redis在Web项目中的应用与实践
  • scrapy学习之路4(itemloder的使用)
  • vue数据传递--我有特殊的实现技巧
  • 从tcpdump抓包看TCP/IP协议
  • 对象引论
  • 分布式熔断降级平台aegis
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 说说动画卡顿的解决方案
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • ​第20课 在Android Native开发中加入新的C++类
  • ​如何在iOS手机上查看应用日志
  • # Java NIO(一)FileChannel
  • (AngularJS)Angular 控制器之间通信初探
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (二)WCF的Binding模型
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (过滤器)Filter和(监听器)listener
  • .dwp和.webpart的区别
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • @synthesize和@dynamic分别有什么作用?
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • @vue/cli脚手架
  • [BUG] Authentication Error
  • [BUUCTF 2018]Online Tool(特详解)
  • [CF226E]Noble Knight's Path
  • [CSS]浮动
  • [HackMyVM]靶场 Quick3