<FreeRTOS>

状态 核心含义 触发方式 恢复方式 是否参与调度
运行态 正在占用 CPU 执行 调度器选择就绪任务 时间片到 / 被抢占 是(占用 CPU)
就绪态 等待 CPU 分配 任务创建 / 阻塞到期 / 被恢复 调度器选中 是(等待调度)
阻塞态 等待事件(主动放弃 CPU) 调用 vTaskDelay / 等信号量 事件触发 / 延迟到期(自动)
挂起态 被强制暂停 调用 vTaskSuspend 调用 vTaskResume(手动)
删除态 已删除,等待内存回收 调用 vTaskDelete 空闲任务回收内存

状态

1. 就绪态 ↔ 运行态

  • 就绪态 → 运行态 :由调度器触发,选择 "就绪态中优先级最高" 的任务,将其切换为运行态(独占 CPU 执行)。
  • 运行态 → 就绪态 :满足以下任一条件时触发:
    • 时间片结束(同优先级任务轮转调度);
    • 被更高优先级的就绪任务 "抢占";
    • 任务主动放弃 CPU(如进入阻塞态、挂起态)。

2. 运行态 ↔ 阻塞态

  • 运行态 → 阻塞态 :任务因 "等待事件" 主动放弃 CPU,触发条件包括:
    • 调用 vTaskDelay()/vTaskDelayUntil() 等待时间延迟;
    • 调用 xSemaphoreTake()/xQueueReceive() 等待信号量、队列数据等同步 / 通信事件。
  • 阻塞态 → 就绪态 :当 "等待的事件满足" 时自动触发,如:
    • 延迟时间到期;
    • 信号量被释放、队列有新数据等事件到达。

3. 就绪态 / 运行态 / 阻塞态 ↔ 挂起态

  • 就绪态 / 运行态 / 阻塞态 → 挂起态 :通过 API vTaskSuspend() 触发,无论任务当前处于就绪、运行还是阻塞态,均可被强制挂起(暂停执行,不参与调度)。
  • 挂起态 → 就绪态 :仅通过 API vTaskResume()(任务上下文)或 vTaskResumeFromISR()(中断上下文)手动唤醒,才能从挂起态回到就绪态,重新参与调度。

4. 运行态 → 僵尸态(删除态)

  • 运行态 → 僵尸态 :当任务 "正常结束" 或被 vTaskDelete() 显式删除时,进入僵尸态(即 "删除态")。
  • 僵尸态 → 内存释放 :由 FreeRTOS 的空闲任务(Idle Task) 自动回收该任务的 TCB 和栈内存,完成最终清理。

核心区分总结

  • 阻塞态 :因 "等事件" 被动阻塞,事件满足后自动恢复为就绪态;
  • 挂起态 :因 vTaskSuspend() 强制暂停,需手动调用 vTaskResume() 才能恢复;
  • 僵尸态:任务已逻辑删除,仅等待空闲任务回收物理内存。

延时

一、核心计时逻辑与起点

  • vTaskDelay(相对延时) :计时起点是 **"调用函数并进入阻塞态的瞬间"**(即任务加入等待队列的时刻),延时时长为相对当前时刻的 xTicksToDelay 个系统节拍(如 1000 节拍 = 1000ms)。例如:任务执行到 vTaskDelay(1000) 时,从 "此时" 开始等待 1000ms 后解除阻塞,与任务 "何时开始执行" 无关。

  • vTaskDelayUntil(绝对延时) :计时起点是 **"上次被唤醒的绝对时间点"**(通过 xLastWakeTime 记录),下次唤醒时间严格为 xLastWakeTime + 固定周期(xPeriod)。例如:首次唤醒时间为 t0,则下次唤醒时间必为 t0 + 1000ms,无论任务执行耗时或中断占用多久,周期间隔始终固定。

二、周期稳定性对比

  • vTaskDelay:周期不稳定。实际周期 = 任务执行时间 + 延时节拍时间 + 中断占用时间(若中断发生在任务执行阶段),会随执行耗时、中断等因素漂移。

  • vTaskDelayUntil :周期绝对稳定。两次唤醒的时间间隔严格等于 xPeriod(如 1000ms),不受任务执行耗时、中断的影响(仅压缩任务可执行时间,不改变周期)。

三、适用场景

  • vTaskDelay :适合非周期性任务(如单次延时后执行、对周期精度无要求的场景),例如初始化后延时启动传感器、临时等待某个条件。

  • vTaskDelayUntil :必须用于周期性任务(如定时采样、周期性控制指令),需严格保证固定频率,避免因执行耗时或中断导致的周期偏差。

四、选择原则

  • 若只需 "延时一段时间后执行一次",用 vTaskDelay(简单直观);
  • 若需 "按固定周期重复执行",必须用 vTaskDelayUntil(确保周期稳定,是高精度周期任务的唯一选择)。
相关推荐
q***062913 小时前
搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程
开发语言·后端·golang
阿Y加油吧14 小时前
Java SE核心面试题总结——day 01
java
布丁写代码14 小时前
GESP C++ 一级 2025年09月真题解析
开发语言·c++·程序人生·学习方法
2021_fc14 小时前
Flink入门指南:使用Java构建第一个Flink应用
java·大数据·flink
GOTXX14 小时前
用Rust实现一个简易的rsync(远程文件同步)工具
开发语言·后端·rust
诸葛亮的芭蕉扇14 小时前
抓图巡检-底图支持绘制
开发语言·前端·javascript
Java开发追求者14 小时前
vscode导入springboot项目
java·ide·spring boot·vscode
麦烤楽鸡翅14 小时前
坚持60s (攻防世界)
java·网络安全·jar·ctf·misc·反编译·攻防世界
少废话h15 小时前
Flume Kafka源与汇的topic覆盖问题解决
java·linux·kafka·flume
激动的兔子15 小时前
Geoserver修行记-连接瀚高数据库显示java.sql.SQLException: org.postgresql.util.PSQLException
java·geoserver·瀚高数据库