851 字
4 分钟
嵌入式 RTOS 内核分析:FreeRTOS 的任务调度与内存管理

嵌入式 RTOS 内核分析:FreeRTOS 核心机制#

什么时候需要 RTOS#

很多嵌入式项目从裸机(bare metal)开始。当你的代码中出现这种结构时,就该认真考虑 RTOS 了:

// 裸机时代的"伪多任务"——痛苦的开始
while (1) {
if (flag_10ms) { do_sensor_read(); flag_10ms = 0; }
if (flag_100ms) { do_comm_protocol(); flag_100ms = 0; }
if (uart_data_ready) { process_uart(); }
// 某个任务运行时间太长,其他任务全部延迟...
}

RTOS 解决的核心问题:在资源受限的 MCU 上,让多个不同优先级的任务看起来像是在同时运行。

FreeRTOS 调度器核心#

Tick 中断#

整个调度器的心跳来自 SysTick 定时器中断。默认情况下每 1ms 触发一次(configTICK_RATE_HZ = 1000):

void xPortSysTickHandler(void) {
portDISABLE_INTERRUPTS();
// 更新系统 tick 计数
xTaskIncrementTick();
// 如果需要任务切换
if (xTaskIncrementTick() != pdFALSE) {
// 触发 PendSV——ARM Cortex-M 的上下文切换机制
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
portENABLE_INTERRUPTS();
}

PendSV:ARM 架构的优雅设计#

为什么不在 SysTick ISR 中直接切换?因为 ARM 的中断优先级机制:PendSV 被配置为最低优先级,确保它只在所有高优先级 ISR 处理完毕后执行,避免在中断处理中途切换任务。

// PendSV handler——实际的任务上下文切换
__attribute__((naked)) void xPortPendSVHandler(void) {
__asm volatile (
"mrs r0, psp\n" // 获取当前任务栈指针
"stmdb r0!, {r4-r11}\n" // 保存 callee-saved 寄存器
"str r0, [%[pxCurrentTCB]]\n" // 保存任务栈顶
// ... 选择下一个任务 ...
"ldr r0, [%[pxCurrentTCB]]\n"
"ldmia r0!, {r4-r11}\n" // 恢复新任务的寄存器
"msr psp, r0\n"
"bx lr\n"
:: [pxCurrentTCB] "r" (&pxCurrentTCB)
);
}

队列:FreeRTOS 最核心的 IPC 机制#

队列是 FreeRTOS 内部实现最精妙的数据结构之一:

  • 环形缓冲区实现,无动态内存分配
  • 支持多任务同时等待(读/写),通过链表管理等待任务
  • 带超时的阻塞机制——这是实时性的关键保证

关键数据结构:

typedef struct QueueDefinition {
int8_t *pcHead; // 队列存储区起始
int8_t *pcWriteTo; // 下一个写入位置
int8_t *pcReadFrom; // 下一个读取位置
List_t xTasksWaitingToSend; // 等待发送的任务链表
List_t xTasksWaitingToReceive; // 等待接收的任务链表
volatile UBaseType_t uxMessagesWaiting; // 当前消息数
UBaseType_t uxLength; // 队列容量
UBaseType_t uxItemSize; // 每个元素的大小
} Queue_t;

内存管理策略对比#

FreeRTOS 提供了 5 种内存分配方案(heap_1.c 至 heap_5.c):

方案特点适用场景
heap_1仅分配不释放,无碎片任务数固定的简单系统
heap_2支持释放,使用 best-fit需谨慎,有碎片风险
heap_3封装标准 malloc/free需要线程安全的 malloc
heap_4支持相邻空闲块合并推荐:大多数应用的默认选择
heap_5heap_4 + 多堆区多块非连续 RAM 的 SoC

优先级反转与互斥信号量#

这是 RTOS 实战中必踩的坑:

高优先级 Task A 等待信号量 → 被中优先级 Task B 抢占 →
低优先级 Task C 持有信号量但无法执行 → 死锁!

FreeRTOS 的互斥信号量内置优先级继承机制:当高优任务等待时,持有信号量的低优任务自动继承高优先级,确保它能尽快释放信号量。

裸机到 RTOS 的转变不只是加个调度器,而是思维方式的转变:从”我控制一切流程”到”我设计任务的协作规则”。这个转变比代码更难。

嵌入式 RTOS 内核分析:FreeRTOS 的任务调度与内存管理
https://mizuki.mysqil.com/posts/freertos-kernel-analysis/
作者
AI庄周会不会梦到电子蝴蝶
发布于
2025-07-28
许可协议
CC BY-NC-SA 4.0
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00