在使用 FreeRTOS 的过程中通常会在一个任务函数中使用延时函数对这个任务延时,当执行延时函数的时候会进行任务切换,并且此任务就会进入阻塞态,直到延时完成,任务重新进入就绪态。
FreeRTOS 延时函数
1、函数 vTaskDelay()
在FreeRTOS 中延时函数也有相对模式和绝对模式,不过在FreeRTOS中不同的模式用的函数也不同,其中函数 vTaskDelay()是相对模式(相对延时函数),函数 vTaskDelayUntil()是绝对模式(绝对延时函数)。
函数 vTaskDelay()在文件 tasks.c 中有定义,要使用此函数的话宏 INCLUDE_vTaskDelay 必须为 1。
(1)延时时间由参数 xTicksToDelay 来确定,为了延时的时间节拍数,延时时间肯定要大于0。否则的话相当于直接调用函数 portYIELD()进行任务切换。
(2)调用函数 vTaskSuspendAll()挂起任务调度器。
(3)调用函数 prvAddCurrentTaskToDelayedList() 将要延时的任务添加到延时列表 pxDelayedTaskList 或 者 pxOverflowDelayedTaskList() 中 。
(4)调用函数 xTaskResumeAll()恢复任务调度器。
(5)如果函数 xTaskResumeAll()没有进行任务调度的话那么在这里就得进行任务调度。
(6)调用函数 portYIELD_WITHIN_API()进行一次任务调度。
2、函数 12.3vTaskDelayUntil()
函数 vTaskDelayUntil() 会阻塞任务,阻塞时间是一个绝对时间,那些需要按照一定的频率运行的任务可以使用。
使用方法:
void TestTask( void * pvParameters )
{
TickType_t PreviousWakeTime;
//延时 50ms,但是函数 vTaskDelayUntil()的参数需要设置的是延时的节拍数,不能直接
//设置延时时间,因此使用函数 pdMS_TO_TICKS 将时间转换为节拍数。
const TickType_t TimeIncrement = pdMS_TO_TICKS( 50 );
PreviousWakeTime = xTaskGetTickCount();
for( ;; )
{
/******************************************************************/
/*************************任务主体*********************************/
/******************************************************************/
//调用函数vTaskDelayUntil 进行延时
vTaskDelayUntil( &PreviousWakeTime, TimeIncrement);
```
}
}
函数 vTaskDelayUntil() 延时的任务不一定就能周期性的运行,使用函数 vTaskDelayUntil() 只能保证按照一定的周期取消阻塞,进入就绪态。
FreeRTOS 系统时钟节拍
xTickCount 就是FreeRTOS的系统时钟节拍计数器。每个滴答定时器中断中 xTickCount 就会加1。