RT-Thread内核实现(五):定时器

整体思想
  • 前几章的线程延时是通过线程的remaining_tick属性来记录延时时间,在 SysTick 中断中扫描并更新每个线程remaining_tick,如果remaining_tick等于0,将该线程就绪,时间复杂度O(n);而定时器的策略是,每个线程都有自己的定时器,当线程需要延时时,先将线程挂起,然后启动内置的定时器,并将定时器挂到一个系统维护的全局的定时器列表rt_timer_list,每个节点代表了正在延时的线程的定时器,节点按照延时时间大小做升序排列,所以时基更新时只用扫描系统定时器列表的第一个节点timeout_tick,如果第一个定时器未到期,则后面的也不用判断,时间复杂度O(1)。定时器结构体如下,
    struct rt_timer
    {
         
        struct rt_object parent;                         /* 从 rt_object 继承 */
    
        rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];         /* 节点(跳跃表) */
    
        void (*timeout_func)(void *parameter);           /* 超时函数 */
        void            *parameter;                      /* 超时函数形参 */
    
        rt_tick_t        init_tick;                      /* 定时器实际需要延时的时间 */
        rt_tick_t        timeout_tick;                   /* 定时器实际超时时的系统节拍数 = rt_tick + init_tick */
    };
    typedef struct rt_timer *rt_timer_t;
    
  • 结构体成员 rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; 是数据结构跳跃表(skip list)的应用,一种以空间换时间的查找策略,后面有详细点的说明。
  • 结构体成员 void (*timeout_func)(void *parameter);定时器超时后调用该函数;
  • 结构体成员 rt_tick_t timeout_tick; 其值timeout_tick = rt_tick + init_tickrt_tick是该定时器启动时系统的tick数值,加上init_tick,表示定时器超时时,系统tick的数值。
  • 使用定时器要先初始化系统定时器列表。rt_system_timer_init();
  • 定时器初始化函数rt_timer_init(),在线程初始化时调用。
/**
 * 该函数用于初始化一个定时器,通常该函数用于初始化一个静态的定时器
 *
 * @param timer 静态定时器对象
 * @param name 定时器的名字
 * @param timeout 超时函数
 * @param parameter 超时函数形参
 * @param time 定时器的超时时间
 * @param flag 定时器的标志
 */
void rt_timer_init(rt_timer_t  timer,
                   const char *name,
                   void (*timeout)(void *parameter),
                   void       *parameter,
                   rt_tick_t   time,
                   rt_uint8_t  flag)
{
   
    /* 定时器对象初始化 */
    rt_object_init((rt_object_t)timer, RT_Object_Class_Timer, name);

    /* 定时器初始化 */
    _rt_timer_init(timer, timeout, parameter, time, flag);
}
启动定时器
  • rt_err_t rt_timer_start(rt_timer_t timer); 这里有个宏RT_TIMER_SKIP_LIST_LEVEL,表示定时器跳跃表等级,默认是1。这个函数会更新该定时器标志parent.flag和超时时间timeout_tick,然后在系统定时器列表中找到合适的位置插入该定时器节点。
/**
 * 启动定时器,并将定时器挂到定时器列表
 *
 * @param timer 将要启动的定时器
 *
 * @return 操作状态, RT_EOK on OK, -RT_ERROR on error
 */
rt_err_t rt_timer_start(rt_timer_t timer)
{
   
    unsigned int row_lvl = 0;
    rt_list_t *timer_list;
    register rt_base_t level;
    rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值