@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 }