FreeRTOS源码理解(一)——FreeRTOS思路梳理

文章详细分析了FreeRTOS源码中的关键组件,包括任务调度、中断处理、队列与信号量的实现原理,以及事件组和任务通知的工作方式。通过理解这些核心概念,读者能更好地掌握FreeRTOS的内部运作机制。

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

FreeRTOS源码理解(一)——FreeRTOS思路梳理

FreeRTOS源码理解(二)——中断和列表项

FreeRTOS源码理解(三)——任务

FreeRTOS源码理解(四)——任务调度器

FreeRTOS源码理解(五)——任务切换

FreeRTOS源码理解(六)——时间管理

FreeRTOS源码理解(七)——队列

FreeRTOS源码理解(八)——信号量

FreeRTOS源码理解(九)——事件组和任务通知

FreeRTOS源码理解(十)——软件定时器和空闲任务

FreeRTOS源码理解(十一)——内存管理

FreeRTOS源码理解(十二)——汇总

FreeRTOS思路梳理

前置知识

中断屏蔽:芯片会有个中断屏蔽相关的寄存器,往这个寄存器中写入一个值,芯片会自动将优先级小于这个值的中断屏蔽掉

滴答定时器:为OS提供心跳,计时,本质仍然是中断

PendSV异常:本质是中断,它的特点是可以缓期执行——在ISR被占用时可以暂时挂起

PSP和MSP:有些芯片会提供有两个堆栈指针,MSP用于OS内核和中断异常处理,PSP用于任务

列表:可以看成是双向链表

列表项:可以看成列表里面的节点

关于任务调度

在FreeRTOS中,任务被抽象成了一个TCB_t结构体,这个结构体中有这个任务所有的信息

在TCB中有两个列表项,一个表示状态,一个表示事件

列表项中存储一个指向所属TCB的指针,所以移动列表项就可以完成对TCB状态的更改——就像衣架,移动钩子,钩子下面的衣服也就跟着移动了

同时列表项中还有一个指向所属列表的指针,它一般用来表示在等待事件、信号量、队列等

FreeRTOS定义了很多种列表,主要分状态列表和事件列表,列表按value值排序,value表示被处理的优先度

状态列表主要是用来表示任务状态,有就绪列表、等待延时列表、挂起列表和等待唤醒列表

唤醒任务、阻塞任务等操作均是通过操作TCB中的列表项到相应的列表中完成

FreeRTOS在PendSV中执行任务调度和任务切换,在每一次进入滴答定时器中断后,会自动悬起一个PendSV中断(P.S.因为PendSV优先级允许缓期执行,所以会ISR未被占用后进行任务调度,适合做任务调度)

在PendSV中断中,OS直接选择就绪列表中优先级最高的那个任务进行切换执行;在任务切换时,会进行上下文切换,即保护现场(将运行环境,寄存器变量等压入任务堆栈中),恢复现场(从任务堆栈中按规则取出数据和寄存器的值进行恢复)

当任务阻塞时,如果有等待时间则将任务状态TCB移动到延时等待列表中,延时列表根据延时时间排序

在每个滴答定时器中断中都会更新系统时间,并检查是否有延时到的任务需要唤醒,唤醒流程——将列表项移到就绪列表中,将此TCB的任务列表项归属置NULL

关于队列和信号量

队列是利用一片内存来存储数据,队列结构体中有两个列表,一个表示入队阻塞的任务(队列满了),一个表示出队阻塞的任务(队列为空)

队列为空时,要出队的任务的事件列表项将被挂载在队列中的列表中,如有等待时间移动状态列表项到延时等待列表中,如果死等则挂起任务

队列满时,入队的任务操作流程相同

当可以入队时,将消息拷贝到消息队列中,然后按优先级唤醒相应因出队阻塞的任务;可以入队时,操作类似

各种信号量底层均是队列,利用队列完成信号量的上锁等待等操作

互斥信号量较其他信号量多了优先级翻转,在等待时,互斥信号量会将正在持有互斥量的任务优先级提高到和自己一样

关于事件组

事件组的实现和队列类似,事件组的结构体中有一个列表,列表存储等待事件组某些事件发生的任务

当任务调用等待某一事件组的某些事件时,会将此任务的事件列表项挂载在此列表下,列表项的value值存储等待哪些事件的发生,同时将其状态切换为延时阻塞或挂起

当事件组被写入某些事件时,遍历列表中的所有任务,查看是否满足要求,满足则唤醒,最后根据要求清除相应的事件标志位

关于任务通知

修改TCB中的元素的值和任务通知的状态变量

文档汇总

文档汇总

### 学习 FreeRTOS 源码的必要性和重要性 学习 FreeRTOS 源码对于深入理解其工作机制以及如何高效地应用于实际项目具有重要意义。以下是对其必要性和重要性的具体分析: #### 1. 提升对操作系统的本质认知 通过研究 FreeRTOS 源码,开发者可以深入了解操作系统的核心概念,例如任务调度、上下文切换、中断管理等机制。这种底层的理解有助于开发人员更好地设计和优化自己的应用程序[^1]。 #### 2. 掌握内存分配策略 FreeRTOS 支持多种堆内存管理方案(如 `heap_1` 至 `heap_5`),其中最常用的为 `heap_4`。通过对源码的学习,能够掌握不同堆实现方式的特点及其适用场景。例如,在某些情况下可能需要自定义堆数组以满足特定硬件需求,这可以通过阅读如下代码片段来加深认识: ```c extern uint8_t ucHeap[configTOTAL_HEAP_SIZE]; #else PRIVILEGED_DATA static uint8_t ucHeap[configTOTAL_HEAP_SIZE]; #endif /* configAPPLICATION_ALLOCATED_HEAP */ ``` 上述代码展示了当未启用 `configAPPLICATION_ALLOCATED_HEAP` 宏时,默认静态声明块全局变量作为 RTOS 堆空间;而如果启用了该宏,则允许外部程序自行定义此区域的位置与属性[^3]。 #### 3. 调试复杂问题的能力增强 熟悉 FreeRTOS 的内部结构可以帮助工程师快速定位并解决运行过程中遇到的各种异常情况。比如默认创建的任务会设置固定优先级高于最低级别,并且具备可调整栈尺寸参数等功能特性描述如下所示: ```c /* Create the idle task at the lowest possible priority and assign it a stack that is only large enough to call the idle hook (if defined). */ xTaskCreate( prvIdleTask, "IDLE", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); ``` 这里提到主函数执行入口处调用的 `app_main()` 方法所在主线程也遵循相似原则设定初始状态信息[^2]。因此旦发现任何关于线程行为不符合预期的现象都可以回溯到相应初始化部分查找原因。 #### 4. 实现定制化功能扩展 基于已有的框架基础之上进行二次开发往往离不开参照官方提供的标准模板来进行修改适配工作。只有彻底弄清楚每个模块背后的设计思路才能做到游刃有余地完成此类任务。无论是增加新的服务接口还是改进现有算法效率等方面都需要依赖扎实的基础理论支撑再加上实践经验积累共同作用下达成目标效果最佳表现形式呈现出来给最终使用者带来便利体验价值最大化体现出来。 --- ### 结论 综上所述,学习 FreeRTOS 源码不仅能够让开发者获得更深层次的技术能力提升,还能有效促进产品性能优化及稳定性提高等方面的进步成果展现出来供更多同行借鉴参考使用形成良性循环推动整个行业向前发展迈进大步距离理想中的未来世界越来越近步之遥即可触碰得到梦想成真时刻即将到来值得期待不已!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值