rt-thread中软件定时器组件超时界限的一点理解

时间:2022-07-04 23:38:13

@2019-01-15

【小记】

对 rt-thread 中的软件定时器组件中超时界限的一点理解

rt_thread_timer_entry(void *parameter)函数中if ((next_timeout - current_tick) < RT_TICK_MAX / 2)  --- 条件1
rt_soft_timer_check(void)函数中if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)        --- 条件2

举个特例:

  假定某时刻 

  next_timeout = 0xFFFFFF00;
  current_tick = 0x100;
  next_timeout - current_tick = 0xFFFFFE00  <  RT_TICK_MAX / 2 = 0x7FFFFFFF    条件1不成立
  current_tick - t->timeout_tick = 0x200   <  RT_TICK_MAX / 2 = 0x7FFFFFFF    条件2成立  (实际比0x200d大一点,因current_tick在增长)

  这样则会出现定时器错误的定时到达而调用其回调函数,实际定时器计时还远未到

 为避免以上情况出现,在函数 rt_timer_start(rt_timer_t timer) 中断言语句 RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2) 规定了延时长度(即MSB为0)

具体代码:

  1 /**
  2  * This function will check timer list, if a timeout event happens, the
  3  * corresponding timeout function will be invoked.
  4  */
  5 void rt_soft_timer_check(void)
  6 {
  7     rt_tick_t current_tick;
  8     rt_list_t *n;
  9     struct rt_timer *t;
 10 
 11     RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
 12 
 13     current_tick = rt_tick_get();
 14 
 15     /* lock scheduler */
 16     rt_enter_critical();
 17 
 18     for (n = rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next;
 19          n != &(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]);)
 20     {
 21         t = rt_list_entry(n, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
 22 
 23         /*
 24          * It supposes that the new tick shall less than the half duration of
 25          * tick max.
 26          */
 27         if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
 28         {
 29             RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
 30 
 31             /* move node to the next */
 32             n = n->next;
 33 
 34             /* remove timer from timer list firstly */
 35             _rt_timer_remove(t);
 36 
 37             /* not lock scheduler when performing timeout function */
 38             rt_exit_critical();
 39             /* call timeout function */
 40             t->timeout_func(t->parameter);
 41 
 42             /* re-get tick */
 43             current_tick = rt_tick_get();
 44 
 45             RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
 46             RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
 47 
 48             /* lock scheduler */
 49             rt_enter_critical();
 50 
 51             if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
 52                 (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
 53             {
 54                 /* start it */
 55                 t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
 56                 rt_timer_start(t);
 57             }
 58             else
 59             {
 60                 /* stop timer */
 61                 t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
 62             }
 63         }
 64         else break; /* not check anymore */
 65     }
 66 
 67     /* unlock scheduler */
 68     rt_exit_critical();
 69 
 70     RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
 71 }
 72 
 73 /* system timer thread entry */
 74 static void rt_thread_timer_entry(void *parameter)
 75 {
 76     rt_tick_t next_timeout;
 77 
 78     while (1)
 79     {
 80         /* get the next timeout tick */
 81         next_timeout = rt_timer_list_next_timeout(rt_soft_timer_list);
 82         if (next_timeout == RT_TICK_MAX)
 83         {
 84             /* no software timer exist, suspend self. */
 85             rt_thread_suspend(rt_thread_self());
 86             rt_schedule();
 87         }
 88         else
 89         {
 90             rt_tick_t current_tick;
 91 
 92             /* get current tick */
 93             current_tick = rt_tick_get();
 94 
 95             if ((next_timeout - current_tick) < RT_TICK_MAX / 2)
 96             {
 97                 /* get the delta timeout tick */
 98                 next_timeout = next_timeout - current_tick;
 99                 rt_thread_delay(next_timeout);
100             }
101         }
102 
103         /* check software timer */
104         rt_soft_timer_check();
105     }
106 }