FreeRTOS-ARM架构、TCB结构体,调度机制

本文详细解析ARM架构的组成部分,探讨CPU、RAM和FLASH的作用。重点讲解任务切换时寄存器保存策略,以及TCB、调度机制(优先级、状态和调度流程)。涉及TCB结构、中断调度和链表在调度中的运用,包括pxReadyTasksList、pxDelayedTaskList和pxPendingReadyList。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ARM架构

对于ARM架构来说,主要有3部分构成:CPU,RAM,FLASH。

CPU内部主要是运算单元和寄存器单元,可以读写RAM,修改内存,也可以读取FLASH里的汇编代码。

RAM为内部存储空间,有栈的数据结构,对于地址有内存存储,可被CPU改写。

FLASH为存储代码的空间,可被CPU读取。

Q:在任务切换时,所有寄存器都要保留吗?
A:都要保留,但是对于硬件中断来说,只需要保存用到的寄存器即可;对于子函数来说,不需要保存子函数用到的寄存器

创建任务:

在这里插入图片描述
第一个为函数地址,赋给PC寄存器
第二个为任务名
第三个为栈大小 每个任务都有自己的栈栈的大小由局部变量和调用深度决定
第四个为任务函数的入口参数,存在R0里

TCB结构体

对于每个任务在内存总都有相应的TCB结构体包含栈顶,两个链表(雾),优先级,栈的起始
在这里插入图片描述

在保存现场时,将16个寄存器的数据记录放在RAM栈中,下一次重新运行的时候从PC寄存器的地址运行

调度机制

优先级:
高优先级的任务,优先执行,可以抢占第有相机的任务
高优先级的任务不停止,低优先级的任务永远无法执行
同等优先级的任务,轮流执行:时间片轮转,最后放进链表的先执行,然后再从链表头运行,每个任务运行之后尾插到链表尾部

状态

运行态:running
就绪态:ready
阻塞:blocked(等待某件事
暂停:suspend(休息去了

怎么取出要运行的任务?
找到最高优先级的运行态,就绪态任务运行
如果平级,轮流执行:派对,链表前面的先运行,运行1个tick后,去链表尾部排队。

谁来调度?
Tick中断:每1ms产生一个中断,中断后调用Tick中断函数
Tick中断函数:
1)取出下一个TASK
2)保存当前Task;回复新的Task

链表理解调度机制

共有3种链表

pxReadyTasksList//如果有5个优先级(0-4)就由5个组成,通常在存在于pxReadyTasksList[0]链表尾部有一个空闲任务idle task,用于清除销毁任务的内存

pxDelayedTaskList//延迟类,先将该任务从pxReadyTasksList放进pxDelayedTaskList,休眠Xms,
每次Tick中断检查pxDelayedTaskList内的Task计时有没有到,
当到达设置时间点,将这个Task放回其优先级对应的pxReadyTasksList,然后再次调度此Task。

pxPendingReadyList

可抢占:高优先级的任务先运行
时间片轮转:同优先级的任务轮流执行
空闲任务礼让:如果同时优先级0的其他就绪任务,空闲任务主动放弃一次运行机会
最低优先级的中断比最高优先级的任务优先级高

<think>好的,我现在要回答用户的问题:如何在Keil中通过Debug查看FreeRTOSTCB。首先,我需要回忆一下FreeRTOS的任务控制块(TCB)的结构和作用。TCB是存储任务状态、堆栈指针、优先级等信息的数据结构,了解如何查看它对于调试任务相关问题非常重要。 接下来,我需要考虑Keil MDK的调试环境。用户可能使用的是Keil uVision,所以需要指导他们在Debug模式下找到相关的窗口,比如Watch窗口、Call Stack窗口或者Memory窗口。同时,FreeRTOS可能有自己的调试插件或视图,可以显示任务信息,这需要确认。 然后,步骤应该是先启动调试会话,然后暂停程序,接着找到当前运行的TCB。可能需要知道FreeRTOS内部如何管理任务列表,比如通过pxCurrentTCB变量或者任务列表链表。在Keil中,用户可能需要手动添加这些变量到Watch窗口,或者使用表达式来查看TCB的内容。 另外,还需要考虑内存查看,因为TCB是一个结构体,用户可能需要知道其内存地址,并通过Memory窗口直接查看。这里需要注意结构体的各个字段在内存中的偏移量,比如uxPriority、pxStack等字段的位置。 还要提醒用户关于调试时的配置,比如在FreeRTOSConfig.h中是否启用了必要的宏,比如configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS,这些可能会影响调试信息的可用性。 可能遇到的困难包括:找不到TCB变量,结构体字段显示不正确,或者内存地址错误。需要提供一些常见问题的解决方法,比如检查变量名称是否正确,确认FreeRTOS的版本是否匹配,或者使用正确的数据类型来查看内存。 最后,应该总结一下步骤,让用户能够一步步跟随操作,并强调注意事项,确保他们能够顺利查看TCB信息。</think>在Keil MDK中通过Debug模式查看FreeRTOS任务控制块(TCB)的步骤如下: --- ### 一、基础准备 1. **工程配置** - 确保在`FreeRTOSConfig.h`中启用调试相关宏: ```c #define configUSE_TRACE_FACILITY 1 // 启用跟踪设施 #define configUSE_STATS_FORMATTING_FUNCTIONS 1 // 允许格式化任务信息 ``` 2. **编译与进入调试模式** - 编译工程后点击Keil的`Start/Stop Debug Session`按钮(或按`Ctrl+F5`)进入调试模式。 --- ### 二、查看TCB的3种方法 #### 方法1:通过Watch窗口直接观察 1. 在调试模式下打开`Watch 1`窗口 2. 添加以下表达式: - `pxCurrentTCB`:查看当前运行任务的TCB地址 - `pxReadyTasksLists`:查看就绪任务链表 - `xTasksWaitingTermination`:查看等待删除的任务链表 3. **展开TCB结构体** 输入例如:`(TaskHandle_t)pxCurrentTCB->uxPriority` 可查看任务优先级。 --- #### 方法2:使用Call Stack + Locals窗口 1. 暂停程序执行(点击暂停按钮或按`Pause`键) 2. 在`Call Stack + Locals`窗口中: - 展开当前任务的调用栈 - 找到`vTaskSwitchContext()`函数(任务切换上下文函数) - 查看局部变量中的TCB指针 --- #### 方法3:内存窗口直接查看 1. 获取TCB地址: - 在Watch窗口输入`pxCurrentTCB`获取当前任务TCB的十六进制地址(如`0x20001234`) 2. 打开`Memory 1`窗口 3. 输入地址并选择`unsigned long`格式显示 4. **解析关键字段**(以ARM Cortex-M为例): ``` 偏移量 字段 说明 0x00 pxTopOfStack 当前栈顶指针 0x04 xStateListItem 任务状态列表项 0x18 uxPriority 任务优先级 0x1C pxStack 任务堆栈起始地址 0x24 pcTaskName 任务名称字符串指针 ``` --- ### 三、高级调试技巧 1. **任务列表查看** 在Watch窗口添加表达式: ```c (tskTCB *)&xTaskList[0] // 查看任务链表头节点 ``` 通过`pxNext`指针遍历整个任务链表。 2. **使用FreeRTOS插件** - 安装`FreeRTOS Debug Helpers`插件(需单独下载) - 在调试模式下通过`View > FreeRTOS Task List`直接可视化查看所有TCB信息 --- ### 四、注意事项 1. **内存对齐问题** Cortex-M系列要求4字节对齐,TCB地址必须是4的倍数,否则可能触发HardFault。 2. **TCB结构体版本差异** FreeRTOS不同版本的TCB结构可能有差异,建议对照源码中的`tskTaskControlBlock`定义。 3. **优化级别影响** 若编译优化级别过高(如-O3),可能导致某些变量无法观察,建议调试时使用-O0优化。 --- 通过以上步骤,可以系统地查看和分析FreeRTOS任务的实时状态信息,快速定位任务调度、优先级或堆栈相关问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉山有客不自赏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值