定时器管理

定时器,是指从指定的时刻开始,经过一个指定时间,然后触发一个事件,类似定个时间提醒第二天能够按时起床。定时器有硬件定时器和软件定时器之分:

  • 硬件定时器是芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。

  • 软件定时器是由操作系统提供的一类系统接口(函数),它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。

在操作系统中,通常软件定时器以系统节拍(tick)为单位。节拍长度指的是周期性硬件定时器两次中断间的间隔时间长度。这个周期性硬件定时器也称之为操作系统时钟。软件定时器以这个节拍时间长度为单位,数值必须是这个节拍的整数倍,例如节拍是10ms,那么上层软件定时器只能是10ms,20ms,100ms等,而不能取值为15ms。由于节拍定义了系统中定时器能够分辨的精确度,系统可以根据实际系统CPU的处理能力和实时性需求设置合适的数值,tick值设置越小,精度越高,但是系统开销也将越大(在1秒中系统用于处理时钟中断的次数也就越多)。RT-Thread的定时器也基于类似的系统节拍,提供了基于节拍整数倍的定时能力。

RT-Thread的定时器提供两类定时器机制:第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动的停止定时器否则将永远持续执行下去。

下面以一个实际部分代码来说明RT-Thread软件定时器的基本工作原理。在RT-Thread定时器模块中维护着两个重要的全局变量:

  • 当前系统经过的tick时间rt_tick(当硬件定时器中断来临时,它将加1);
  • 定时器链表rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到rt_timer_list链表中。
    定时器链表

如上图所示,系统当前tick值为20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为50个tick的Timer1、100个tick的Timer2和500个tick的Timer3,这三个定时器分别加上系统当前时间rt_tick = 20,从小到大排序链接在rt_timer_list链表中,形成如上图所示的定时器链表结构。

而rt_tick随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick变量会加1), 50个tick以后, rt_tick从20增长到70,与Timer1的timeout值相等, 这时会触发与Timer1定时器相关联的超时函数,同时将Timer1从rt_timer_list链表上删除。同理,100个tick和500个tick过去后,与Timer2和Timer3定时器相关联的超时函数会被触发,接着将Time2和Timer3定时器从rt_timer_list链表中删除。

如果系统当前定时器状态在10个tick以后(rt_tick = 30)有一个任务新创建了一个tick值为300的Timer4定时器,由于Timer4定时器的timeout = rt_tick + 300 =330, 因此它将被插入到Timer2和Timer3定时器中间,形成如图3-2所示链表结构:

插入Timer #4后的示意图