03-FreeRTOS移植指南.md 6.4 KB


tags: [source-summary] type: source source: "尚硅谷嵌入式技术之FreeRTOS实时操作系统 V1.0.3 — FreeRTOS移植" author: "尚硅谷研究院" date: 2026-07-17

created: 2026-07-17

FreeRTOS 移植指南

用生活理解:移植 FreeRTOS 就像给一台电脑装操作系统——你得知道安装包(源码结构)里有什么,按照步骤装驱动(移植文件),再配置系统设置(FreeRTOSConfig.h),最后开机运行。我们的芯片是 Cortex-M3,选对应驱动即可。

FreeRTOS 源码结构

Basic concept

FreeRTOS 源码包顶层结构:

目录 说明
FreeRTOS/ 内核源码——移植的核心
FreeRTOS-Plus/ 第三方组件(TCP、FAT 等)
Tools/ 工具
Quick_Start_Guide/ 快速入门指南

Source/ 目录详解

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              # 软件定时器(可选)
  • 必选 .c 文件:tasks.clist.c(基础依赖)
  • portableRVDS/ARM_CM3/port.c(Cortex-M3 移植接口)+ portmacro.h
  • MemMang:选一个 heap 文件,初学者推荐 heap_4.c

Portable 层

portable 目录是连接 FreeRTOS 与硬件的桥梁,包含两部分:

组件 文件 说明
移植接口 port.c 上下文切换汇编代码(已由官方编写好)
移植头文件 portmacro.h 数据类型定义和宏定义

对于 STM32F103(Cortex-M3 内核),只需使用 RVDS/ARM_CM3/ 下的这两个文件即可。官方已经把底层移植代码写好了,我们只需要"拿起即用"。

MemMang 方案对比

算法 特点 适用场景
heap_1 只分配不释放,无碎片 确定不需要删除任务的场景
heap_2 最佳匹配,可释放,会碎片 不推荐,已被 heap_4 替代
heap_3 简单包装 malloc/free,线程安全 编译器的 malloc 可用时
heap_4 首次匹配,合并相邻空闲块 初学者首选,通用场景
heap_5 heap_4 + 跨非连续内存区域 多块物理内存的场景

HAL 库移植步骤

Step 1: 目录添加源码文件

  1. 在工程根目录新建 FreeRTOS/ 文件夹,其下创建 portable/source/
  2. 复制 FreeRTOS/Source/ 下的 7 个 .c 文件(tasks.c, queue.c, timers.c, event_groups.c, croutine.c, list.c, stream_buffer.c)到 source/
  3. 复制 portable/ 下的 Keil/RVDS/MemMang/portable/
  4. MemMang/ 只保留 heap_4.c
  5. RVDS/ 只保留 ARM_CM3/
  6. 复制 include/FreeRTOS/
  7. Demo/CORTEX_STM32F103_Keil/ 复制 FreeRTOSConfig.hCore/Inc/

Step 2: 工程添加源文件

  1. 在 Keil 中创建两个 Group:
    • FreeRTOS/Source —— 添加 source/ 下的 7 个 .c 文件
    • FreeRTOS/Portable —— 添加 port.cheap_4.c
  2. 添加头文件路径:FreeRTOS/include/FreeRTOS/portable/RVDS/ARM_CM3/
  3. FreeRTOSConfig.hCore/Inc/(该路径通常已有)

Step 3: 修改 FreeRTOSConfig.h

FreeRTOSConfig.h 中添加:

#define xPortPendSVHandler  PendSV_Handler
#define vPortSVCHandler     SVC_Handler
#define INCLUDE_xTaskGetSchedulerState   1

Step 4: 修改 stm32f1xx_it.c

  1. 添加头文件:

    #include "FreeRTOS.h"
    #include "task.h"
    
  2. 注释掉默认的空中断:

    // void SVC_Handler(void) { }
    // void PendSV_Handler(void) { }
    
  3. 添加 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 */
    }
    

Step 5: 解决 HAL + SysTick 冲突

HAL 库默认使用 SysTick 作为时基。FreeRTOS 也依赖 SysTick 作为系统滴答。

解决方案:在 STM32CubeMX 的 SYS 配置中,将 Timebase Source 改为其他定时器(如 TIM6),并将中断优先级设为较高(如 1)。

寄存器版移植步骤

与 HAL 库移植的前两步相同(目录添加 + 工程添加源文件)。

不同之处在于系统配置修改:

  1. 同样在 FreeRTOSConfig.h 添加三个配置
  2. main.c 中添加 SysTick_Handler:

    extern void xPortSysTickHandler(void);
    
    void SysTick_Handler(void)
    {
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
        xPortSysTickHandler();
    }
    }
    

Core API Reference Table

Function Parameters Return Description
vTaskStartScheduler() void void 启动调度器
xTaskGetSchedulerState() void BaseType_t 获取调度器状态(NOT_STARTED / RUNNING / SUSPENDED)
xPortSysTickHandler() void void 滴答中断处理函数(在 SysTick_Handler 中调用)

Common Issues & Pitfalls

  • PendSV_Handler 被注释掉了吗?:FreeRTOS 接管了 PendSV_Handler,必须在 stm32f1xx_it.c 中注释掉原有的空函数,否则链接时冲突。
  • SysTick 冲突卡死:HAL 与 FreeRTOS 都默认使用 SysTick。启动调度器后,HAL 的 HAL_Delay 会失效甚至卡死。记得将 HAL 时基换到其他定时器。
  • 变量报 undefined:如果编译报变量未定义,检查 FreeRTOSConfig.h 开头是否包含了系统头文件(如 stm32f1xx_hal.h)并定义了 SystemCoreClock
  • 内存不足configTOTAL_HEAP_SIZE 默认可能太大。STM32F103 系列通常设为 10*1024(10KB)即可。