FreeRTOS阅读源码之编程风格
- 嵌入式开发
- 17小时前
- 10热度
- 0评论
FreeRTOS 阅读源码之编程风格
一、编程风格
FreeRTOS 严格遵循匈牙利命名法——看到名字就能推断出返回值类型、所属模块和参数类型。
变量看前缀,类型一目了然 → u/c/s/l/x/p
函数三段式,返回+模块+动作 → vTaskDelay / xQueueSend
宏看开头词,就知在哪定义 → config/pd/port/task
1.1 数据类型
FreeRTOS 对标准 C 类型进行了重定义(定义在 portmacro.h 中),加 port 前缀——port 表示接口,将 FreeRTOS 移植到处理器上时,需要用接口文件把它们连接在一起。
在 STM32CubeIDE 中,该文件位于:Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h

/* portmacro.h 中的数据类型重定义 */
#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
portXXX 类型,直接用 uint32_t 等标准类型完全可以。
int 从不使用!FreeRTOS 只用
short(16 位)和 long(32 位),因为 int 在不同架构上大小不同。
char 是有符号还是无符号。KEIL 默认 char 为无符号,可通过 Options → C/C++ → Plain Char is Signed 勾选改为有符号。
1.2 变量名
变量名的前缀表示数据类型。无符号加 u,指针加 p,可组合(如 uc = unsigned char,pc = char 指针)。
| 前缀 | 含义 | 举例 |
|---|---|---|
c |
char | cCharToSend |
s |
short | sTaskPriority |
l |
long | lBytesReceived |
x |
BaseType_t / 结构体 / 句柄 | xQueue, xSemaphore |
u |
unsigned(组合用) | ucMotorSpeed, ulTimerCount |
p |
pointer(组合用) | pcTaskName, pvParameters, pxTopOfStack |
1.3 函数名
格式:返回值前缀 + 所属模块(= 所在文件名) + 功能描述
私有函数额外加 prv(private)前缀。
| 返回值前缀 | 类型 | 举例 |
|---|---|---|
v |
void | vTaskDelay() |
x |
BaseType_t / 句柄 | xTaskCreate() |
pv |
void* | pvPortMalloc() |
ux |
UBaseType_t | uxTaskPriorityGet() |
prv |
私有函数 | prvTaskIsTaskSuspended() |
| 模块名 | 定义在 | 说明 |
|---|---|---|
Task |
tasks.c |
任务管理 |
Queue |
queue.c |
队列操作 |
Semaphore |
semphr.h(宏封装) |
信号量 / 互斥量 |
Timer |
timers.c |
软件定时器 |
EventGroup |
event_groups.c |
事件组 |
Port |
port.c |
硬件移植层 |
List |
list.c |
链表操作 |
🔍 拆解练习
```
vTaskPrioritySet() → v + Task + PrioritySet
返回 void,在 task.c 中定义,功能:设置优先级
xQueueReceive() → x + Queue + Receive
返回 BaseType_t,在 queue.c 中定义,功能:接收队列
uxTaskGetStackHighWaterMark() → ux + Task + GetStackHighWaterMark
返回 UBaseType_t,在 tasks.c 中定义,功能:获取栈高水位线
```
1.4 宏
宏用大写字母,小写前缀表示定义文件:
| 前缀 | 定义文件 | 举例 |
|---|---|---|
config |
FreeRTOSConfig.h |
configUSE_PREEMPTION |
pd |
projdefs.h |
pdTRUE, pdFALSE |
port |
portmacro.h |
portMAX_DELAY |
task |
task.h |
taskENTER_CRITICAL() |
err |
projdefs.h |
errQUEUE_FULL |
通用宏定义(贯穿整个代码):
| 宏 | 值 | 说明 |
|---|---|---|
pdTRUE / pdPASS |
1 | 成功 |
pdFALSE / pdFAIL |
0 | 失败 |
1.5 格式
- 缩进:1 Tab = 4 空格,建议用空格不用 Tab(避免跨编辑器格式错乱)
- 大括号:Allman 风格(独占一行)
- 注释:
/* */风格(兼容 C89),不用//
二、版权与发展史
- 2003 年:由美国的 Richard Barry 发布,是 FreeRTOS 的拥有者和维护者
- 经历 9 个大版本迭代,与众多半导体厂商合作,拥有数百万开发者,市场占有率最高的 RTOS
- 2018 年:被亚马逊(Amazon)收购,改名为 AWS FreeRTOS
- 版本号升级为 V10,开源协议从 GPLv2+ 改为 MIT(完全免费)
- V10 相比 V9 主要加入了物联网相关组件,内核基本不变
三、收费问题
3.1 FreeRTOS(免费开源)
遵循 GPLv2+ 许可协议:
- 未修改内核源码 → 产品全部代码可以闭源
- 修改了内核源码 → 修改部分必须开源,其他应用部分不用
- 个人和公司均可免费使用
3.2 FreeRTOS vs OpenRTOS
代码完全一样,区别在于可获取的服务:
| 比较项目 | FreeRTOS | OpenRTOS |
|---|---|---|
| 是否免费 | ✅ | ❌ |
| 可否商业使用 | ✅ | ✅ |
| 是否提供技术支持 | ❌ | ✅ |
| 是否被法律保护 | ❌ | ✅ |
| 是否需要开源修改的内核源码 | ✅ | ❌ |
3.3 SaveRTOS(安全认证版,收费)
基于 FreeRTOS,针对特定安全领域做了认证(工控 IEC 61508、医疗 IEC 62304、汽车 ISO 26262、航空 DO178B 等)。
四、资料获取
| 资源 | 获取方式 |
|---|---|
| 最新源码 | freertos.org → Download Source |
| 历史版本 | SourceForge |
| 官方电子书 | 官网 → PDF Books |
| 快速入门 | 官网 → Quick Start(网页版) |
1. FreeRTOS V10.0.0 Reference Manual.pdf — API 参考手册
2. Mastering the FreeRTOS Real Time Kernel - A Hands-On Tutorial Guide.pdf — 入门教程
整理自《FreeRTOS 内核实现与应用开发实战指南:基于 STM32》第 1 章(刘火良、杨森 著)
五、自测题
Q1:看到变量名 pxCurrentTCB,能推断出什么信息?
- p → 指针
- x → 指向 BaseType_t 或结构体
- 组合起来:这是一个指向结构体的指针,名为 CurrentTCB(当前任务控制块)
Q2:函数 xTimerStart() 的返回值类型、所属模块、定义文件分别是什么?
- x → 返回 BaseType_t
- Timer → 所属模块:软件定时器
- 定义在 timers.c
Q3:宏 configUSE_PREEMPTION 定义在哪个文件?
前缀 config → 定义在 FreeRTOSConfig.h
Q4:FreeRTOS 为什么不用 int 类型?
因为 int 在不同处理器架构上大小不同(16 位平台是 16 bit,32 位平台是 32 bit),FreeRTOS 只用 short(16 位)和 long(32 位)来保证跨平台一致性。
Q5:FreeRTOS、OpenRTOS、SaveRTOS 三者的核心区别是什么?
- FreeRTOS:免费开源(GPLv2+),无技术支持,修改内核须开源
- OpenRTOS:代码相同但收费,提供技术支持和法律保护,无需开源
- SaveRTOS:收费,针对安全关键领域做了行业认证(IEC 61508、ISO 26262 等)
Q6:看到函数 prvListTasksWithinSingleList(),拆解它的命名。
- prv → 私有函数(private,仅文件内部调用)
- List → 所属模块:链表,定义在 list.c
- TasksWithinSingleList → 功能:列出单个链表中的任务