参考:
大D老师

任务_Task
本质
任务是程序执行的最小单元,相当于独立的"微型程序"。
特性
- 独立的执行流(程序计数器)
- 专属的栈空间(存储局部变量、返回地址等)
- 优先级属性(0~configMAX_PRIORITIES-1)
- 任务控制块(TCB)存储状态信息
// 任务创建示例
xTaskCreate(
vTaskFunction, // 任务函数
"Task_Name", // 任务名称
configMINIMAL_STACK_SIZE, // 栈大小
NULL, // 任务参数
tskIDLE_PRIORITY + 2, // 优先级
&xTaskHandle // 任务句柄
);
任务状态及其转换

创建态(Created)
-
特征:任务已被创建但未加入调度
-
进入条件:
xTaskCreate()调用成功 -
转换:
-
创建态 → 就绪态:调度器启动后(
vTaskStartScheduler()
-

就绪态(Ready)
-
特征:准备执行,等待CPU资源
-
队列:位于就绪列表(Ready List)中
-
转换:
-
→ 运行态:被调度器选中
-
→ 阻塞态:主动等待资源
-
→ 挂起态:被显式挂起
-
→ 删除态:被删除
-
就绪态 → 运行态:
运行态(Running)
-
特征:正在使用CPU执行
-
单核限制:仅1个任务处于此状态
-
转换:
-
→ 就绪态:时间片耗尽或更高优先级任务就绪
-
→ 阻塞态:调用阻塞API
-
→ 挂起态:调用
vTaskSuspend() -
→ 删除态:调用
vTaskDelete()
-
运行态 → 阻塞态:

运行态 → 挂起态:
阻塞态(Blocked)
-
特征:等待外部事件,不消耗CPU
-
等待事件类型:
-
定时器事件:
vTaskDelay() -
同步事件:
xSemaphoreTake() -
通信事件:
xQueueReceive() -
通知事件:
ulTaskNotifyTake()
-
-
转换:
-
→ 就绪态:等待事件发生
-
→ 删除态:被删除
-
阻塞态 → 就绪态:

挂起态(Suspended)
-
特征:被强制暂停,不参与调度
-
控制API:
vTaskSuspend(xTaskHandle); // 挂起任务 vTaskResume(xTaskHandle); // 恢复任务 xTaskResumeFromISR(); // 中断中恢复 -
转换:
-
→ 就绪态:被显式恢复
-
挂起态 → 就绪态:

删除态(Deleted)
-
特征:任务已终止,资源待回收
-
内存回收:由空闲任务(Idle Task)清理
-
API:
vTaskDelete(xTaskHandle)
状态转换触发条件
| 转换方向 | API/事件 | 典型场景 |
|---|---|---|
| Ready → Running | 调度器选择 | 更高优先级任务阻塞 |
| Running → Blocked | vTaskDelay() | 定时等待 |
| xQueueReceive() | 等待队列数据 | |
| xSemaphoreTake() | 获取信号量 | |
| Blocked → Ready | 定时器超时 | vTaskDelay()结束 |
| xQueueSend() | 队列数据到达 | |
| xSemaphoreGive() | 信号量释放 | |
| → Suspended | vTaskSuspend() | 调试时暂停任务 |
| Suspended → Ready | vTaskResume() | 恢复调试任务 |
| → Deleted | vTaskDelete() | 结束不再需要的任务 |
优先级与状态转换
优先级影响:
- 高优先级任务会立即抢占低优先级任务
- 同优先级任务采用时间片轮转(需启用
configUSE_TIME_SLICING)
优先级反转问题:
- 场景:低优先级任务持有高优先级任务需要的资源
- 解决方案:优先级继承(
configUSE_MUTEXES_INHERIT)
状态监控与调试
API获取状态:
eTaskState eTaskGetState(TaskHandle_t xTask);
/* 返回状态枚举:
eRunning, eReady, eBlocked,
eSuspended, eDeleted, eInvalid */
栈溢出检测:
// 获取栈高水位线
UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask);
运行时可视化:
// 打印所有任务状态
vTaskList(pcWriteBuffer);
/* 输出格式:
TaskName State Pri Stack Num */
实践
栈空间分配:
- 最小栈 ≥ 128字(512字节)
- 复杂任务需≥256字(1KB)
- 使用
uxTaskGetStackHighWaterMark()验证
状态转换原则:
void vTaskExample(void *pvParameters) {
for(;;) {
// 1. 运行态处理逻辑
ProcessData();
// 2. 主动进入阻塞态(让出CPU)
vTaskDelay(pdMS_TO_TICKS(100));
// 3. 等待同步事件
xSemaphoreTake(xSemaphore, portMAX_DELAY);
}
}
避免常见错误:
-
禁止在中断中调用阻塞API
-
删除任务前释放其占用的资源
-
挂起任务时考虑其对系统的影响
eg:
// 任务A:高优先级
void vTaskA(void *pv) {
while(1) {
// 获取信号量(可能阻塞)
xSemaphoreTake(xSem, portMAX_DELAY);
ProcessCritical();
xSemaphoreGive(xSem);
}
}
// 任务B:低优先级
void vTaskB(void *pv) {
vTaskDelay(100); // 进入阻塞态
// 此时任务A若等待信号量,任务B可运行
xSemaphoreTake(xSem, 0); // 尝试获取
// ...
}
案例
STM32cubeIDE,STM32F103C8T6
任务:
用CubeMX创建:
- OLED显示任务(LED1,LED2)状态;
- LED1任务:控制LED1以500ms周期翻转亮灭;
- LED2任务:控制LED2以1000ms周期翻转亮灭;
- 按键KEY1任务:按下,挂起or删除LED1任务;
- 按键KEY2任务:按下,创建or删除LED2任务;
解析
iic通信控制OLED屏幕
实践
AI给出代码,工程师负责修改,调试等

665

被折叠的 条评论
为什么被折叠?



