delin17的笔记 https://passport2.21ic.com/?467504 [收藏] [复制] [RSS]

日志

rt-thread的Timer的学习

已有 2093 次阅读2011-12-30 05:48 |系统分类:ARM

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


 


 


 


 


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)