FreeRTOS 基础入门:堆栈、目录结构与编程规范

FreeRTOS 基础入门

本文整理了 FreeRTOS 学习过程中的基础知识,包括堆栈概念、FreeRTOS 的目录结构以及官方推荐的编程规范。

一、RTOS 学习基础:堆与栈

1. 堆 (Heap)

堆是一个由用户控制的空闲内存区域,需要手动申请和释放空间。我们通常使用 malloc 分配的内存(如 char *p = malloc(10);)就位于堆中。

简单的堆分配演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
char heap_buf[1024]; // 模拟堆内存池
int pos = 0; // 堆指针

void *my_malloc(int size) {
int old_pos = pos; // 保存当前分配起始位置
pos = pos + size; // 更新堆指针
return &heap_buf[old_pos]; // 返回申请到的内存首地址
}

int main() {
char ch = 65; // 'A'

// 模拟分配堆内存
char *buf = (char *)my_malloc(100); // 分配100字节 0x000~0x063
char *buf2 = (char *)my_malloc(100); // 分配100字节 0x064~0x0C7

uint8_t uch = 200;

for (int i = 0; i < 100; i++) {
buf[i] = ch + i; // 往堆内存写入数据
}

for (int i = 0; i < 100; i++) {
buf2[i] = uch + i; // 往堆内存写入数据
}

return 0;
}

2. 栈 (Stack)

栈是函数运行时使用的内存区域,由编译器自动分配和释放。栈主要用于存放:

  • 函数的参数
  • 局部变量
  • 函数返回地址

函数调用与栈的过程:

当主函数调用子函数时,会将下一条指令的地址(返回地址)压入栈中,然后跳转到子函数执行。子函数执行完毕后,从栈中弹出返回地址,跳转回主函数继续执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void AFUN(void) {
int a = 10;
int b = 20;

// 假设这条指令的地址是 0x1000
BFUN(); // ← 调用 BFUN

// 假设这条指令的地址是 0x1004 ← 这就是返回地址!
int c = a + b; // BFUN 返回后,继续执行这里

// 地址 0x1008
return;
}

void BFUN(void) {
int x = 5;
// ... 执行一些操作
return; // 返回到 0x1004(AFUN 中调用 BFUN 的下一条指令)
}

二、FreeRTOS 目录结构 (基于 STM32F1)

了解 FreeRTOS 的源码目录结构有助于快速上手移植和开发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FreeRTOS/

├── Demo/ # 示例工程
│ ├── Common/ # 通用演示代码
│ └── CORTEX_STM32F103_Keil/ # 特定平台的演示工程

├── License/ # 许可证
│ └── license.txt

├── Source/ # 内核源码(核心部分)
│ ├── include/ # 头文件
│ ├── portable/ # 移植层文件(与硬件相关)
│ │ ├── [Compiler]/[Arch]/ # 对应编译器和架构的接口文件
│ │ └── MemMang/ # 内存管理实现 (heap_1.c ~ heap_5.c)
│ ├── croutine.c # 协程(通常不常用)
│ ├── event_groups.c # 事件组
│ ├── list.c # 链表实现
│ ├── queue.c # 队列实现
│ ├── stream_buffer.c # 流缓冲区
│ ├── tasks.c # 任务管理
│ └── timers.c # 软件定时器

├── README.md
└── ...

三、FreeRTOS 数据类型和编程规范

FreeRTOS 有一套独特的命名规范,遵循这些规范可以让代码风格与内核保持一致。

1. 变量命名前缀

变量名通常包含一个小写字母前缀,表示变量的类型。

变量名前缀 含义 C 类型
c Char char
s Short int16_t, short
l Long int32_t, long
x BaseType BaseType_t 及非标准类型 (结构体, Handle 等)
u Unsigned unsigned
p Pointer 指针
uc Unsigned Char uint8_t, unsigned char
pc Pointer to Char char *

2. 函数命名前缀

函数名也包含前缀,表示返回值类型和作用域。

函数名前缀 含义 示例
prv Private (私有) prvSetupHardware (通常是 static 函数)
v Void (无返回值) vTaskStartScheduler
x BaseType (非 void) xTaskCreate (返回 BaseType_t 或 Handle)

3. 宏命名规范

宏通常大写,前缀小写,表示宏定义所在的文件。

宏的前缀 含义 (定义文件) 示例
port portable.hportmacro.h portMAX_DELAY
task task.h taskENTER_CRITICAL()
pd projdefs.h pdTRUE
config FreeRTOSConfig.h configUSE_PREEMPTION
err projdefs.h errQUEUE_FULL

4. 通用宏定义

FreeRTOS 中常用的逻辑值宏定义:

pdTRUE 1
pdFALSE 0
pdPASS 1
pdFAIL 0

FreeRTOS 基础入门:堆栈、目录结构与编程规范
http://example.com/2025/12/05/freertos-basics/
作者
John Doe
发布于
2025年12月5日
许可协议