tags: [source-summary] type: source source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — FreeRTOS移植" author: "尚硅谷研究院" date: 2026-07-17
用生活理解:移植 FreeRTOS 就像给一台电脑装操作系统——你得知道安装包(源码结构)里有什么,按照步骤装驱动(移植文件),再配置系统设置(FreeRTOSConfig.h),最后开机运行。我们的芯片是 Cortex-M3,选对应驱动即可。
FreeRTOS 源码包顶层结构:
| 目录 | 说明 |
|---|---|
FreeRTOS/ |
内核源码——移植的核心 |
FreeRTOS-Plus/ |
第三方组件(TCP、FAT 等) |
Tools/ |
工具 |
Quick_Start_Guide/ |
快速入门指南 |
FreeRTOS/Source/ 是最重要的文件夹:
Source/
├── include/ # 通用头文件(与编译器/处理器无关)
├── portable/ # 移植文件(与编译器/架构相关)
│ ├── Keil/ # → 指向 RVDS
│ ├── RVDS/ # 各处理器核的接口文件
│ │ └── ARM_CM3/ # Cortex-M3 移植(port.c + portmacro.h)
│ └── MemMang/ # 内存管理(heap_1 ~ heap_5)
├── croutine.c # 协程(可选)
├── event_groups.c # 事件组(可选)
├── list.c # 列表(必选)
├── queue.c # 队列(可选,但信号量/互斥量依赖它)
├── stream_buffer.c # 流式缓冲区(可选)
├── tasks.c # 任务管理(必选)
└── timers.c # 软件定时器(可选)
tasks.c、list.c(基础依赖)RVDS/ARM_CM3/port.c(Cortex-M3 移植接口)+ portmacro.hportable 目录是连接 FreeRTOS 与硬件的桥梁,包含两部分:
| 组件 | 文件 | 说明 |
|---|---|---|
| 移植接口 | port.c |
上下文切换汇编代码(已由官方编写好) |
| 移植头文件 | portmacro.h |
数据类型定义和宏定义 |
对于 STM32F103(Cortex-M3 内核),只需使用 RVDS/ARM_CM3/ 下的这两个文件即可。官方已经把底层移植代码写好了,我们只需要"拿起即用"。
| 算法 | 特点 | 适用场景 |
|---|---|---|
| heap_1 | 只分配不释放,无碎片 | 确定不需要删除任务的场景 |
| heap_2 | 最佳匹配,可释放,会碎片 | 不推荐,已被 heap_4 替代 |
| heap_3 | 简单包装 malloc/free,线程安全 | 编译器的 malloc 可用时 |
| heap_4 | 首次匹配,合并相邻空闲块 | 初学者首选,通用场景 |
| heap_5 | heap_4 + 跨非连续内存区域 | 多块物理内存的场景 |
FreeRTOS/ 文件夹,其下创建 portable/ 和 source/FreeRTOS/Source/ 下的 7 个 .c 文件(tasks.c, queue.c, timers.c, event_groups.c, croutine.c, list.c, stream_buffer.c)到 source/portable/ 下的 Keil/、RVDS/、MemMang/ 到 portable/MemMang/ 只保留 heap_4.cRVDS/ 只保留 ARM_CM3/include/ 到 FreeRTOS/ 下Demo/CORTEX_STM32F103_Keil/ 复制 FreeRTOSConfig.h 到 Core/Inc/FreeRTOS/Source —— 添加 source/ 下的 7 个 .c 文件FreeRTOS/Portable —— 添加 port.c 和 heap_4.cFreeRTOS/include/ 和 FreeRTOS/portable/RVDS/ARM_CM3/FreeRTOSConfig.h 在 Core/Inc/(该路径通常已有)在 FreeRTOSConfig.h 中添加:
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define INCLUDE_xTaskGetSchedulerState 1
添加头文件:
#include "FreeRTOS.h"
#include "task.h"
注释掉默认的空中断:
// void SVC_Handler(void) { }
// void PendSV_Handler(void) { }
添加 SysTick 中断服务函数:
/* USER CODE BEGIN PV */
extern void xPortSysTickHandler(void);
/* USER CODE END PV */
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
/* USER CODE BEGIN SysTick_IRQn 1 */
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
/* USER CODE END SysTick_IRQn 1 */
}
HAL 库默认使用 SysTick 作为时基。FreeRTOS 也依赖 SysTick 作为系统滴答。
解决方案:在 STM32CubeMX 的 SYS 配置中,将 Timebase Source 改为其他定时器(如 TIM6),并将中断优先级设为较高(如 1)。
与 HAL 库移植的前两步相同(目录添加 + 工程添加源文件)。
不同之处在于系统配置修改:
FreeRTOSConfig.h 添加三个配置在 main.c 中添加 SysTick_Handler:
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}
| Function | Parameters | Return | Description |
|---|---|---|---|
vTaskStartScheduler() |
void | void | 启动调度器 |
xTaskGetSchedulerState() |
void | BaseType_t | 获取调度器状态(NOT_STARTED / RUNNING / SUSPENDED) |
xPortSysTickHandler() |
void | void | 滴答中断处理函数(在 SysTick_Handler 中调用) |
stm32f1xx_it.c 中注释掉原有的空函数,否则链接时冲突。FreeRTOSConfig.h 开头是否包含了系统头文件(如 stm32f1xx_hal.h)并定义了 SystemCoreClock。configTOTAL_HEAP_SIZE 默认可能太大。STM32F103 系列通常设为 10*1024(10KB)即可。