【FreeRTOS 手册详解】完整指南:The FreeRTOS Distribution
FreeRTOS :Real Time Engineers Ltd.
《A_Hands-On_Tutorial_Guide》 作者:Richard Barry
本专栏是对 FreeRTOS-《A Hands On Tutorial Guide》的翻译、解释、引申 加以本人一点点理解。
书可以在 FreeRTOS 官网 SUPPORT 下面的 Books & Maunals 找到,即 《Mastering the FreeRTOS Real Time Kernel-A Hands On Tutorial Guide》。
有关 FreeRTOS 接口的详细介绍在 《 Reference Manual 》中。
在开始正文之前,本节先用来介绍一些先验知识,以帮助大家更好更全面的理解 FreeRTOS。
文章目录
什么是 FreeRTOS ?
什么是 RTOS
参考 wiki 可知:
实时操作系统(Real-time operating system, RTOS),又称即时操作系统,它会按照排序执行、管理系统资源,并为开发应用程序提供一致的基础。
实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。
为什么是 FreeRTOS
完全免费、开源、市场占有率高。
创始人 Richard Barry 提供了大量的移植代码和配套文档。基于 FreeRTOS 的 SafeRTOS 经过了安全性验证,侧面表现了 FreeRTOS 安全方面做的也是比较好的。FreeRTOS 代码量少,和 Linux 等其他系统动辄上多少万的代码量相比真是小巧精致,但是也是五脏俱全。
开源、免费、而且提供了大量的帮助和指导文档,Richard Barry 的开源精神,这些实在是非常让人无法拒绝的地方。
了解 FreeRTOS
本专栏将从如下方面了解 FreeRTOS:
两类实时性要求
FreeRTOS 是一个实时内核(或者实时调度器),在其之上可以构建嵌入式程序来满足其硬实时需求。他允许把多个程序组织为独立执行线程的集合。单核处理器下,内核通过检查程序设计者赋予程序的优先级来决定某一个时刻应该执行哪个线程。例如,程序可以被赋予高优先级,来满足其硬实时需求,低的优先级来满足软实时的需求,这会确保硬实时需求的程序总是在软实时需求的程序之前执行。但是优先级赋值是困难的(不总是简单的,are not always that simplistic)。
价值观 value proposition
FreeRTOS 是专业开发的、严格质量把控、健壮、被支持并且不存在任何知识产权模糊,在商业应用程序中免费使用且不需要暴露任何你拥有的源代码,更不要说支付费用。任何时候,想要一个书面的保证、保障或者备份,都有一个简单的低成本的商业升级路径。任何时候都可以选择走商业路径,十分便利(原文 peace of mind comes with you can take opt to commercial route an any time you choose)。在 FreeRTOS 中每个可执行的线程(thread)也被称为任务(task)。
优势
除了满足应用程序硬实时要求之外的优势:
FreeRTOS 特性
1 The FreeRTOS Distribution
1.1 FreeRTOS 文件结构
Freertos port 定义
每种支持的编译器和处理器的组合被认为是一个 freertos port
构建 freertos
Freertos 可以被认为是一个为裸机应用程序提供多任务能力的库。Freertos 是一系列 C 源文件的形式。一些源文件对于所有 freertos port 通用,一些只适用于特定的 freertos port。每个官方的 freertos port 都提供了一个已经配置好的 demo。Demo 应该是拿来就能用,虽然有些发布的比较早,并且只要构建工具一个改变就可能导致构建出现问题。
FreeRTOSConfig.h
Freertos 是通过头文件 FreeRTOSConfig.h 配置的。FreeRTOSConfig.h 为特定应用程序定制 FreeRTOS。例如,其包含了 configUSE_PREEMPTION 等常量,这些常量的设置,定义了会使用协作式调度算法还是抢占式调度算法。FreeRTOSConfig.h 包含了特定应用程序的定义(application specific definitions),其应该放到作为被构建的应用程序的一部分的目录中,而不是放到 FreeRTOS 的源码目录中。推荐从给出的 demo 中相应 port 的 FreeRTOSConfig.h 开始,然后逐步修改适应,无需从头创建。
官方 freertos 的文件结构
在构建应用程序的过程中并不是 freertos 的所有文件都会被用到。文件包含了对所有 freertos port 通用的 freertos 的源码以及 freertos port 相应的 demo project。也包含了 freertos+ 生态的一系列组件和 demo application。
通用源文件
特定 FreeRTOS port 的构建
如果你使用名为“arch”架构的处理器,用名为”cp“的编译器进行构建,那么除了核心源文件,还需要和 FreeRTOS/Source/portable/[cp]/[arch] 下的文件一起构建。
Include path
- Freertos 源文件的头文件 FreeRTOS/Soucre/include
- 特定 freertos port 的源文件 FreeRTOS/Source/portable/[[compiler]/[architecture]
- 到 FreeRTOSConfig.h 的路径
Header Files
一个使用 FreeRTOS API 的源文件必须包含头文件 FreeRTOS.h,然后紧跟着包含要使用的特定函数原型的头文件,例如 task.h、queue.h、semphr.h、timers.h、event_groups.h
1.2 Demo Applications
每个 freertos port 都会至少有一个 demo 可以没有错误和警告的进行构建。FreeRTOS 是在 windows 上开发和测试的,所以当工程在 linux 上进行构建的时候可能偶尔会发生错误。但是错误总是在引用文件名字的时候和字母大小写和斜线的方向有关系。
Demo Application 的目的:
每一个工程都放在 FreeRTOS/Demo 下唯一的子目录中,子目录的名字意义是和 demo 工程相关的 freertos port。所有 demo project 都是通用 demo task 的子集,他们的实现放在 FreeRTOS/Demo/Common/Minimal 目录下。通用代码的存在存粹是为了演示如何使用 FreeRTOS API,他们不实现任何具体的有用的功能。
1.3 创建一个 FreeRTOS 工程
调整提供的 demo project
建议通过调整存在的项目来创建新的项目,这会让工程包含正确的文件,正确安装中断处理程序,以及正确的编译器选项设置。
- 打开提供的一个代码,确保它可以按预料的那样构建和执行
- 删除定义 demo tasks 的源文件,所有放在 Demo/Common 中的文件都可以删除
- 删除 main 函数中除 prvSetupHardware 和 vTaskStartScheduler 外的所有函数调用
- 检查项目能否正常构建
int main(void)
{
prvSetupHardware();
vTaskStartScheduler();
for (;;);
return 0;
}
从头创建一个新工程
推荐从已有的 demo 创建新的工程,如果这不可取的时候,可以按以下步骤创建新工程:
- 使用你的工具链,创建一个新的不包含任何 FreeRTOS 源代码的工程
- 确保工程可以被构建,下载到你的目标硬件,然后执行
- 确保已有的工程可以工作,然后添加如下文件
- tasks.c
- queue.c
- list.c
- timers.c
- event_groups.c
- All c and assembler files (FreeRTOS/portable/[compiler]/[architecture])
- heap_n.c(FreeRTOS/portable/MemMang)
- 复制 demo 为当前 port 提供的 project 中的 FreeRTOSConfig.h
- 增加下面的头文件搜索路径
- FreeRTOS/Source/inlcude
- FreeRTOS/Source/portable/[compiler]/[architecture]
- 包含 FreeRTOSConfig.h 的目录
- 从相关 demo 中复制编译器的设置
- 根据相关 demo 和 port 的相关描述,安装任何可能必要的中断处理程序
1.4 数据类型和编码风格
一些编译器的 char 是 unsigned 的,一些事 unsigned 的。处于这个原因,FreeRTOS 的代码每次使用 char 都会赋值。除非 char 用来存储 ASCII 字符,或者 char * 指向一个字符串。而且从来不使用 int。
Variable names
前缀:
Function names
前缀:返回值类型 + 函数定义所在的文件
制表符
一个 tab 等于 4 个空格
宏名
宏以大写形式书写,前缀为小写的宏定义所在位置的文件。信号量 API 几乎全是写为一系列宏,这些宏遵守函数命名规则,而不是宏的命名规则。
贯穿整个 FreeRTOS 的宏定义: