TI OSAL之四(软件定时器链表)

OSAL中的每个任务的每个事件都可以拥有一个软件定时器,而这些定时器由一个链表统一组织起来。软件定时器的作用就是对 任务和相应的事件 周期执行提供支持。

一、定时器链表节点结构

typedef struct
{
  void   *next;	//指向下一个节点
  osalTime_t timeout;	//定时器定时时间
  uint16 event_flag;	//事件标志
  uint8  task_id;	//任务ID
  uint32 reloadTimeout;	//定时器重载的定时时间
} osalTimerRec_t;

二、创建定时器链表节点

//创建一个属于task_id和event_flag的定时器,如果已经存在则更新计数值
osalTimerRec_t * osalAddTimer( uint8 task_id, uint16 event_flag, uint32 timeout )
{
  osalTimerRec_t *newTimer;
  osalTimerRec_t *srchTimer;

  // Look for an existing timer first
  //寻找是否已经存在属于task_id和event_flag的定时器
  newTimer = osalFindTimer( task_id, event_flag );
  if ( newTimer )
  {
    // Timer is found - update it.
    //已经存在,则更新timeout
    newTimer->timeout.time32 = timeout;

    return ( newTimer );
  }
  else
  {
    // New Timer
    //不存在,创建一个新的定时器节点,挂到定时器链表尾部
    newTimer = osal_mem_alloc( sizeof( osalTimerRec_t ) );

    if ( newTimer )
    {
      // Fill in new timer
      newTimer->task_id = task_id;
      newTimer->event_flag = event_flag;
      newTimer->timeout.time32 = timeout;
      newTimer->next = (void *)NULL;
      newTimer->reloadTimeout = 0;

      // Does the timer list already exist
      if ( timerHead == NULL )
      {
        // Start task list
        //如果链表为空,即一个节点都没有,则将现在创建的节点作为链表头节点
        timerHead = newTimer;
      }
      else
      {
        // Add it to the end of the timer list
        srchTimer = timerHead;

        // Stop at the last record
        while ( srchTimer->next )
          srchTimer = srchTimer->next;

        // Add to the list
        srchTimer->next = newTimer;
      }

      return ( newTimer );
    }
    else
    {
      return ( (osalTimerRec_t *)NULL );
    }
  }
}

三、定时器的计数方式

//该函数在时钟管理的时间更新中(void osalTimeUpdate( void ))被调用,形参updateTime单位是ms
void osalTimerUpdate( uint32 updateTime )
{
  halIntState_t intState;
  osalTimerRec_t *srchTimer;
  osalTimerRec_t *prevTimer;

  osalTime_t timeUnion;
  timeUnion.time32 = updateTime;

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
  // Update the system time
  //记录系统时间,从上电开始算起
  osal_systemClock += updateTime;
  HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

  // Look for open timer slot
  if ( timerHead != NULL )
  {
    // Add it to the end of the timer list
    srchTimer = timerHead;
    prevTimer = (void *)NULL;

    // Look for open timer slot
    while ( srchTimer )
    {
      osalTimerRec_t *freeTimer = NULL;

      HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

      // To minimize time in this critical section, avoid 32-bit math
      //timeUnion是逝去的时间,如果该数值高24位为0,即小于256,则仅仅只需要比较低八位大小然后进行计算,一定程度上避免32位的计算,加快运算速度
      if ((timeUnion.time16[1] == 0) && (timeUnion.time8[1] == 0))
      {
        // If upper 24 bits are zero, check lower 8 bits for roll over
        //链表节点中的定时数值的低八位比timeUnion的低八位小,则直接低八位数相减即可,减少了运算时间
        if (srchTimer->timeout.time8[0] >= timeUnion.time8[0])
        {
          // 8-bit math
          srchTimer->timeout.time8[0] -= timeUnion.time8[0];
        }
        else
        {
          // 32-bit math
          if (srchTimer->timeout.time32 > timeUnion.time32)
          {
            srchTimer->timeout.time32 -= timeUnion.time32;
          }
          else
          {
            srchTimer->timeout.time32 = 0;
          }
        }
      }
      else
      {
          // 32-bit math
        if (srchTimer->timeout.time32 > timeUnion.time32)
        {
          srchTimer->timeout.time32 -= timeUnion.time32;
        }
        else
        {
          srchTimer->timeout.time32 = 0;
        }
      }

      // Check for reloading
      //检查是否需要重载定时器,即定时时间到后是否需要继续定时。
      if ( (srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 0) &&
           (srchTimer->reloadTimeout) && (srchTimer->event_flag) )
      {
        // Notify the task of a timeout
        //定时时间到,对task_id设置事件标志event_flag,等待在任务轮询中被处理
        osal_set_event( srchTimer->task_id, srchTimer->event_flag );

        // Reload the timer timeout value
        srchTimer->timeout.time32 = srchTimer->reloadTimeout;
      }

      // When timeout or delete (event_flag == 0)
      //定时时间到,或者事件标志为空,即没有事件,则将该节点独立出来,并释放空间
      if ( ((srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 0)) ||
            (srchTimer->event_flag == 0) )
      {
        // Take out of list
        if ( prevTimer == NULL )
        {
          timerHead = srchTimer->next;
        }
        else
        {
          prevTimer->next = srchTimer->next;
        }

        // Setup to free memory
        freeTimer = srchTimer;

        // Next
        srchTimer = srchTimer->next;
      }
      else
      {
        // Get next
        prevTimer = srchTimer;
        srchTimer = srchTimer->next;
      }

      HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.

      if ( freeTimer )
      {
      	//定时时间到
        if ( (freeTimer->timeout.time16[0] == 0) && (freeTimer->timeout.time16[1] == 0) )
        {
          //设置任务的事件标志位
          osal_set_event( freeTimer->task_id, freeTimer->event_flag );
        }
        osal_mem_free( freeTimer );
      }
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值