Contiki学习笔记3:定时器
来源:互联网 发布:mac子弹头色号 编辑:程序博客网 时间:2024/05/19 04:05
把学习笔记2暂时删掉了。我的论文查重居然和自己的重复了,等确实不再查重了再恢复吧。论文里面分析了protothread机制,完成了contiki内核的移植,然后在内核移植的基础上完成了uIP协议栈的移植,实现了UDP通信^_^,以后在把这些移植过程详细描述。
上次翻译完process篇后,感觉不错。写论文时自己分析了阅读了一些源码,感觉其实contiki的学习一定要自己去阅读源代码,去展开宏,不要害怕。
今天参照wiki上的 contiki-timers 来说一下定时器部分。
定时器模式
众所周知,Contiki有五种定时器模式:timer,stimer,etimer,rtimer,ctimer.
timer定时us级别的时间,stimer定时s级别的时间。
etimer就是事件定时器,用来调度Contiki中的进程。在contiki进程中使用etimer可以使进程等待,从而系统可以调度其他进程。
ctiemr是回调定时器,定时一段时间后去再次调度函数,Rime协议栈里面会经常用来处理通信超时。感觉ctimer比较复杂。
rtimer就是实时定时器,他可以抢占任何进程,这样子使得实时任务可以准确调度。
时钟模式
该部分内容向我们展示了clock接口函数的作用,这部分函数在<clock.c>
中定义。以下结合cc2530的<clock.c>
。
clock_init()
函数就是初始化系统时钟,这里面cc2530使用的是sleep定时器来定时,中断时间也即定时时间是7.8ms。每次中断都会使全局变量count+1。
clock_time()
函数就是计时函数,直接返回count的值,这样就知道当前时间了,因为每次count+1都表示时间经过了7.8ms。
CLOCK_SECOND
宏就是一秒的宏,该宏值乘以7.8ms应该是1s,所以程序里面设置该宏值为128,这样,128 * 7.8 = 998.4≈1S。
clock_seconds()
函数返回以秒为单位的数值seconds.该全局变量在时钟中断函数中,每当count值为128时,都会加1,相当于每增加1都经过了1秒。
剩下两个API是用来阻塞CPU的,但不会放弃控制权,就是平常的延时函数,有的底层驱动可能会需要。分别是clock_delay()
和clock_wait()
函数。
以上就是<clock.c>
中的API,基于这些知识,我们自己就可以编写clock文件。
Timer库
Timer使用clock模式中的clock_time()
函数来获取当前系统时间。应用程序必须自行检查timer是否到期。
struct timer { clock_time_t start; clock_time_t interval;};
timer_set()
函数结构如下:
voidtimer_set(struct timer *t, clock_time_t interval){ t->interval = interval; t->start = clock_time();}
strar获取当前时间,interval存储间隔时间,这样就设置好了timer定时器。
而timer_restart()
函数就是t->start = clock_time();
重设start时间,而间隔不变,这样子必然导致时间轴发生变化,轴上的每一个时间节点都会移动位置。
区别函数是timer_reset()
函数,该函数就是t->start += t->interval;
相当于将当前时间移到下一个时间节点,并不会改变时间轴。 timer_expired()
函数定义如下:
inttimer_expired(struct timer *t){ clock_time_t diff = (clock_time() - t->start) + 1; return t->interval < diff;}
该函数通过判断间隔时间和diff这个时间差的大小,从而确定timer是否到期。比如,start为5,internal为8,那么可知下一个时间节点是13,那么当clock_time
返回12时,diff为8,所以函数返回0;当clock_time
返回13时,diff为9,所以函数返回1,表示时间到期,至于为什么要给diff额外+1,从而return变为不是返回diff >= t->interval
,注释里面说明,这样做是为了避免mspgcc报错。 timer_remaining()
函数返回距离下次到期时间还剩余的时间。
Stimer库
和timer库几乎完全一样,只不过将clock_time
换成了clock_seconds
.
Etimer库
etimer结构体先放在前面:
struct etimer { struct timer timer; struct etimer *next; struct process *p;};
etimer_set()
函数和timer中的作用差不多。函数定义如下:
voidetimer_set(struct etimer *et, clock_time_t interval){ timer_set(&et->timer, interval); add_timer(et);}
其中timer_set()
函数已经讲过,设置到期时间。 add_timer(et)
函数主要工作是:
- 将etimer_process进程优先级变高。
- 遍历etimer链表,如果需要添加的etimer不在链表中,那么将其加入到链表,并且使其process结构指针指向当前的进程,这是将etimer和进程绑定到一起了。
- 然后调用更新时间函数
update_time()
,该函数的作用就是通过遍历etimer链表,来统计下一个etimer发生还需要多长时间。
etimer_reset()
,etimer_restart()
函数和timer中的功能差不多,不再赘述。 etimer_stop()
函数就是将目标事件定时器移出链表。 etimer_expired()
来判断etimer是否到期,到期的话会在etimer_process
进程中将etimer中的进程指针p设置为PROCESS_NONE。
看一个1s调用一次的例程:
#include "sys/etimer.h" PROCESS_THREAD(example_process, ev, data) { static struct etimer et; PROCESS_BEGIN(); /* Delay 1 second */ etimer_set(&et, CLOCK_SECOND); while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); /* Reset the etimer to trig again in 1 second */ etimer_reset(&et); /* ... */ } PROCESS_END(); }
Ctimer库
ctimer结构如下:
struct ctimer { struct ctimer *next; struct etimer etimer; struct process *p; void (*f)(void *); void *ptr;};
可以看出,这几个定时器都是继承的关系,ctimer->etimer->timer。结构体中f为一个指向函数的指针,就是用来调用回调函数的。
ctimer函数库和etimer基本一样,除了ctimer_set()
函数。
该函数声明如下:
voidctimer_set(struct ctimer *c, clock_time_t t, void (*f)(void *), void *ptr)
介绍两个宏,PROCESS_CONTEXT_BEGIN
和PROCESS_CONTEXT_END
。这两个宏搭配使用,就是用来保存当前process_current指针的,用完后再将其恢复。
一个例子:
#include "sys/ctimer.h" static struct ctimer timer; static void callback(void *ptr) { ctimer_reset(&timer); /* ... */ } void init(void) { ctimer_set(&timer, CLOCK_SECOND, callback, NULL); }
每秒调用一次callback函数。上述实例展示了使用方法。
Rtimer库
Rtimer没有使用clock模式,使用的是自己的定时器,这里指的是cc2530中的定时器T1. RTIMER_NOW()
宏用来取得当前时间,RTIMER_SECOND
用来定义每秒的滴答数.
其他是移植时必须实现的函数接口,感谢前人的帮忙,这些接口都已经做好了。
就这样吧,写不动了。
- Contiki学习笔记3:定时器
- Contiki学习笔记
- Contiki学习笔记:目录
- Contiki学习笔记:目录
- Contiki学习笔记
- contiki学习笔记之hello_world
- contiki学习笔记 clock部分
- contiki学习笔记 etimer部分
- contiki学习笔记之leds
- contiki学习笔记 spi部分解析
- contiki 学习笔记 leds实现部分
- Contiki学习笔记之时钟初始化
- Contiki学习笔记之时钟初始化
- contiki中etimer定时器事件
- contiki学习笔记——IAR工程合集
- Contiki学习笔记——RPL协议详解
- contiki学习笔记-UDP-Client原厂代码分析
- contiki学习笔记-udp-server.c文件详细的解析
- 阅读郭林《第一行代码》的笔记——第4章 手机平板要兼顾,探究碎片
- SQL
- IOS 多线程技术
- 线性表--数组描述(封装类)
- oralce横表转纵表示例
- Contiki学习笔记3:定时器
- git-canal介绍
- Hibernate分页查询的实现
- Java中线程局部变量ThreadLocal使用教程及源码分析
- sql的临时表使用小结
- STL之set和multiset总结
- Ural 1658 Sum of Digits
- jsp中的9个内置对象
- 【CodeForces】96B - Lucky Numbers (easy)(模拟,字典序全排列)