WSF操作系统抽象层学习笔记(四)---定时器

定时器

定时器的实现方式:

使用OS自带的定时器模块,建立一个定时器,定时间隔为自定义TICKS,定时器的回调函数中设置定时器到时的事件。

定时器模块定义了一个定时器的链表,用于定时器的管理。

操作定时器管理链表的过程需要关闭任务调度。

注意:OS本身定时器存在一定的误差,通过OS来实现的定时器也是有误差的。误差的大小跟WSF自定义的ticks大小有关。

定时器的管理结构

//定时器对象管理结构
typedef struct wsfTimer_tag
{
  struct wsfTimer_tag *pNext;             //指向队列中下一个定时器节点
  wsfTimerTicks_t     ticks;              //定时器超时ticks
  wsfHandlerId_t      handlerId;          //定时器超时,处理函数句柄
  bool_t              isStarted;          //定时器是否启动
  wsfMsgHdr_t         msg;                //应用定义的定时器参数
} wsfTimer_t;

定时器的初始化

  1. 初始化定时器管理链表
  2. 创建WSF驱动定时器,用于周期性发送事件处理定时器的超时。
/* 系统OS定时器回调函数,主Task发送定时器到时事件 */
static void WsfTimer_handler(TimerHandle_t xTimer)
{
  WsfTaskSetReady(0, WSF_TIMER_EVENT);
}

/* WSF定时器基础初始化 */
void WsfTimerInit(void)
{
  /* 定时器管理链表初始化 */
  WSF_QUEUE_INIT(&wsfTimerTimerQueue);

  if(xWsfTimer == NULL)
  {
    /* 使用OS相关接口创建一个定时器,此处使用的是freeRtos的接口 */
    xWsfTimer = xTimerCreate("WSF Timer", pdMS_TO_TICKS(WSF_MS_PER_TICK),
          pdFALSE, NULL, WsfTimer_handler);
    configASSERT(xWsfTimer);
  }
}

定时器的启动

       计算出定时器到时的ticks count,并将定时器根据到时的时间插入到管理链表中。

/* 启动MS级别的定时器 */
void WsfTimerStartMs(wsfTimer_t *pTimer, wsfTimerTicks_t ms)
{
  WSF_TRACE_INFO2("WsfTimerStartMs pTimer:0x%x ticks:%u", (uint32_t)pTimer, WSF_TIMER_MS_TO_TICKS(ms));

  /* 计算时间为WSF的tick值,并根据大小插入到定时器链表中 */
  wsfTimerInsert(pTimer, WSF_TIMER_MS_TO_TICKS(ms));
}

定时器的停止

       找到定时器在链表中的位置,并将定时器从链表中移除,设置定时器的状态为,未启动状态。

//定时器停止函数
void WsfTimerStop(wsfTimer_t *pTimer)
{
  WSF_TRACE_INFO1("WsfTimerStop pTimer:0x%x", pTimer);

  /* task schedule lock */
  WsfTaskLock();

  //将定时器从管理链表移除,设置定时器运行状态为false
  wsfTimerRemove(pTimer);

  /* task schedule unlock */
  WsfTaskUnlock();
}

定时器更新函数

       轮询定时器管理链表中的每个定时器,减去已经过去的ticks时间,判断每个定时器是否到时,若定时器到时则发送时间给对应的处理函数。

void WsfTimerUpdate(wsfTimerTicks_t ticks)
{
  wsfTimer_t  *pElem;

  /* 关任务调度 */
  WsfTaskLock();

  pElem = (wsfTimer_t *) wsfTimerTimerQueue.pHead;

  /* 轮询链表上所有的定时器 */
  while (pElem != NULL)
  {
    /* 减去已经获取的始终ticks */
    if (pElem->ticks > ticks)
    {
      pElem->ticks -= ticks;
    }
    else
    {
      pElem->ticks = 0;

      /* 定时器到期,通知对应的事件处理函数 */
      WsfTaskSetReady(pElem->handlerId, WSF_TIMER_EVENT);
    }

    pElem = pElem->pNext;
  }

  /* 是能任务调度 */
  WsfTaskUnlock();
}

获取当前系统ticks,并更新所有定时器,并根据下一个到期Timer的时间,重新设置系统定时器的超时时间。

//根据实际的OS仅从此函数的移植,这个函数在相关的TASK中应该一直被调用
void WsfTimerUpdateTicks(void)
{
    uint32_t ui32CurrentTime, ui32ElapsedTime;
    bool_t bTimerRunning;
    wsfTimerTicks_t xNextExpiration;

    /* 读取OS的时间值 */
    ui32CurrentTime = xTaskGetTickCount();

    /* 计算上次到这次计算之间的间隔 */
    ui32ElapsedTime = ui32CurrentTime - g_ui32LastTime;

    /* 计算是否达到了WSF的自定义tick值 */
    if ( (ui32ElapsedTime / CLK_TICKS_PER_WSF_TICKS) > 0 )
    {
        /* 更新所有定时器 */
        WsfTimerUpdate(ui32ElapsedTime / CLK_TICKS_PER_WSF_TICKS);

        g_ui32LastTime = ui32CurrentTime;
    }

    /* 检查是否有定时器在运行,并获取剩余的ticks */
    xNextExpiration = WsfTimerNextExpiration(&bTimerRunning);

    /* 根据下一个到时时间,重新设置OS定时器的周期 */
    if ( xNextExpiration )
    {
        configASSERT(pdPASS == xTimerChangePeriod( xWsfTimer,
                pdMS_TO_TICKS(xNextExpiration*CLK_TICKS_PER_WSF_TICKS), 100)) ;
    }
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值