推荐FreeRTOS教程

链接一:FreeRTOS官网
链接二:百问网FreeRTOS教程
链接三:百问网移至文件

1. 核心源文件(Source 根目录)

这些文件是 FreeRTOS 内核的通用实现,与具体硬件无关,因此放在 Source 根目录下,所有移植版本共用。

文件 作用 为什么放在这里
tasks.c 任务管理:创建、删除、延时、调度、优先级管理 内核最核心的功能,与硬件无关
list.c 链表数据结构实现,内核内部使用(就绪链表、延时链表等) 纯软件数据结构,与硬件无关
queue.c 队列、信号量、互斥量的实现 内核同步机制,与硬件无关
timers.c 软件定时器实现 依赖 tick,但本身逻辑与硬件无关
event_groups.c 事件组实现 内核同步机制,与硬件无关
croutine.c 协程(Co-routine)实现(可选,已较少使用) 与硬件无关
stream_buffer.c 流缓冲区(Stream Buffer)实现 与硬件无关
message_buffer.c 消息缓冲区(Message Buffer)实现(基于流缓冲区) 与硬件无关

为什么这些文件放在 Source 根目录?
因为它们只依赖 C 语言和 FreeRTOS 内部接口,不直接操作寄存器或特定硬件。放在根目录可以避免重复,所有工程共享同一份代码。

2. 移植相关文件(portable 目录)

portable 目录下按 [compiler]/[architecture] 分子目录,例如 RVDS/ARM_CM3

文件 作用 为什么放在这个子目录
port.c 实现硬件相关的底层操作:上下文切换、启动第一个任务、SysTick 中断处理、临界区进入/退出 这些操作依赖具体 CPU 架构和编译器,必须为每种组合单独实现
portmacro.h 定义硬件相关的数据类型(如 TickType_tBaseType_t)、临界区宏、上下文切换相关的宏 port.c,与架构和编译器强相关

为什么按 [compiler]/[architecture] 分目录?
不同编译器(RVDS、IAR、GCC)的内联汇编、符号修饰、数据对齐等特性不同;不同架构(Cortex-M3、M4、RISC-V)的寄存器和指令集不同。分目录可以清晰隔离这些差异。

3. 内存管理文件(portable\MemMang)

文件 作用 为什么放在 portable 下
heap_1.c 只分配不释放,适用于简单应用 内存分配策略依赖应用场景,用户可以根据需求选择或自定义
heap_2.c 支持分配和释放,但不合并相邻空闲块 同上
heap_3.c 包装标准 malloc/free,线程安全 同上
heap_4.c 支持分配、释放,并合并相邻空闲块(最常用) 同上
heap_5.c heap_4,但支持多个非连续内存区域 同上

为什么放在 portable 目录?
内存管理方案与硬件内存布局、编译器特性、应用需求相关,因此被设计为可替换组件。portable 目录的本意就是“用户可以提供自己的实现”。

4. 头文件目录

4.1 Source\include

包含所有内核公开的头文件:

头文件 作用
FreeRTOS.h 总包含文件,引入其他头文件
task.h 任务管理 API 声明
queue.h 队列、信号量、互斥量 API 声明
semphr.h 信号量相关宏和函数声明
timers.h 软件定时器 API 声明
event_groups.h 事件组 API 声明
stream_buffer.h 流缓冲区 API 声明
message_buffer.h 消息缓冲区 API 声明
projdefs.h 通用宏定义(如 pdTRUEpdFALSE
portable.h 移植层接口声明
list.h 链表结构声明(内核内部使用)
stack_macros.h 栈检查相关宏

4.2 portable\[compiler]\[architecture]

包含 portmacro.h,定义硬件相关数据类型和宏,是所有源文件需要包含的移植头文件。

4.3 Core\Inc(或工程配置目录)

包含 FreeRTOSConfig.h,这是用户配置文件,用于裁剪和配置内核功能(如是否启用软件定时器、tick 频率、堆大小等)。

为什么 FreeRTOSConfig.h 放在工程目录而不是 Source 目录?
因为它是工程特定的配置,每个工程可以有不同的配置,不应修改内核源文件。放在工程目录可以独立于内核源码进行管理。

5. 入口函数与启动流程

入口函数通常位于 main.c 中,与 STM32CubeMX 生成的代码结合:

osKernelInitialize();   // 初始化 FreeRTOS 内核(创建空闲任务、初始化链表等)
MX_FREERTOS_Init();     // 创建用户任务(由 CubeMX 生成,位于 freertos.c)
osKernelStart();        // 启动调度器,开始任务调度
  • osKernelInitialize()osKernelStart() 是 CMSIS-RTOS 封装,底层调用 FreeRTOS 的 vTaskStartScheduler() 等函数。
  • freertos.c 中定义的任务创建代码最终会调用 xTaskCreate()

总结:目录划分的设计思想

FreeRTOS/Source
├── include            # 内核公共头文件(API 声明、内部数据结构)
├── *.c                # 内核核心实现(与硬件无关)
├── portable
│   ├── [compiler]/[arch]   # 移植层(上下文切换、硬件相关数据类型)
│   └── MemMang            # 可替换的内存管理实现
└── (工程目录)
    ├── FreeRTOSConfig.h   # 工程配置
    └── main.c / freertos.c # 入口和任务创建
  • 核心代码与移植代码分离:方便支持不同硬件平台。
  • 配置与源码分离FreeRTOSConfig.h 放在工程目录,避免修改内核源码。
  • 可替换组件独立:内存管理、协程等可选功能放在 portable 下,用户可按需选择。

如果你需要我根据具体的文件列表(比如你提到的 image2image3 中的内容)逐一解释,请将图片中的文字或文件名贴出来,我可以继续补充。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐