目录:
1 FreeRTOS 的特点
- 支持抢占式调度,合作式调度和时间片调度。
- SafeRTOS 作为 FreeRTOS 的衍生品大大提高了 FreeRTOS 在代码完整性方面的信心。
- 用于低功耗的 Tickless 模式。
- 支持 35 种系统架构。
- FreeRTOS-MPU 支持 M3/M4/M7 内核的 MPU(内存保护单元)。
- 设计的简单易用,典型的内核使用大小在 4k-9k。
- 移植非常简单,代码主要用 C 编写。
- 同时支持合作式和抢占式任务。
- 支持消息队列、 二值信号量、 计数信号量、 递归信号量和互斥信号量,可用于任务与任务间的消息传
递和同步, 任务与中断间的消息传递和同步。 - 优先级继承方式的互斥信号量。
- 高效的软件定时器。
- 强大的跟踪执行函数。
- 堆栈溢出检查。
- 提供丰富的,配置好的工程例子。
- 提供论坛技术支持, 有可选的商业支持和许可版本。
- 任务的数量不限。
- 任务优先级数量不限。
- 多个任务可以分配相同优先级, 即支持时间片调度。
- 免费的开发工具。
- 免费的嵌入式软件源码。
- 免版权费。
2 高质量的管理机制
FreeRTOS 经过非常严格的高质量管理,不仅表现为规范的源码,还主要表现在以下几个方面:
- 在关键代码区和中断里面从不会执行像遍历列表这样的时间非确定性任务。
- 高效的软件定时器,不需要损耗额外的 CPU 时间,除非需要执行定时器任务。
- 任务间直接的消息传递,相对于通用的信号量、 消息队列等方式,速度较快。
- 不需要定时的去查询阻塞或者挂起列表。
- FreeRTOS 的队列使用模型( 消息队列、 互斥信号量、 信号量等都是基于此队列模式设计的)使得它简单并且灵活。
- FreeRTOS 的队列是其它通信和同步机制的基础,这种代码复用方式可以有效地降低整体代码的大小,并且反过来有助于调试。
3 FreeRTOS 的命名规则
变量
- uint32_t 定义的变量都加上前缀 ul。 u 代表 unsigned 无符号, l 代表 long 长整型。
- uint16_t 定义的变量都加上前缀 us。 u 代表 unsigned 无符号, s 代表 short 短整型。
- uint8_t 定义的变量都加上前缀 uc。 u 代表 unsigned 无符号, c 代表 char 字符型。
- stdint.h 文件中未定义的变量类型,在定义变量时需要加上前缀 x,比如 BaseType_t 和
TickType_t 定义的变量。- stdint.h 文件中未定义的无符号变量类型,在定义变量时要加上前缀 u, 比如 UBaseType_t 定义的变量要加上前缀 ux。
- size_t 定义的变量也要加上前缀 ux。
- 枚举变量会加上前缀 e。
- 指针变量会加上前缀 p,比如 uint16_t 定义的指针变量会加上前缀 pus。
- 根据 MISRA 代码规则, char 定义的变量只能用于 ASCII 字符,前缀使用 c。
- 根据 MISRA 代码规则, char *定义的指针变量只能用于 ASCII 字符串, 前缀使用 pc。
函数
- 加上了 static 声明的函数, 定义时要加上前缀 prv, 这个是单词 private 的缩写。
- 带有返回值的函数, 根据返回值的数据类型,加上相应的前缀,如果没有返回值,即 void 类型,函数的前缀加上字母 v。
- 根据文件名, 文件中相应的函数定义时也将文件名加到函数命名中,比如 tasks.c 文件中函数 vTaskDelete,函数中的 task 就是文件名中的 task。
宏定义
- 根据宏定义所在的文件,文件中的宏定义声明时也将文件名加到宏定义中,比如宏 configUSE_PREEMPTION
是定义在文件
FreeRTOSConfig.h
里面。 宏定义中的 config 就是文件名中的 config。 另外注意,前缀要小写。- 除了前缀,其余部分全部大写, 同时用下划线分开。
3 FreeRTOS 中数据类型
FreeRTOS 使用的数据类型主要分为 stdint.h 文件中定义的和自己定义的两种
FreeRTOS 主要自定义了以下四种数据类型:
- TickType_t
如果用户使能了宏定义 configUSE_16_BIT_TICKS, 那么 TickType_t 定义的就是 16 位无符号数, 如果没有使能,那么 TickType_t 定义的就是 32 位无符号数。 对于 32 位架构的处理器,一定要禁止此宏定义,即设置此宏定义数值为 0 即可。- BaseType_t
这个数据类型根据系统架构的位数而定,对于 32 位架构, BaseType_t 定义的是 32 位有符号数,对于 16 位架构, BaseType_t 定义的是 16 位有符号数。 如果 BaseType_t 被定义成了 cha型,要特别注意将其设置为有符号数,因为部分函数的返回值是用负数来表示错误类型。- UBaseType_t
这个数据类型是 BaseType_t 类型的有符号版本。- StackType_t
栈变量数据类型定义, 这个数量类型由系统架构决定,对于 16 位系统架构, StackType_t 定义的是16 位变量,对于 32 位系统架构, StackType_t 定义的是 32 位变量。- UBaseType_t
这个数据类型是 BaseType_t 类型的有符号版本。- StackType_t
栈变量数据类型定义, 这个数量类型由系统架构决定,对于 16 位系统架构, StackType_t 定义的是16 位变量,对于 32 位系统架构, StackType_t 定义的是 32 位变量。
代码清单 FreeRTOS 中的数据类型重定义
/* 数据类型重定义 */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif
表格 FreeRTOS 通用宏定义
宏 | 实际的值 |
---|---|
pdTRUE | 1 |
pdFALSE | 0 |
pdPASS | 1 |
pdFAIL | 0 |
4 FreeRTOS 的排版和注释
缩进
Tab 制表符用于缩进, Tab 一次缩进 4 个字符空间。
注释
源码中主要是采用/* */的形式进行注释,不采用 C++中的双斜杠风格来注释。
5 FreeRTOS 和 OpenRTOS、SafeRTOS 的区别
FreeRTOS 和 OpenRTOS 有相同的源码, 只是 OpenRTOS 是受商用授权保护。
SafeRTOS 被安全方面的专家重新做了设计, SafeRTOS 获得的安全认证都非常重要 。