STM32F407移植FreeRTOS完整教程(HAL库版本)
STM32F407移植FreeRTOS完整教程(HAL库版本)
📌 本文适合嵌入式初学者,将手把手教你如何在STM32F407VET6上移植FreeRTOS实时操作系统。
📖 前言
FreeRTOS是一个轻量级的实时操作系统(RTOS),在嵌入式开发中应用非常广泛。本教程将基于STM32F407VET6芯片,使用HAL库,详细讲解如何从零开始移植FreeRTOS。
🎯 学习目标:
- 理解FreeRTOS的基本架构
- 掌握FreeRTOS在STM32上的移植方法
- 创建包含LED、按键、串口的基础工程
一、准备工作
1.1 什么是FreeRTOS?
FreeRTOS(Free Real Time Operating System)是一个免费的实时操作系统内核。简单来说,它就像一个"任务管理器",可以让你的单片机同时运行多个任务,比如一边闪烁LED,一边接收串口数据,一边检测按键。
核心概念:
- 任务(Task): 可以理解为一个独立的"小程序"
- 调度器(Scheduler): 负责分配CPU时间给各个任务
- 可裁剪性: 可以根据需求删减功能,节省存储空间
1.2 硬件与软件环境
- 开发板: STM32F407VET6(Cortex-M4架构)
- 开发工具: Keil MDK5
- HAL库: STM32CubeMX生成
- FreeRTOS版本: V9.0.0(其他版本步骤类似)
二、创建基础HAL库工程
在移植FreeRTOS之前,我们需要先用STM32CubeMX创建一个基础工程。
2.1 配置基础外设
使用STM32CubeMX配置以下模块:
/* 基础外设配置清单 */
✅ LED - 用于指示任务运行状态
✅ 按键 - 用于触发任务事件
✅ 串口 - 用于调试信息输出(USART1)
✅ 时钟 - 配置系统时钟为168MHz
⚠️ 重要提示:
- SysTick定时器稍后会被FreeRTOS接管,需要修改HAL库的时基源
- 建议将HAL时基源改为TIM6或TIM7
2.2 修改HAL库时基源(关键步骤!)
在STM32CubeMX中:
- 进入
SYS配置页 - 将
Timebase Source从SysTick改为TIM7

为什么要这样做?
FreeRTOS需要占用SysTick定时器作为系统心跳(节拍),如果HAL库也使用SysTick,就会产生冲突。所以我们把HAL库的时基改用其他定时器。
三、FreeRTOS文件结构分析
在正式移植前,我们先了解一下FreeRTOS的文件组成。
3.1 创建工程文件夹
在你的工程目录下建立以下结构:
📦 工程根目录┣ 📂 Mid // 中间件文件夹┃ ┗ 📂 FreeRTOS // FreeRTOS主目录┃ ┣ 📂 source // 源文件(核心.c文件)┃ ┗ 📂 portable // 移植文件(硬件相关)┣ 📂 Core // HAL库工程文件┗ 📂 Drivers // HAL库驱动

3.2 需要移植的文件清单
FreeRTOS移植需要4类文件:
① 核心源文件(7个.c文件)
从 FreeRTOS/Source 目录复制以下文件到 source 文件夹:
tasks.c // 任务管理(最核心)
queue.c // 队列通信
list.c // 链表操作
timers.c // 软件定时器
event_groups.c // 事件组
croutine.c // 协程(可选,一般不用)

文件功能说明:
tasks.c: 实现任务创建、删除、调度等功能queue.c: 实现任务间数据传递list.c: 提供链表数据结构支持(内部使用)
② 硬件移植文件(架构相关)
这部分文件与CPU架构和编译器有关。
选择路径:FreeRTOS/Source/portable/RVDS/ARM_CM4F
RVDS = RealView Development Suite(Keil使用的编译器)
ARM_CM4F = ARM Cortex-M4F架构(STM32F407是M4内核)
需要复制到 portable 文件夹的文件:
port.c // 底层接口实现
portmacro.h // 架构相关宏定义

架构选择对照表:
| 芯片系列 | CPU内核 | 文件夹选择 |
|---|---|---|
| STM32F1 | Cortex-M3 | ARM_CM3 |
| STM32F4 | Cortex-M4F | ARM_CM4F |
| STM32F7 | Cortex-M7 | ARM_CM7 |
③ 内存管理文件
从 FreeRTOS/Source/portable/MemMang 复制一个 heap_x.c 文件。
常用选择: heap_4.c(推荐新手使用)
heap_1.c // 最简单,只分配不释放
heap_2.c // 可释放,但不能合并碎片
heap_3.c // 调用标准库的malloc/free
heap_4.c // 可释放+碎片合并(最常用)⭐
heap_5.c // 支持不连续内存区域

④ 配置头文件
从 FreeRTOS/Demo/CORTEX_M4F_STM32F407ZG-SK 复制:
FreeRTOSConfig.h // FreeRTOS配置文件
建议放到工程的 Core/Inc 或 User 文件夹。

⑤ 头文件目录
复制整个 include 文件夹到 FreeRTOS 目录:
include/┣ FreeRTOS.h // 主头文件┣ task.h // 任务相关┣ queue.h // 队列相关┣ semphr.h // 信号量相关┗ ...
四、Keil工程配置
4.1 添加源文件到工程
在Keil的Project窗口添加分组:

操作步骤:
- 右键工程 →
Add Group→ 命名为FreeRTOS - 右键
FreeRTOS组 →Add Existing Files to Group - 添加以下文件:
/* source文件夹 */
tasks.c
queue.c
list.c
timers.c
event_groups.c/* portable文件夹 */
port.c
heap_4.c/* 配置文件(可选添加,方便查看) */
FreeRTOSConfig.h

4.2 添加头文件路径
点击Keil的"魔术棒"图标 → C/C++ → Include Paths,添加:
../Mid/FreeRTOS/source/include
../Mid/FreeRTOS/portable
../Core/Inc (FreeRTOSConfig.h所在目录)

五、配置文件修改(关键步骤)
5.1 FreeRTOSConfig.h修改(STM32F407)
打开 FreeRTOSConfig.h,修改以下内容:
① 修改外部引用头文件
找到文件末尾,确保有以下定义:
/* 将FreeRTOS的中断函数映射到STM32的中断向量 */
#define xPortPendSVHandler PendSV_Handler // 任务切换中断
#define vPortSVCHandler SVC_Handler // 系统调用中断
#define xPortSysTickHandler SysTick_Handler // 时钟节拍中断
为什么要这样做?
FreeRTOS使用了3个中断,但函数名与STM32启动文件中的不同。通过宏定义重命名,避免链接错误。
② 修改中断优先级配置
按下图修改其余参数。

5.2 删除冲突的中断函数
打开 stm32f4xx_it.c,注释掉以下三个中断函数:
/* 这些函数已由FreeRTOS接管,保留会导致重复定义 */
// void SVC_Handler(void)
// {
// }// void PendSV_Handler(void)
// {
// }// void SysTick_Handler(void)
// {
// HAL_IncTick();
// }

5.3 在CubeMX中调整TIM6中断优先级

六、编译
点击Keil的 Build 按钮,如果一切正常,应该显示:
0 Error(s), 0 Warning(s).
此时表示已经移植freertos成功了。后续我将会介绍freertos的其他用法及特性。
如果觉得本文有帮助,请点个赞再走吧!你的支持是我持续创作的动力! ❤️
