通过BUG(prvIdleTask、pxTasksWaitingTerminatio不断跳转问题)了解空闲函数(prvIdleTask)和TCB

一、前言与问题

在基于 FreeRTOS 的嵌入式系统中,我使用 STM32F1 开发一个 MQTT 客户端应用,涉及两个主要任务:

  • ATRecvParser:负责解析 Wi-Fi 模块的 AT 命令响应(如 OK、ERROR 和 +IPD 数据)。
  • MQTT_Client_Task:通过 MQTT 协议连接服务器,订阅主题并发布消息。

在运行过程中,程序出现以下异常:

  1. 调用栈跳转 :调试器显示程序在 prvIdleTask(空闲任务)和 prvCheckTasksWaitingTermination(FreeRTOS 内部清理函数)之间反复跳转,无法正常运行。
  2. TCB 异常:任务控制块(TCB)的 pxTCB 值显示为 0xA5A5A5A5(未初始化值),表明 TCB 可能损坏。

二、了解空闲任务prvIdleTask、pxTasksWaitingTerminatio、TCB

1、什么是空闲任务-----prvIdleTask

1.调用时间

在没有其他任务可运行时(没有任何其他任务处于就绪态时)保持 CPU 忙碌

2.调用例子:

系统中有三个任务:defaultTaskATRecvParserMQTT_Client_Task

  • defaultTask 调用 osDelay(1),几乎一直处于阻塞态。
  • ATRecvParser 因 HAL_AT_Secv 阻塞。
  • MQTT_Client_Task 已删除,不再调度。

此时,当系统中无其他就绪任务时,调度器将 CPU 分配给 prvIdleTask。

3.特征

  • 自动创建,优先级最低(通常为 0)。
  • prvIdleTask 是一个无限循环任务,包含 for(;;) 循环,定期检查系统状态。
  • 执行低优先级操作(如电源管理钩子)。
  • 调用 prvCheckTasksWaitingTermination 清理已删除任务。
  • (避免进入低功耗模式,视配置而定)。

二、什么是pxTasksWaitingTerminatio

  • prvCheckTasksWaitingTermination
    • 这是 FreeRTOS 内部函数(定义在 tasks.c 中),负责检查并清理 pxTasksWaitingTermination 列表中的已删除任务。
    • 当任务被 vTaskDelete 标记为待删除时,FreeRTOS 将其 TCB 加入该列表。prvCheckTasksWaitingTermination 会释放 TCB 和栈内存,但前提是任务列表有效且资源可用。
    • 如果 TCB 指针无效或列表遍历出错,函数可能进入死循环或异常状态。

关系:

  • prvIdleTask 是 prvCheckTasksWaitingTermination 的调用者之一。空闲任务在系统空闲时运行,负责清理工作,因此当 MQTT_Client_Task 删除后,prvIdleTask 会尝试调用 prvCheckTasksWaitingTermination。

三、TCB

TCB(Task Control Block,任务控制块) 是 FreeRTOS 中用于管理任务的核心数据结构。它存储了一个任务的所有关键信息,以便 FreeRTOS 调度器能够正确地创建、调度、暂停或删除任务。TCB 包含以下主要内容:任务的栈指针。任务状态:如运行态、就绪态、阻塞态等。任务优先级:决定调度顺序。任务名称:用于调试。

以下是一个TCB的内容:在这里展现的是一个损坏的TCB,正常 TCB:pxTCB 应为有效地址(如 0x20001000),pxTopOfStack 指向栈顶,xStateListItem 包含有效列表项。

问题:

每个任务都有一个独立的 TCB。那我上面的prvCheckTasksWaitingTermination();有不是一个任务,为什么可以看见他的TCB?

  • pxTCB 并不是 prvCheckTasksWaitingTermination 自己的 TCB(因为它不是任务),而是它正在处理的某个已删除任务(如 MQTT_Client_Task)的 TCB。
  • FreeRTOS 的 TCB 是动态分配的,当任务删除时,TCB 被加入 pxTasksWaitingTermination,等待清理。prvCheckTasksWaitingTermination 从列表中取出 TCB,赋值给局部变量 pxTCB 进行处理。

四、TCB损坏导致pxTasksWaitingTerminatio和prvIdleTask之间跳转

正常情况下,MQTT_Client_Task 删除后,ATRecvParser 阻塞,系统中无就绪任务,prvIdleTask 运行并通过 prvCheckTasksWaitingTermination 清理资源,随后持续运行直到有任务就绪。

TCB 损坏原因

  • 栈溢出:MQTT_Client_Task 的栈(2048 字节)可能不足,溢出覆盖 TCB 内存。
  • 内存不足:堆内存(2032 字节)可能无法分配 TCB 或栈,导致无效指针。
  • 任务删除异常:vTaskDelete(NULL) 在网络操作未完成时执行,TCB 状态不一致。
  • 互斥锁死锁:at_ret_mutex 未解锁,阻塞 ATSendCmd,影响 mqtt_connect,导致 TCB 未正确更新。

我就是因为删除的任务重,at_ret_mutex 未解锁就把任务删除了,导致资源为释放,TCB损坏

相关推荐
恒锐丰科技林技术员1 小时前
EG2302 半桥驱动芯片详解:高压半桥高性价比栅极驱动方案
经验分享·嵌入式硬件·硬件工程
会不再投降2194 小时前
初识嵌入式历史发展与生态
stm32
LCG元5 小时前
STM32 定时器编码器接口模式电机测速实战:从 CubeMX 配置到 M 法转速计算与溢出处理
stm32·单片机·嵌入式硬件
星河单片机8 小时前
STM32驱动WaterSensor水位传感器+OLED显示完整原理与实验
stm32·单片机·嵌入式硬件
子文雨9 小时前
基于 uC3845 与 ATtiny13 双芯片架构的 8.4V/2.5Ah 锂电池智能充电器设计
单片机·嵌入式硬件·算法
快秃头的码农9 小时前
esp32-s3移植lvgl总结
嵌入式硬件·esp32-s3
恒锐丰科技林技术员10 小时前
EG1191 宽压降压 DC‑DC 芯片解析:高性价比工业电源方案
经验分享·嵌入式硬件·硬件工程
千秋岁rr11 小时前
8TIM编码器接口
stm32
智购科技无人售货机工厂店11 小时前
2026自动售货机大屏交互设计原则:从信息层级到视觉动线的工程实践~YH
运维·python·单片机·嵌入式硬件·自动化·交互
艾芯微科技14 小时前
SKY13370‑374LF|0.5‑6GHz SPDT 射频开关,WLAN/LTE 射频前端实用器件
网络·单片机·嵌入式硬件·集成测试·51单片机