FreeRTOS学习笔记(更新中)
1. 简介
1.1 RTOS简介
RTOS(实时操作系统)是指一类系统,如 FreeRTOS,uC/OS,RTX,RT-Thread 等,都是 RTOS 类操作系统。
FreeRTOS 由美国的 Richard Barry 于 2003 年发布。
FreeRTOS 于 2017 年被亚马逊收购,改名为 AWS FreeRTOS。
1.2 FreeRTOS优势
FreeRTOS 通过 MIT 开源许可免费分发,包括一个内核和一组不断丰富的 IoT 库,适用于所有行业领域。FreeRTOS 的构建突出可靠性和易用性。
-
开源和免费:FreeRTOS是一款开源的RTOS,采用MIT许可证发布,可以免费使用、修改和分发。
-
轻量级设计:FreeRTOS注重轻量级设计,适用于资源受限的嵌入式系统,不占用过多内存和处理器资源。
-
广泛应用:FreeRTOS在嵌入式领域得到广泛应用,包括工业自动化、医疗设备、消费电子产品、汽车电子等。
-
多平台支持:FreeRTOS的设计注重可移植性,可以轻松地移植到不同的硬件平台,支持多种处理器架构。
-
丰富的功能:提供了多任务调度、任务通信、同步等功能,适用于复杂的嵌入式应用场景。
简单来说:使用人数多,轻量级,开源免费,兼容性强,功能丰富。
2. FreeRTOS基础知识
2.1 多任务处理
使用多任务操作系统可以简化原本复杂的软件应用程序的设计:
-
操作系统的多任务处理和任务间通信功能允许将复杂的应用程序 划分为一组更小且更易于管理的任务。
-
这种划分可以简化软件测试,确保团队分工明确,并促进代码复用。
-
复杂的时序和排序细节将由 RTOS 内核负责,从而减轻了应用程序代码的负担。
简单来说:FreeRTOS可以帮助我们把复杂的项目细分为一小块一小块。
2.2 多任务处理与并发
常规单核处理器一次只能执行一个任务,但多任务操作系统可以快速切换任务, 使所有任务看起来像是同时在执行。下图展示了 三个任务相对于时间的执行模式。任务名称用不同颜色标示,并写在左侧。时间从左向右移动, 彩色线条显示在特定时间执行的任务。上方展示了所感知的并发执行模式, 下方展示了实际的多任务执行模式。
简单理解:单核就是一个厕所,多核就是多个厕所。如果只有一个厕所,同一个时间只能一个人上厕所。但是想要同时上厕所,通过调度多人快速轮循上厕所看起来像是多人一起上厕所。
2.3 任务调度
由上可知想要看起来像多人上厕所,就需要一个管理人员负责调度,所以任务调度器就出现了。
调度器负责决定在任何特定时间哪个人去上厕所。
FreeRTOS 默认使用固定优先级的抢占式调度策略,对同等优先级的任务执行时间片轮询调度:
-
抢占式调度:FreeRTOS采用抢占式调度方式,允许更高优先级的任务在任何时刻抢占正在执行的低优先级任务。这确保了高优先级任务能够及时响应,并提高了系统的实时性。
-
时间片轮询:在相同优先级的任务之间,FreeRTOS采用时间片轮转策略。每个任务执行一个时间片,如果有其他同优先级的任务等待执行,则切换到下一个任务。这有助于公平地分配CPU时间。
但是并不是说高优先级的任务会一直执行,导致低优先级的任务无法得到执行。如果高优先级任务等待某个资源(延时或等待信号量等)而无法执行,调度器会选择执行其他就绪的高优先级的任务。
简单理解:坐飞机的话分为vip通道和普通通道,你是vip说明你优先级高,你可以先上飞机。这就是抢占式调度。时间片轮训类似A,B,C三个人同时想上厕所(优先级相同),A先去拉一会(拉一个时间片)然后出出来,B再去拉一会(拉一个时间片)然后出出来,C再去拉一会(拉一个时间片)然后出出来,然后一直循环
2.4 任务状态
FreeRTOS中任务共存在4种状态:
-
运行态:当任务实际执行时,它被称为处于运行状态。如果运行 RTOS 的处理器只有一个内核, 那么在任何给定时间内都只能有一个任务处于运行状态。注意在STM32中,同一时间仅一个任务处于运行态。
-
就绪态:准备就绪任务指那些能够执行(它们不处于阻塞或挂起状态), 但目前没有执行的任务, 因为同等或更高优先级的不同任务已经处于运行状态。
-
阻塞态:如果任务当前正在等待延时或外部事件,则该任务被认为处于阻塞状态。
-
挂起态:类似暂停,调用函数 vTaskSuspend() 进入挂起态,需要调用解挂函数vTaskResume()才可以进入就绪态。
只有就绪态可转变成运行态,其他状态的任务想运行,必须先转变成就绪态。转换关系如下:
这四种状态中,除了运行态,其他三种任务状态的任务都有其对应的任务状态列表:
-
就绪列表:pxReadyTasksLists[x],其中x代表任务优先级数值。
-
阻塞列表:pxDelayedTaskList。
-
挂起列表:xSuspendedTaskList。
每种状态都维护了一个列表List(其实用的链表):
就绪态是特殊的:
① 维护一个32bit的变量,对应优先级有任务,对应的bit位置1,方便查找;
② 每一个优先级,都单独维护了一个列表(链表),相同优先级的任务在同一个列表中
代码实现:如果想使用状态机实现一个音乐播放器
char status = 'C';switch (status)case 'A' :播放处理;if(暂停按键) status = 'B';if(停止按键) status = 'C';case 'B' : 暂停处理;if(停止按键) status='C';if(播放按键) status='A';case 'C' : 停止处理;if(播放按键) status = 'A';