当前位置:网站首页>FreeRTOS(八)——时间管理
FreeRTOS(八)——时间管理
2022-06-29 09:10:00 【水似冰】
在使用过程中,我们通常会在一个任务函数中使用 延时函数来延时,当执行延时函数的时候就会进行任务切换,并且此任务就进入阻塞态。直到延时完成,任务重新进入就绪态。延时函数属于FreeRTOS的时间管理。在这个时间管理过程中,
- 调用延时函数以后究竟发生了什么?
- 任务是如何进入阻塞态的?
- 延时完成以后任务又是如何恢复到就绪态的?
FreeRTOS延时函数
函数vTaskDealy()
在FreeRTOS中延时函数又相对模式和绝对模式,其中vTaskDealy()是相对模式,函数vTaskDelayUntil()是绝对模式。函数vTaskDealy()在文件中有定义,如果想使用次函数的话宏INCLUDE_vTsakDelay必须为1。
函数代码:
#if ( 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 ) /*(1)*/
{
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll(); /*(2)*/
{
traceTASK_DELAY();
/* A task that is removed from the event list while the scheduler is suspended will not get placed in the ready list or removed from the blocked list until the scheduler is resumed. This task cannot be in an event list as it is the currently executing task. */
prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); /*(3)*/
}
xAlreadyYielded = xTaskResumeAll(); /*(4)*/
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */
if( xAlreadyYielded == pdFALSE ) /*(5)*/
{
portYIELD_WITHIN_API(); /*(6)*/
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* INCLUDE_vTaskDelay */(1)延时时间由参数xTicksToDelay来确定,为要延时的时间的节拍数,延时时间肯定要大于0。否则的话相当于直接调用portTIELD()进行任务切换。
(2)调用函数vTaskSuspendAll()挂起任务调度器。
(3)调用函数prvAddCurrentTaskToDelayList()将要延时的任务添加到延时列表pxDelaydTaskList或者pxOverFlowDelaydTaskList中。
(4)调用函数xTaskResumeAll()恢复任务调度器。
(5)如果函数xTaskResumeAll()没有进行任务调度的话那么在这里就得进行任务调度。
(6)调用函数portYIELD_WITHIN_API()进行一次任务调度。
函数vTaskDelayUntil()
函数vTaskDelayUntil()会阻塞任务,阻塞时间是一个绝对时间,那些需要按照一定的频率执行的任务可以使用函数vTaskDelayUntil()。此函数定义在tasks.c中。
| 参数 | Are |
|---|---|
| pxPreviousWakeTime | 上次任务延时结束被唤醒的时间点,任务中第一次调用函数vTaskDelayUntil()的话需要pxPreviousWakeTime初始化进入任务的whiel()循环体的时间点值,在以后运行中函数vTaskDelayUntil()会自动更新pxPreviousWakeTime |
| xTimeIncrement | 任务需要延时的时间节拍数(相对于pxPreviousWakeTime本次延时的节拍数) |
#if ( INCLUDE_vTaskDelayUntil == 1 )
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
{
TickType_t xTimeToWake;
BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
configASSERT( pxPreviousWakeTime );
configASSERT( ( xTimeIncrement > 0U ) );
configASSERT( uxSchedulerSuspended == 0 );
vTaskSuspendAll(); /*(1)*/
{
/* Minor optimisation. The tick count cannot change in this block. */
const TickType_t xConstTickCount = xTickCount; /*(2)*/
/* Generate the tick time at which the task wants to wake. */
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; /*(3)*/
if( xConstTickCount < *pxPreviousWakeTime ) /*(4)*/
{
/* The tick count has overflowed since this function was lasted called. In this case the only time we should ever actually delay is if the wake time has also overflowed, and the wake time is greater than the tick time. When this is the case it is as if neither time had overflowed. */
if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )/*(5)*/
{
xShouldDelay = pdTRUE; /*(6)*/
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* The tick time has not overflowed. In this case we will delay if either the wake time has overflowed, and/or the tick time is less than the wake time. */
if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )/*(7)*/
{
xShouldDelay = pdTRUE; /*(8)*/
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/* Update the wake time ready for the next call. */
*pxPreviousWakeTime = xTimeToWake; /*(9)*/
if( xShouldDelay != pdFALSE ) /*(10)*/
{
traceTASK_DELAY_UNTIL( xTimeToWake );
/* prvAddCurrentTaskToDelayedList() needs the block time, not the time to wake, so subtract the current tick count. */
prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE ); /*(11)*/
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
xAlreadyYielded = xTaskResumeAll(); /*(12)*/
/* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */
if( xAlreadyYielded == pdFALSE )
{
portYIELD_WITHIN_API();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* INCLUDE_vTaskDelayUntil */(1)挂起任务调度器
(2)记录进入函数vTaskDelayUntil()的时间点值,并保存在xConstTickCount中。
(3)根据延时时间xTimeIncrement来计算任务下一次要唤醒的时间点,并保存在xTimeToWake中。这个延时时间是相对于上一次任务被唤醒的时间点pxPreviousWakeTime的。
(4) xConstTickCount溢出。
(5)既然xConstTickCount溢出,那么计算得到的任务唤醒时间点肯定也是溢出的,并且xTimeToWake肯定大于xConstTickCount。
(6)如果满足(5)条件就将pdTRUE赋值给xShouldDelay,标记允许延时。
(7)其他两种情况,1是只有xTimeToWake溢出。2是都没溢出。
(8)将pdTRUE赋值给xShouldDelay,标记允许延时。
(9)更新pxPreviousWakeTime的值为xTimeToWake,为本函数下一次执行做准备。
(10)经过前面判断,允许进行任务延时。
(11)调用函数prvAddCurrentTaskToDelaydList()进行延时。
(12)调用函数xTaskResumeAll()恢复任务调度器。
边栏推荐
- 【NOI模拟赛】为NOI加点料(重链剖分,线段树)
- Construction and use of Changan chain go language smart contract environment
- 1.4 机器学习方法之回归问题
- 【技术开发】酒精测试仪解决方案开发设计
- KiCad学习笔记--快捷键
- zabbix4.4配置监控服务器指标,以及图形页乱码解决
- 你知道BFD是什么吗?一文详解BFD协议原理及使用场景
- 滑块验证代码
- JS obtain mobile phone model and system version
- Reading notes on how to connect the network - Web server request and response (IV)
猜你喜欢

1.4 regression of machine learning methods

数据可视化:数据可视化四象限,教你正确应用图标

Gd32f4xx Ethernet Chip (ENC28J60) Drive transplantation

遍历vector容器中的对象的方式

In the era of data processing, data quality construction is the way for enterprises to survive

2020-09-29 非商品模板化代码层次 rapidjson库

数据治理:数据标准管理(第三篇)

阿里云服务器安装配置redis,无法远程访问

如何将谷歌浏览器设置为默认浏览器

CROSSFORMER: A VERSATILE VISION TRANSFORMER BASED ON CROSS-SCALE ATTENTION
随机推荐
Introduction to Chang'an chain data storage and construction of MySQL storage environment
After installing anaconda, you need to enter a password to start jupyterlab
Self cultivation (XXI) servlet life cycle, service method source code analysis, thread safety issues
1.4 机器学习方法之回归问题
The former security director of Uber faced fraud allegations and concealed the data leakage event
Invalidconnectionattributeexception exception exception handling
367. effective complete square dichotomy
【NOI模拟赛】为NOI加点料(重链剖分,线段树)
如何将谷歌浏览器设置为默认浏览器
zabbix4.4配置监控服务器指标,以及图形页乱码解决
IDEA自动补全
Five heart charity matchmaker team
Matlab tips (21) matrix analysis -- partial least squares regression
Leetcode skimming -- teponacci sequence
你知道BFD是什么吗?一文详解BFD协议原理及使用场景
linux下centos7中mysql5.7安装教程
[noi Simulation Competition] add points for noi (heavy chain dissection, line segment tree)
JS获取手机型号和系统版本
How to implement observer mode
官方stm32芯片包下载地址 stm32f10x stm32f40x下载