加入收藏 在线留言 联系我们
关注微信
手机扫一扫 立刻联系商家
全国服务热线15915421161

SIEMENS山东省潍坊市 西门子代理商——西门子华北一级总代理

更新时间
2024-07-02 07:00:00
价格
请来电询价
西门子总代理
PLC
西门子一级代
驱动
西门子代理商
伺服电机
联系电话
15903418770
联系手机
15915421161
联系人
张经理
立即询价

详细介绍
2.6 软件定时器任务基本功能(三部分)

软件定时器任务的具体内容可分为三部分:

获取Zui近一次定时器超时时间

处理超时的定时器或者让队列阻塞

处理队列接收到的命令

三部分不断循环处理实现Daemon任务。

























static void prvTimerTask( void *pvParameters ){TickType_t xNextExpireTime;BaseType_t xListWasEmpty;
   /* Just to avoid compiler warnings. */    ( void ) pvParameters;
   #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 )    ...略去部分代码    #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */
   for( ;; ){        /* 获取Zui近一次定时器超时时间 */        xNextExpireTime = prvGetNextExpireTime(&xListWasEmpty);        /* 处理超时的定时器或者让队列阻塞 */        prvProcessTimerOrBlockTask(xNextExpireTime, xListWasEmpty);        /* 处理队列接收到的命令 */        prvProcessReceivedCommands();}}

以上介绍了从启动调度器到实现Daemon任务的具体过程,下面来详细分析Daemon任务中的三部分功能的细节。


3 软件定时器任务功能分析


先来一张整体结构图:

首先是从定时器列表中获取下一次的溢出时间,因为各定时器的溢出时间是按照升序排列的,因此只需获取下一次的溢出时间。

3.1 获取下一个定时超时时间























/* 获取下一次的定时器超时时间 */static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ){TickType_t xNextExpireTime;
   /* 判断当前定时器列表是否为空 */    *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList );    /* 当前列表非空 */    if( *pxListWasEmpty == pdFALSE ){        /* 获取Zui近超时时间 */        xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );}    else /* 当前列表为空 */{        /*超时时间设为0,使任务非阻塞 */        xNextExpireTime = ( TickType_t ) 0U;}
   return xNextExpireTime;}

3.2 处理或阻塞软件定时器任务

那系统如何处理软件定时器列表?系统在不断运行,而xTimeNow(xTickCount)随着SysTick的触发一直在增长,在软件定时器任务运行的时候会获取下一个要唤醒的定时器:

比较当前系统时间xTimeNow是否大于或等于下一个定时器唤醒时间xTicksToWait

若大于则表示已经超时,定时器任务将会调用对应定时器的回调函数

否则将软件定时器任务挂起,直至下一个要唤醒的软件定时器时间到来或者接收到命令消息






















































/* 处理或阻塞软件定时器任务 */static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ){    TickType_t xTimeNow;    BaseType_t xTimerListsWereSwitched;
   /* 挂起调度器 */    vTaskSuspendAll();    {        /* 获取当前时间,并判断是否需要切换定时器列表,如果需要则切换 */        xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );        /* 定时器列表没有切换 */        if( xTimerListsWereSwitched == pdFALSE )        {            /* 当前列表中有定时器,且下次唤醒时间小于当前时间,即超时了 */            if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )            {                /* 解除调度器挂起 */                ( void )xTaskResumeAll();                /* 处理超时的定时器 */                prvProcessExpiredTimer( xNextExpireTime, xTimeNow );            }            else/* 定时器列表为空,或者没有超时 */            {                /* 定时器列表为空 */                if( xListWasEmpty != pdFALSE )                {                    /* 判断溢出列表是否为空,如果两个列表都为空,则无限期阻塞 */                    xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );                }
               /* 定时器定时时间还没到,将当前任务挂起,让队列按照给定的时间进行阻塞 */                vgeRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );                /* 解除调度器挂起 */                if( xTaskResumeAll() == pdFALSE )                {                    /* 申请切换任务 */                    portYIELD_WITHIN_API();                }                else                {                    mtCOVERAGE_TEST_MARKER();                }            }        }        else        {            /* 解除调度器挂起 */            ( void ) xTaskResumeAll();        }    }}


相关产品

联系方式

  • 电  话:15903418770
  • 联系人:张经理
  • 手  机:15915421161
  • 微  信:15915421161