FreeRTOS学习笔记 · 第三讲:1.3文件组成和基本原理

文件组成

用户配置文件指 FreeRTOSConfig.h,程序文件指 freertos.c

FreeRTOS 通用功能文件

用于实现 freeRTOS 的队列、信号量、软件定时器、事件组等功能。

先看 .c 文件

  • croutine.c:协程,适用于那些内存非常小的 MCU,现在已经很少使用。
  • event_groups.c:事件组, 用于解决任务间的同步问题,特别是当一个任务需要等待“多个条件同时满足”或“多个条件之一满足”时,事件组是比信号量(Semaphore)更高效的选择。
  • list.c双向链表数据结构, 在 FreeRTOS 中,几乎所有的任务调度、时间管理和资源分配逻辑,本质上都是在不同的“列表”之间移动任务控制块(TCB)。
  • task.c:任务管理功能,任务调度器等核心功能就是在这里实现的。不过,它不直接操作 MCU 等硬件,那是 port.c的功能。
  • timer.c:软件定时器功能, 与硬件定时器不同,软件定时器不占用 MCU 的硬件定时器资源,而是由 RTOS 内核通过代码逻辑模拟出来的定时功能;它还支持单次触发和周期触发,就好比 JavaScript 的 setTimeout 和 setInterval 函数。
  • stream_buffer.c:流缓冲区功能, 是 为点对点数据传输设计的高效通信模块;它主要用于解决“一个生产者、一个消费者”的场景,比如将 DMA 接收到的串口数据传递给处理任务,以及进程间的数据通信。

再看 .h 文件

  • message_buffer.h: 消息缓冲区,是基于 Stream Buffer 之上的宏封装 。
  • mpu_prototypes.hmpu_wrappers.h: 系统安全性 , 在支持 MPU(内存保护单元,Memory Protection Unit) 的硬件上实现权限隔离等功能,如特权模式和非特权模式。
  • semphr.h:信号量, 它没有对应的 semphr.c,是因为本质上是队列(Queue)的一种特殊包装。 信号量的所有核心功能,底层全部是直接调用 queue.c 中的函数实现的。

虽然 cubemx 在创建工程时会将这些代码一并复制到项目里,但实际编译时不一定会全部编译。除了任务管理的功能之外,所有功能都需要通过配置添加进去。

这些配置实际上就是通过修改宏定义改变编译条件。

通用定义文件

FreeRTOS.h

默认宏定义、数据类型定义、接口函数定义等,以及功能剪裁定义。

如前缀为config的宏表示参数设置,前缀为INCLUDE的宏表示是否编译某个函数的源代码。

想要修改配置,我们不需要更改这个文件的内容,在 Core/Inc 里有一个 FreeRTOSConfig.h文件, 如果没有着这个文件中去定义相对应的宏,才会使用 FreeRTOS.h 的默认设置。

因此,绝大部分设置都可以通过 CubeMX 完成并生成到FreeRTOSConfig.h里。

projdefs.h

通用定义,如错误编号、逻辑值的宏定义等。

常用宏定义

pdFALSE、pdTRUE、pdFAIL、pdPASS:即布尔值 0、1;

pd_MS_TO_TICKS(xTimeInMs):将毫秒转化为节拍数,因为延时函数 vTaskDelay 的输入参数是节拍数。

StackMacros.h

定义了进行栈溢出检查的函数。

CMSIS-RTOS 标准接口文件

cmsis_os2.h

定义了各种抽象接口,这些接口再进一步调用 freertos 的具体实现函数,通过这一层抽象,可以使用户代码与具体的 rtos 种类解耦。

由于本教程旨在学习 freertos ,因此会尽量直接使用 freertos 的函数而不使用这些接口。

硬件相关文件

这两个文件定义了与硬件相关的基础数据类型、宏定义、函数定义。

由于与底层密切相关,你甚至可以看到汇编写的代码。

内存管理相关文件,定义了动态分配内存和释放内存的函数。_4 表示这是第 4 种管理方案。freertos 一共有 5 种方案,可以在 cubemx 种配置,这里使用默认的第 4 种即可。

命名方式

变量名命名方式

1. 基本类型前缀

  • cchar 类型。
  • sint16_t (short) 类型。
  • lint32_t (long) 类型。
  • u:表示 unsigned (无符号)。例如:
  • ucuint8_t (unsigned char)。
  • usuint16_t (unsigned short)。
  • uluint32_t (unsigned long)。

2. 特殊类型前缀

  • x:用于 BaseType_t 以及所有非标准类型
    • 这包括:结构体变量、任务句柄(Task Handle)、队列句柄等。
    • 例如:xTaskCreate 中的 x
  • ux:用于 UBaseType_t(无符号类型,通常对应 CPU 的字长,如 32 位)。

3. 指针前缀

  • p:表示指针(Pointer)。通常叠加在类型前缀之前:
  • pc:指向字符的指针 (char *)。
  • px:指向结构体或复杂类型的指针。

函数名

返回值前缀

  • v:返回值为 void(如 vQueueDelete)。
  • x:返回值为 BaseType_t(如 xTaskCreate)。
  • pc:返回值为 char *(如 pcTimerGetName)。
  • pv:返回值为 void *(如 pvPortMalloc)。

CMSIS-RTOS 例外

为了跨内核兼容,CMSIS 层定义的函数(如 osThreadNew)统一以 os 开头,不包含返回值类型前缀。

宏定义

  • config:系统全局配置,
    • configUSE_MUTEXES,用于 FreeRTOSConfig.h,控制内核功能的开关(如是否启用互斥锁)。
  • INCLUDE_:条件编译控制,
    • INCLUDE_vTaskDelay,控制是否编译某个特定的 API 函数,用以精简内核体积。
  • task:任务管理相关,
    • taskENTER_CRITICAL(),与任务调度、临界区保护相关的宏,通常在 task.h 中定义。
  • queue:队列相关,
    • queueQUEUE_TYPE_MUTEX,队列、信号量等通信机制相关的宏,定义在 queue.h。
  • pd:项目通用定义,
    • pdTRUE, pdFALSE,定义在 projdefs.h,用于标准的成功/失败、真/假状态返回。
  • port:移植层/硬件相关,
    • portMAX_24_BIT_NUMBER,定义在 portmacro.h,涉及特定芯片架构(如 ARM, ESP32)的底层定义。
  • tmr:软件定时器相关,
    • tmrCOMMAND_START,定义在 timer.h,用于控制软件定时器的启动、停止等命令。
  • os:CMSIS RTOS 接口,
    • osFlagsWaitAll,这是封装层(如 STM32 常用的 CMSIS-V2)特有的前缀,用于屏蔽底层 RTOS 差异。

配置参数

config 相关的配置都可以在Config parameters里配置;与INCLUDE_相关的都可以在Include parameters里配置。

下面我们来看看Config parameters里都有什么。

Config parameters 参数

下面所有参数对应的宏都以cofig开头。

Memory allocation / API

FreeRTOS version :内核版本号。

CMSIS-RTOS version :CMSIS-RTOS 适配层版本。

MPU/FPU

ENABLE_MPU :是否启用内存保护单元(MPU)。用于任务级内存隔离。

ENABLE_FPU :是否启用硬件浮点单元支持(需CPU具备FPU)。

Kernel settings

分组内核设置。

USE_PREEMPTION :是否使用抢占式调度;高优先级任务可立即抢占低优先级任务。设置为 disable 系统会使用合作式任务调度。

CPU_CLOCK_HZ :FreeRTOS 使用的CPU时钟频率。

TICK_RATE_HZ :系统节拍中断频率(Hz),决定调度时间基准;可设置为 1~1000,默认 1000,即 1ms。

MAX_PRIORITIES :任务优先级数量上限(从0到N-1)。固定 56,不可修改。

MINIMAL_STACK_SIZE :空闲任务的最小栈大小(以word为单位)。最小值 64,最大值依芯片型号决定。

MAX_TASK_NAME_LEN :任务名称最大长度(含结尾\0)。

USE_16_BIT_TICKS :是否使用16位tick计数器;影响最大延时范围。默认为 disable,即使用 32 位计数器。

IDLE_SHOULD_YIELD :空闲任务在同优先级任务存在时是否让出CPU。默认开启。

USE_MUTEXES :启用互斥锁(含优先级继承)。默认开启。

USE_RECURSIVE_MUTEXES :启用递归互斥锁。默认开启。

USE_COUNTING_SEMAPHORES :启用计数信号量。默认开启。

QUEUE_REGISTRY_SIZE :队列注册表容量,用于调试可见性,使用内核查看队列和信号量时,需要先注册。0~255, 默认为 8 。

USE_APPLICATION_TASK_TAG :是否启用任务标签钩子。

ENABLE_BACKWARD_COMPATIBILITY :兼容旧版API。

USE_PORT_OPTIMISED_TASK_SELECTION :是否启用端口相关的快速优先级选择算法。默认不选择,即使用通用算法,不依赖相关硬件。

USE_TICKLESS_IDLE :空闲时停止周期tick以降低功耗。启用会在空闲时自动进入低功耗模式

USE_TASK_NOTIFICATIONS :启用任务通知机制(轻量级同步)。

RECORD_STACK_HIGH_ADDRESS :记录栈高地址以辅助栈使用分析。

Memory management settings

内存管理设置。

Memory Allocation :动态或静态对象创建方式。默认同时支持动静态分配,不可更改。

TOTAL_HEAP_SIZE :动态堆大小(字节)。512~64k(F103,F429 最大值是 192k)。RTOS 的堆空间使用情况可在FreeRTOS Heap Usage选项卡中查看。

Memory management scheme :堆管理实现(heap_1~heap_5,默认为heap_4,支持分配与释放)。

Hook function related definitions

钩子函数相关定义。钩子函数类似于回调函数,在某个功能或函数执行时被调用;钩子函数代码由用户编写。

USE_IDLE_HOOK :启用空闲任务钩子函数。

USE_TICK_HOOK :启用系统tick钩子函数。

USE_MALLOC_FAILED_HOOK :内存分配失败回调。

USE_DAEMON_TASK_STARTUP_HOOK :软件定时器服务任务启动钩子。

CHECK_FOR_STACK_OVERFLOW :栈溢出时钩子函数。有两个可选项,对应 freertos 两种不同的栈溢出处理方法。

Run time and task stats gathering

运行时间和任务状态收集相关定义。

GENERATE_RUN_TIME_STATS :启用运行时间统计,可以使用vTaskGetRunTimeStats()来获取认为运行时间信息;默认关闭。

USE_TRACE_FACILITY :启用内核跟踪功能接口,会增加一些结构体和函数。

USE_STATS_FORMATTING_FUNCTIONS :启用统计信息格式化输出函数。

Co-routine related definitions

协程机制,协程可以节省 MCU 的内存开销。

USE_CO_ROUTINES :是否启用协程机制(已逐渐不推荐)。

MAX_CO_ROUTINE_PRIORITIES :协程优先级数量上限。

Software timer definitions

软件定时器。

USE_TIMERS :启用软件定时器服务。

TIMER_TASK_PRIORITY :定时器服务任务优先级。0~55, 默认 2。

TIMER_QUEUE_LENGTH :定时器命令队列长度。1~255,默认 10 。

TIMER_TASK_STACK_DEPTH :定时器服务任务栈大小(word)。128~49152k,默认 256 。

Interrupt nesting behaviour configuration

中断嵌套行为。

LIBRARY_LOWEST_INTERRUPT_PRIORITY :库可用的最低中断优先级值。默认 15 。

LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY :可调用FreeRTOS API的最高中断优先级阈值。默认 5 。

Added with 10.2.1 support

该版本新支持的参数。

MESSAGE_BUFFER_LENGTH_TYPE :消息缓冲区长度字段类型。默认 size_t。

USE_POSIX_ERRNO :是否启用POSIX风格errno 编号支持。

CMSIS-RTOS V2 flags

USE_OS2_THREAD_ENUMERATE :启用线程枚举功能。

USE_OS2_THREAD_SUSPEND_RESUME :启用线程挂起/恢复接口。

USE_OS2_EVENTFLAGS :启用事件标志对象。

USE_OS2_THREAD_FLAGS :启用线程标志。

USE_OS2_TIMER :启用CMSIS定时器封装。

USE_OS2_MUTEX :启用CMSIS互斥量封装。

Include parameters 参数

下面所有参数对应的宏都以INCLUDE_开头。

vTaskPrioritySet:启用后可在运行时修改指定任务的优先级。

uxTaskPriorityGet:启用后可获取指定任务当前的优先级。

vTaskDelete:启用后支持删除任务(包括删除自身或其他任务),释放其控制块和堆栈资源。

vTaskCleanUpResources:用于在某些移植层中清理已删除任务的资源,通常较少使用。

vTaskSuspend:启用后可挂起指定任务,使其进入挂起态,不参与调度。

vTaskDelayUntil:启用后支持基于绝对时间的周期性延时,适用于精确定时任务。

vTaskDelay:启用后支持基于相对时间的延时,使任务阻塞指定 tick 数。

xTaskGetSchedulerState:启用后可查询调度器当前状态(未启动、运行中、已挂起)。

xTaskResumeFromISR:启用后允许在中断服务程序中恢复被挂起的任务。

xQueueGetMutexHolder:启用后可获取某个互斥量当前的持有任务句柄。

xSemaphoreGetMutexHolder:与上类似,但通过信号量接口获取互斥量持有者。

pcTaskGetTaskName:启用后可通过任务句柄获取任务名称字符串指针。

uxTaskGetStackHighWaterMark:启用后可获取任务堆栈历史最小剩余量,用于分析栈使用情况。

xTaskGetCurrentTaskHandle:启用后可获取当前正在运行任务的句柄。

eTaskGetState:启用后可查询指定任务的当前状态(运行、就绪、阻塞、挂起、删除)。

xEventGroupSetBitFromISR:启用后支持在中断中设置事件组的位。

xTimerPendFunctionCall:启用后可在中断中将函数调用挂起到定时器服务任务上下文中执行。

xTaskAbortDelay:启用后可强制终止某个任务的阻塞延时状态,使其提前进入就绪态。

xTaskGetHandle:启用后可通过任务名称查找并获取任务句柄。

uxTaskGetStackHighWaterMark2:为 uxTaskGetStackHighWaterMark 的扩展版本,返回类型通常为 configSTACK_DEPTH_TYPE,适用于更大栈深度配置。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注


目录