FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()和绝对延时vTaskDelayUntil()。
这两个延时函数和自己实现的延时函数不同,这两个延时函数一旦被调用,当前任务会立马进入
阻塞状态
,而自己写的延时函数(以for循环等形式实现的软件延时)会被当做有效任务而一直执行。
-
相对延时是指每次延时都是从任务执行函数vTaskDelay()开始,延时指定的时间结束;
-
绝对延时是指每隔指定的时间,执行一次调用vTaskDelayUntil()函数的任务。换句话说:任务以固定的频率执行。
二、vTaskDelay()
调用vTaskDelay()函数后,任务会进入
阻塞状态
,vTaskDelay()函数的参数xTicksToDelay表示延时多少个系统节拍时钟周期。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必须设置成1,此函数才能有效。
const portTickType xDelay = pdMS_TO_TICKS(500);
vTaskDelay(xDelay);
vTaskDelay(pdMS_TO_TICKS(500)); //延迟500ms
vTaskDelay()指定的延时时间是从调用vTaskDelay()后开始计算的相对时间。
比如vTaskDelay(100),那么从调用vTaskDelay()后,任务进入阻塞状态,经过100个系统时钟节拍周期,任务解除阻塞。因此,vTaskDelay()并不适用与周期性执行任务的场合。此外,其它任务和中断活动,会影响到vTaskDelay()的调用(比如调用前高优先级任务抢占了当前任务),因此会影响任务下一次执行的时间。
三、vTaskDelayUntil()
API函数vTaskDelayUntil()可用于固定频率的延时,它用来延时一个绝对时间。
在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelayUntil 必须设置成1,此函数才有效。
这个函数不同于vTaskDelay()函数的一个重要之处在于:vTaskDelay()指定的延时时间是从调用vTaskDelay()之后(执行完该函数)开始算起的,而vTaskDelayUntil()指定一个绝对时间,每当时间到达,则解除任务阻塞。
void vTaskDelayUntil( TickType_t * pxPreviousWakeTime, TickType_t xTimeIncrement );
参数
|
说明
|
pxPreviousWakeTime
|
指针,指向一个变量(指针说明这个变量即可以当做输入类型的,也可以当做输出类型的)。该变量保存任务最后一次解除阻塞的时间。
第一次使用前,该变量必须初始化为当前时间。
之后这个变量会在vTaskDelayUntil()函数内
自动更新
。
|
xTimeIncrement
|
周期循环时间。当时间等于(*pxPreviousWakeTime + xTimeIncrement)时,任务解除阻塞。如果不改变参数xTimeIncrement的值,调用该函数的任务会按照固定频率执行。
|
如果指定的唤醒时间已经达到,vTaskDelayUntil()立刻返回(不会有阻塞)。因此,使用vTaskDelayUntil()周期性执行的任务,无论任何原因(比如,任务临时进入挂起状态)停止了周期性执行,使得任务少运行了一个或多个执行周期,那么需要重新计算所需要的唤醒时间。这可以通过传递给函数的指针参数pxPreviousWake指向的值与当前系统时钟计数值比较来检测,在大多数情况下,这并不是必须的。
使用示例:
总共有四个任务:
idle task:优先级0
task1 :coutinuous task,优先级1
task2:coutinuous task,优先级1
task3:使用vTaskDelayUntil函数的周期性任务,优先级2
其中,task1、task2和task3的任务内容如下:
void vPeriodicTask( void *pvParameters )//task3
TickType_t xLastWakeTime;
const TickType_t xDelay3ms = pdMS_TO_TICKS( 3 );
xLastWakeTime = xTaskGetTickCount();
for( ;; )
vPrintString( "Periodic task is running\r\n" );
vTaskDelayUntil( &xLastWakeTime, xDelay3ms );
void vContinuousProcessingTask( void *pvParameters )//task2 task1
char *pcTaskName;
pcTaskName = ( char * ) pvParameters;
for( ;; )
vPrintString( pcTaskName );
直接结果:
vTaskDelayUntil函数比vTaskDelay函数多了一个记录任务本次被唤醒的时刻的变量,因此如果想要实现控制任务能够周期性运行的话,vTaskDelayUntil函数是一种比较简单的方法。
对于绝对延时函数,如果任务不是最高优先级,则仍然能周期性的将任务解除阻塞,但是解除阻塞的任务不一定能获得CPU权限,因此任务主体代码也不会总是精确周期性执行。
如果要想精确周期性执行某个任务,可以使用系统节拍钩子函数vApplicationTickHook(),它在系统节拍中断服务函数中被调用,因此这个函数中的代码必须简洁。
https://blog.csdn.net/zhzht19861011/article/details/51705148
https://blog.csdn.net/zhzht19861011/article/details/50454591
一、概述FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()和绝对延时vTaskDelayUntil()。这两个延时函数和自己实现的延时函数不同,这两个延时函数一旦被调用,当前任务会立马进入阻塞状态,而自己写的延时函数(以for循环等形式实现的软件延时)会被当做有效任务而一直执行。相对延时是指每次延时都是从任务执行函数vTaskDelay()开始,延时指定的时间结束; 绝对延时是指每隔指定的时间,执行一次调用vTaskDelayUntil()函数的任务。换句话说:任务以
就是交出CPU一段时间,如果任务一直不延时或者挂起,那么低优先级的任务会无法获得CPU。
FreeRTOS延时的单位是tick,就是调度的基本单位(不是毫秒)
vTaskDelay和vTaskDelayUntil都是延时函数,vTaskDelayUntil是精确延时
void vTaskDelay( const TickType_t xTicksToDelay )
vo...
一、vTaskDelay 和 vTaskDelayUntill
vTaskDelay :至少等待指定个数的tick interrupt才能变为就绪态。(所以在等待的时候是阻塞态)
vTaskDelayUntill :等待到指定的绝对时刻,才能变为就绪态(所以在等待的时候是阻塞态)。
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,//开始时间
const Ti
最近学习白问网韦东山老师在B站开源的freeRTOS课程,网址:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili和7天物联网训练营【第2期】7天物联网智能家居实战训练营
在学习过程中按照韦老师的方法分析了下freeRTOS源码,如果有不对的地方请指证。
vTaskDelayUntil源码分析,基于cubemx生成的freeRTOS工程。
void vTaskDelayUntil( TickType_t * const pxPreviou.
想必各位嵌入式工程师对于Delay延时函数再也熟悉不过了~
但对于各位刚入RTOS的小白来说,有操作系统的延时函数,真的和裸机中的延时函数一样吗?FreeRTOS的任务调度是怎么调度的?如何分配系统的CPU?
今天小编就带大家来扒一下FreeRTOS中的延时函数相对延时vTaskDelay函数,绝对延时vTaskDelayUntil函数。
从事嵌入式这一行的,想必大家在大学的时候一定上过C语言吧,上C语言的时候老师一定给大家写过Delay这个函数吧,给大家举个最简单的延时函数吧~
void De..
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-b5506197d8.css">
<div id="content_views" class="htmledit_views">
<span style="font-family:Microsoft...
博主联系方式:QQ:1256153255 ,邮箱:1256153255@qq.com
点击这里可申请RH850开发板
最直接的办法就是从函数vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement )的源码入手分析
#if ( INCLUDE_vTaskDelayUntil == 1 )
void vTaskDelayUntil( TickType_t * const pxPre
#if ( INCLUDE_vTaskDelay == 1 )
//延时特定时间xTicksToDelay,这个时间需要转换为唤醒绝对时间xTimeToWake,
//这样才能在与vTaskIncrementTick函数中操作的数值是一致的xTicksToDelay:延时的节拍数
void vTaskDelay( const TickType_t xTicksToDelay )
① vTaskDelayUntil精度比vTaskDelay高
② 使用vTaskDelayUntil的任务不会丢失任务执行,vTaskDelay会丢失执行。
如下代码:
Task2使用vTaskDelayUntil延时1s,Task3使用vTaskDelay延时1s,
优先级最高的Task1长期占用CPU(大概3秒),导致Task...
项目场景:
` 最近在准备找工作,没有实际的项目和经验,就买了几个模块结合FreeRTOS来拼凑拼凑整成一个项目——基于ESP8266的远程温度监控,使用MQTT协议和搭载FreeRTOS系统。
省流:vTaskDelay的使用需要放在任务中,否则运行不了!
问题描述:
使用ESP8266时候,按照oneNET的例程移植到STM32上,能够很好的运行,但是把代码复制到FreeRTOS时候却一直初始化不了,等于说是卡在初始化了。下图为初始化函数摆放位置。
原因分析:
在使用串口函数一步一步的在每一个函数
os_delay和vTaskDelay都是延时函数,但是它们的使用场景不同。
os_delay是裸机系统中的延时函数,适用于单片机没有操作系统支持的情况下使用。os_delay函数调用后,会使当前任务挂起一段时间,直到延时时间结束再继续执行下面的任务代码。os_delay函数的单位是毫秒,精度不高,适用于简单的延时操作。
vTaskDelay是FreeRTOS操作系统中的延时函数,适用于多任务情况下使用。vTaskDelay函数调用后,会使当前任务进入阻塞状态,等待延时时间结束后才会被重新调度执行。vTaskDelay函数的单位是系统节拍,可以实现更精确的延时操作。在多任务情况下,使用vTaskDelay可以更好地利用系统资源,避免空闲时间的浪费。