@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)
具体代码:
/**
* This function will check timer list, if a timeout event happens, the
* corresponding timeout function will be invoked.
*/
void rt_soft_timer_check(void)
{
rt_tick_t current_tick;
rt_list_t *n;
struct rt_timer *t; RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n")); current_tick = rt_tick_get(); /* lock scheduler */
rt_enter_critical(); for (n = rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - ].next;
n != &(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - ]);)
{
t = rt_list_entry(n, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - ]); /*
* It supposes that the new tick shall less than the half duration of
* tick max.
*/
if ((current_tick - t->timeout_tick) < RT_TICK_MAX / )
{
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t)); /* move node to the next */
n = n->next; /* remove timer from timer list firstly */
_rt_timer_remove(t); /* not lock scheduler when performing timeout function */
rt_exit_critical();
/* call timeout function */
t->timeout_func(t->parameter); /* re-get tick */
current_tick = rt_tick_get(); RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick)); /* lock scheduler */
rt_enter_critical(); if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
/* start it */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
else
{
/* stop timer */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
}
}
else break; /* not check anymore */
} /* unlock scheduler */
rt_exit_critical(); RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
} /* system timer thread entry */
static void rt_thread_timer_entry(void *parameter)
{
rt_tick_t next_timeout; while ()
{
/* get the next timeout tick */
next_timeout = rt_timer_list_next_timeout(rt_soft_timer_list);
if (next_timeout == RT_TICK_MAX)
{
/* no software timer exist, suspend self. */
rt_thread_suspend(rt_thread_self());
rt_schedule();
}
else
{
rt_tick_t current_tick; /* get current tick */
current_tick = rt_tick_get(); if ((next_timeout - current_tick) < RT_TICK_MAX / )
{
/* get the delta timeout tick */
next_timeout = next_timeout - current_tick;
rt_thread_delay(next_timeout);
}
} /* check software timer */
rt_soft_timer_check();
}
}