不推荐在freertos中使用HAL_Delay() 函数
在 FreeRTOS 中,你不应使用标准库中的 delay()
函数(例如 HAL_Delay()
或类似的阻塞延时函数),而是应该使用 FreeRTOS 提供的延时函数,比如 vTaskDelay()
。原因是 FreeRTOS 是一个多任务操作系统,标准的 delay()
函数会阻塞当前任务,从而导致其他任务无法运行,破坏多任务调度。
FreeRTOS 中的延时函数
1. vTaskDelay()
- 功能:延迟当前任务一定的时间,但不会阻塞系统。FreeRTOS 会在延迟期间挂起该任务,并调度其他任务运行。
- 用法:
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1000 毫秒
- 这里的
pdMS_TO_TICKS(1000)
会将延迟的时间从毫秒转换为系统节拍(tick),这个函数使代码更具可移植性。 - 延迟后,任务进入阻塞状态,直到指定时间过去,任务再次变为就绪状态。
- 这里的
2. vTaskDelayUntil()
-
功能:与
vTaskDelay()
类似,但它允许精确控制任务的执行周期,避免因为延时累积导致周期偏移。 -
用法:
TickType_t xLastWakeTime; const TickType_t xFrequency = pdMS_TO_TICKS(1000); // 1 秒// 初始化上次唤醒时间 xLastWakeTime = xTaskGetTickCount();// 循环任务,每 1 秒执行一次 for(;;) {// 延时直到下一个周期vTaskDelayUntil( &xLastWakeTime, xFrequency ); }
-
优点:确保任务的延时是周期性的,不会因为任务执行的时间导致延时累积。如果任务需要定时执行操作(如每秒运行一次),这个函数更加适合。
FreeRTOS 延时与标准延时的区别
FreeRTOS 延时 (vTaskDelay ) | 标准延时函数(如 HAL_Delay() ) |
---|---|
当前任务延时,其他任务继续运行 | 整个系统阻塞,所有任务无法运行 |
非阻塞,只影响当前任务 | 阻塞,影响整个系统的实时性 |
调度器负责管理延时 | 阻止 FreeRTOS 调度器运行 |
延时单位为 FreeRTOS 的系统节拍(tick) | 延时单位为毫秒或微秒,具体实现与硬件相关 |
什么时候不能使用标准 delay
函数?
标准的 delay()
函数是阻塞式的,会直接阻塞整个系统,直到延时结束。因此,在 FreeRTOS 中不推荐使用标准延时函数,特别是在任务中使用时,会产生以下问题:
- 阻塞调度:整个任务执行被阻塞,FreeRTOS 无法切换到其他任务执行。
- 系统实时性下降:影响系统的实时性能和任务切换。
- 无法响应中断:如果中断优先级和
delay()
实现有关,可能导致中断响应延迟。
什么时候可以使用标准 delay
函数?
在某些初始化代码中,或者在启动 FreeRTOS 调度器之前使用标准的 delay()
函数是可以的。例如,在系统刚启动、调度器未开始运行时,使用 delay()
可以用于硬件初始化的等待。
总结
- FreeRTOS 环境下的任务中,应使用
vTaskDelay()
或vTaskDelayUntil()
等 FreeRTOS 延时函数来避免阻塞其他任务。 - 标准
delay()
函数 在多任务环境下会阻塞系统,影响 FreeRTOS 的调度,不推荐在 FreeRTOS 的任务中使用。