|
对rt-Timer的理解,
timer初始化时,会建立一个void rt_system_timer_init()中创建一个只有头的环型链表。
添创建使用新的timer时,会调用rt_timer_start(),在调用他之前,务必调用control来设置好要延时的tick数。 在rt_timer_start中会计算出timeout_tick的值,由于假定要延时的tick的最大值不能超过rt_time_max/2。 所以当timeout_tick-current_tick的小于rt_time_max/2; timer还未到,否则timer已定时时间已到。
在rt_timer_start中对Timer的环型链表中,按升序插入到链表中。由于初始化链表是空的,所以没有排序操作,只是做了升序插入。
rt_err_t rt_timer_start(rt_timer_t timer)
{
struct rt_timer* t;
register rt_base_t level;
rt_list_t *n, *timer_list;
/* timer check */
RT_ASSERT(timer != RT_NULL);
if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) return -RT_ERROR; //已激活的Timer
#ifdef RT_USING_HOOK
if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(timer->parent));
#endif
/* disable interrupt */
level = rt_hw_interrupt_disable();
/* get timeout tick, the max timeout tick shall not great than RT_TICK_MAX/2 */
RT_ASSERT(timer->init_tick < RT_TICK_MAX/2);
timer->timeout_tick = rt_tick_get() + timer->init_tick; //计算当前timeout到达时的tick
#ifdef RT_USING_TIMER_SOFT
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
{
/* insert timer to soft timer list */
timer_list = &rt_soft_timer_list;
}
else
#endif
{
/* insert timer to system timer list */
timer_list = &rt_timer_list;
}
//环型链表的遍历
for (n = timer_list->next; n != timer_list; n = n->next)
{
//这句话相当于timer_list[n]
t = rt_list_entry(n, struct rt_timer, list);
/*
* It supposes that the new tick shall less than the half duration of tick max.
*/
//这个为什么可以做到升序呢,首先是延时的最大值是RT_TICK_MAX/2。那么timeout_tick与current_tick的最大差值就是RT_TICK_MAX/2。
//那么两个timeout_tick比较,也是同样的,当他们的差值<>RT_TICK_MAX/2。就知道其先后到达顺序
//了。如下面这个语句,t肯定是先于同时timer到达timeout。
//所以要把他插入到timer之前。以达到升序。由此我们可以知道为什么会出现两个一样的进程为什么会出现, 1 2 2 1 1 2 2的情况呢,因为我们是先跑 1号线程,将1号线程的插入到timerlist的第一个元素。马上进行2号线程,并插入2号线程的timer. 这样的话,由于current_tick未变,而导致 2号线程的timer插入时,会插入到1号线程和timer前面,因为他们两的timeout_tick是相等。相减值为0。解决办法是可以再加一个判断。
if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX/2)
{
rt_list_insert_before(n, &(timer->list));
break;
}
}
//这里结果是根本没有小于他的timout,所以将其插入到最后。
/* no found suitable position in timer list */
if (n == timer_list)
{
rt_list_insert_before(n, &(timer->list));
}
timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
return -RT_EOK;
}
rt_timer_check这个是通过systick中断来调用的。
void rt_timer_check(void)
{
struct rt_timer *t;
rt_tick_t current_tick;
register rt_base_t level;
#ifdef RT_TIMER_DEBUG
rt_kprintf("timer check enter\n");
#endif
取当前tick
current_tick = rt_tick_get();
/* disable interrupt */
level = rt_hw_interrupt_disable();
//判断是否有定时中断
while (!rt_list_isempty(&rt_timer_list))
{
//取rt_timer_list[n]
t = rt_list_entry(rt_timer_list.next, struct rt_timer, list);
/*
* It supposes that the new tick shall less than the half duration of tick max.
*/
//这个比较请注意看rt_timer_start的比较说明,其实是同样的方法实现的。
if ((current_tick - t->timeout_tick) < RT_TICK_MAX/2)
{
#ifdef RT_USING_HOOK
if (rt_timer_timeout_hook != RT_NULL) rt_timer_timeout_hook(t);
#endif
/* remove timer from timer list firstly */
rt_list_remove(&(t->list));
/* call timeout */
t->timeout_func(t->parameter);
/* re-get tick */
current_tick = rt_tick_get();
#ifdef RT_TIMER_DEBUG
rt_kprintf("current tick: %d\n", current_tick);
#endif
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;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
/* increase soft timer tick */
#ifdef RT_USING_TIMER_SOFT
rt_soft_timer_tick_increase ( );
#endif
#ifdef RT_TIMER_DEBUG
rt_kprintf("timer check leave\n");
#endif
}