延时函数

vTaskDelay()

相对延时函数,在文件task.c中定义的,要使用的话宏INCLUDE_vTaskDelay必须设置为1;

void vTaskDelay( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE; /* A delay time of zero just forces a reschedule. */
if( xTicksToDelay > ( TickType_t ) 0U )
{
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll();
{
traceTASK_DELAY();
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
}
xAlreadyYielded = xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
} if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
  • 延时参数xTicksToDelay为要延时的时间节拍数,肯定要大于0,否则相当于直接调用函数portYIELD()进行任务切换;
  • 调用vTaskSuspendAll()挂起任务调度器;
  • 调用函数prvAddCurrentTaskToDelayedList()将要延时的任务添加到延时列表中;
  • 调用xTaskResumeAll()恢复任务调度器,并在之后检测xTaskResumeAll()返回参数,如果没进行任务调度的话,那么调用portYIELD_WITHIN_API()进行任务调度;

函数prvAddCurrentTaskToDelayedList()分析

static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
{
TickType_t xTimeToWake;
const TickType_t xConstTickCount = xTickCount; #if( INCLUDE_xTaskAbortDelay == 1 )
{
pxCurrentTCB->ucDelayAborted = pdFALSE;
}
#endif if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
{
portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
}
else
{
mtCOVERAGE_TEST_MARKER();
} #if ( INCLUDE_vTaskSuspend == 1 )
{
if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
{
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
xTimeToWake = xConstTickCount + xTicksToWait;
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
if( xTimeToWake < xConstTickCount )
{
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
}
#else /* INCLUDE_vTaskSuspend */
{
xTimeToWake = xConstTickCount + xTicksToWait;
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); if( xTimeToWake < xConstTickCount )
{
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
}
else
{
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
if( xTimeToWake < xNextTaskUnblockTime )
{
xNextTaskUnblockTime = xTimeToWake;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
} ( void ) xCanBlockIndefinitely;
}
#endif /* INCLUDE_vTaskSuspend */
}
  • 读取进入该函数的时间点并保存在xConstTickCount中,后面在计算唤醒时间点的时候要用到,xTickCount是时钟节拍计数器,每个滴答定时器中断xTickCount都会加一
  • 将当前任务从就绪表中移除;
  • 取消当前任务在uxTopReadyPriority中的就绪标记,即将相应的bit清0;
  • 如果延时时间为最大值portMAX_DELAY并且xCanBlockIndefinitely不为pdFALSE(即表示允许阻塞任务),那么直接将当前任务添加到挂起列表中,任务就不用添加到延时列表中了;
  • 计算唤醒的时间点,之后将唤醒时间点值写入到任务列表中状态列表项的相应字段中;
  • 如果计算得到的唤醒时间点小于xConstTickCount说明发生了溢出,FreeRTOS针对此现象专门做了处理,定义了两个延时列表xDelayedTaskList1和xDelayedTaskList2,也定义了两个指针pxDelayedTaskList和pxOverflowDelayedTaskList来访问这两个列表,在初始化列表函数中分别进行了初始化;
  • xNextTaskUnblockTime是个全局变量,保存着距离下一个要取消阻塞的任务最小时间点值,当计算的唤醒时间点xTimeToWake小于xNextTaskUnblockTime,就更新替换;

vTaskDelayUntil()

绝对延时函数,该函数会阻塞任务,阻塞时间是一个绝对时间,如果是一些需要按照一定的频率运行的任务可以使用该函数;

函数定义如下:

void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
  • pxPreviousWakeTime,上一次任务延时结束被唤醒的时间点,任务中第一次调用该函数时需要将pxPreviousWakeTime初始化进任务的while()循环体的时间点值,之后的运行中该函数会自动更新pxPreviousWakeTime的值;
  • xTimeIncrement,任务需要延时的时间节拍数;

使用模板如下:

void test_task(void *pvParameters)
{
TickType_t PreviousWakeTime; //延时50ms,将延时时间转换成节拍数
const TickType_t TimeIncrement = pdMS_TO_TICKS(50);
PreviousWakeTime = xTaskGetTickCount(); //获取当前的系统节拍值
for( ; ; )
{
/* 任务主体 */ /* 调用延时函数 */
vTaskDelayUntil(&PreviousWakeTime, TimeIncrement);
}
}

注意:使用函数vTaskDelayUntil()延时的任务也不一定就能周期性的运行,只能保证按照一定的周期取消阻塞,进入就绪态,如果有更高优先级或者中断的话,还是要等待其他更高优先级任务或者中断服务函数运行完成后才能运行;

FreeRTOS时间管理的更多相关文章

  1. uC/OS-III 时钟节拍,时间管理,时间片调度

    uC/OS-III 时钟节拍,时间管理,时间片调度   时钟节拍 时钟节拍可谓是 uC/OS 操作系统的心脏,它若不跳动,整个系统都将会瘫痪. 时钟节拍就是操作系统的时基,操作系统要实现时间上的管理, ...

  2. FreeRTOS-04-内核控制函数+时间管理函数

    说明 本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正. FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式.合作式和时间片调度.适用于微处理 ...

  3. PMP备考_第六章_项目时间管理

    项目时间管理 前言 项目时间管理是项目管理中最难的一个环节,与个人时间管理类似,团体的效率如果管理不当,是低于个人效率的,为了管理好时间,从预估,执行到反馈均需要严格的分析和处理.如果制定的计划是无法 ...

  4. Google内部邮件:如何进行高效的时间管理能量波动图

    Google内部邮件:如何进行高效的时间管理能量波动图 发布时间: 2015-12-16 22:16:50| 阅读数:462 views 最近,我给团队内部写了一封简单的邮件.主要内容是征询他们,如何 ...

  5. linux 时间管理——概念、注意点(一)【转】

    转自:http://www.cnblogs.com/openix/p/3324243.html 参考:1.http://bbs.eyeler.com/thread-69-1-1.html        ...

  6. μC/OS-Ⅲ系统的时间管理函数和定时器

    一.时间管理函数 μC/OS-Ⅲ系统提供一些列时间管理服务函数: 1.OSTimeDly():任务延时n个时钟节拍. 2.OSTimeDlyHMSM():任务延时指定的时间,采用“时:分:秒:毫秒”方 ...

  7. 时间管理的若干Tips

    时间管理的若干Tips 记下来 再好的记性也不如一支笔与一个本子. 买一支好点的笔于一个好点的本子,让自己有书写的欲望,将todo事项记下来. 小目标 太大太远的目标会使人气馁.通过将大目标分解再分解 ...

  8. 4D时间管理

    时间管理的4D原则   时间矩阵:每个人,每天要做的事情大致分为四类:一类:必须做的,不做会产生不良后果的二类:需要做的,为将来或者今后阶段做准备工作的三类:可以不做,但又不得不做的,例如通过简约形式 ...

  9. 【uTenux实验】时间管理(系统时间/周期性处理/警报处理)

    1.系统时间管理 系统时间管理函数用来对系统时间进行操作,是OS的一个基础性的东西.个人认为,设置系统时间和获取系统时间对OS来说基本是可有可无的. uTenux提供了三个系统时间相关API.分别用于 ...

随机推荐

  1. iOS-MPMoviePlayerController视频播放

    视频MPMoviePlayerController 在iOS中播放视频可以使用MediaPlayer.framework种的MPMoviePlayerController类来完成,它支持本地 视频和网 ...

  2. iOS-25个小技巧

    (一)关于UITableView  方法flashScrollIndicators:这个很有用,闪一下滚动条,暗示是否有可滚动的内容.可以在ViewDidAppear或[table reload]之后 ...

  3. leetcode903 Valid Permutations for DI Sequence

    思路: dp[i][j]表示到第i + 1个位置为止,并且以剩下的所有数字中第j + 1小的数字为结尾所有的合法序列数. 实现: class Solution { public: int numPer ...

  4. CenOS 7 防火墙 端口 systemctl 操作项

    Centos开放端口 # firewall-cmd --zone=public --add-port=3306/tcp --permanent Centos关闭端口 # firewall-cmd -- ...

  5. CentOS使用yum安装jdk

    1.查看系统版本命令 cat /etc/issue 2.查看yum包含的jdk版本 yum search java 或者 yum list java* 版本 jre jdk 1.8 java-1.8. ...

  6. Linux(CentOS 7)下安装postgres

    事情背景:需要在Linux上安装postgres数据库,但安装目录想直接指定,所以想通过源码编译安装pg 首先下载源码安装包.源码下载地址:https://github.com/postgres/po ...

  7. kibana发音 logstash发音 ElasticSearch发音 音标 翻译

    kibana [kɪbana] 剋吧那 kei ba na == 扩展 logstash [lɔɡ] [stæ:ʃ] 楼个四die吃 == ElasticSearch [ɪˈlæstɪk] [sɜːt ...

  8. Java Socket 的工作机制

    转载,请加上原文链接: 目录 socket 对象的创建时间 socket 通信可能会造成死锁 socket 对象的创建时间 这里需要一点TCP的知识, TCP状态分析请看 --> TCP转态转换 ...

  9. Appium移动端自动化测试--元素操作与触摸动作

    常见自动化动作支持 click sendKeys swipe touch action 元素操作 1.click()点击操作 也可以用tab实现点击操作 driver.find_element_by_ ...

  10. WUSTOJ 1232: 矩阵乘法(C)

    1232: 矩阵乘法 Time Limit: 1 Sec Memory Limit: 128 MB 64bit IO Format: %lld Description 小明明正在学习线性代数,老师布置 ...