通过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损坏

相关推荐
小尧嵌入式11 分钟前
C++基础语法总结
开发语言·c++·stm32·单片机·嵌入式硬件·算法
white-persist11 分钟前
【攻防世界】reverse | IgniteMe 详细题解 WP
c语言·汇编·数据结构·c++·python·算法·网络安全
2401_853448231 小时前
STM32F103C8T6---OLED显示屏
stm32·单片机·oled
沐欣工作室_lvyiyi1 小时前
基于单片机的居家智能音箱系统(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·智能音箱
沐欣工作室_lvyiyi1 小时前
基于单片机的飞机客舱窗帘控制系统(论文+源码)
单片机·嵌入式硬件·毕业设计·窗户
CHY_1282 小时前
JESD204B 协议解析(4)Subclass2 时序分析
嵌入式硬件·fpga开发·jesd204
Bona Sun2 小时前
单片机手搓掌上游戏机(十六)—pico运行fc模拟器之程序修改烧录
c语言·c++·单片机·游戏机
小邓   ༽3 小时前
50道C++编程练习题及解答-C编程例题
c语言·汇编·c++·编程练习·c语言练习题
Bona Sun4 小时前
单片机手搓掌上游戏机(十三)—pico运行fc模拟器之硬件准备
c语言·c++·单片机·游戏机
Bona Sun4 小时前
单片机手搓掌上游戏机(十八)—pico运行fc模拟器之更大屏幕
c语言·c++·单片机·游戏机