STM32 FreeRTOS同优先级任务为何串行运行而非并行?
问题解答
为什么同优先级任务呈串行运行?
这得从FreeRTOS的调度逻辑和任务代码行为两方面分析:
- 同优先级调度依赖时间片轮转配置:FreeRTOS中,同优先级任务要实现“并行”(时间片轮转),必须同时开启
configUSE_PREEMPTION和configUSE_TIME_SLICING(多数默认配置是开启的)。如果你的任务在时间片结束前就主动调用vTaskDelay()进入阻塞态,调度器只会在当前任务阻塞后才切换到下一个同优先级任务。 - 串口发送的阻塞特性:你用的
HAL_UART_Transmit()默认是阻塞式的——它会一直占用CPU直到数据发送完成。如果串口波特率较低、发送的数据量不小,发送耗时可能远超过系统时间片(比如时间片是1ms,发送可能要几十ms),任务会一直运行到发送完成才调用vTaskDelay(),下一个同优先级任务才有机会执行,看起来就像是串行运行。 - 另外,如果你的FreeRTOS配置里关闭了时间片轮转(
configUSE_TIME_SLICING设为0),同优先级任务只会在当前任务主动阻塞或挂起时才切换,必然是串行执行的。
vTaskDelay是否适合用于让任务再次运行的最小延时?
得看你的具体需求:
- 精度限制:vTaskDelay的最小延时单位是系统滴答周期,由
configTICK_RATE_HZ决定。比如configTICK_RATE_HZ设为1000,最小延时就是1ms;如果设为100,最小就是10ms。如果你的最小延时需求小于这个值,vTaskDelay满足不了,得用硬件定时器中断触发唤醒,或者短时间忙等(但忙等会占用CPU,不推荐)。 - 适用场景:vTaskDelay是相对延时——从调用函数的时刻开始,延时指定滴答数后唤醒任务。如果只是需要让任务暂时让渡CPU、之后再运行,且延时需求不低于系统滴答周期,vTaskDelay是合适的;如果需要严格的周期执行,应该用
vTaskDelayUntil()。
内容的提问来源于stack exchange,提问作者IGtti
相关产品推荐
相关产品推荐

