2025最新超详细FreeRTOS入门教程:第十八章 FreeRTOS多核与SMP支持

摘要

传统的 FreeRTOS 主要运行在 单核 MCU(如 STM32 Cortex-M 系列),其内核设计基于单核抢占式调度。
但是随着 多核嵌入式处理器(如 ARM Cortex-A、ESP32 双核、RISC-V 多核 SoC) 的兴起,FreeRTOS 也逐步扩展出了对 SMP(对称多处理)AMP(非对称多处理) 的支持。

本章将详细介绍:

  • FreeRTOS 在 AMP 模式 下的使用
  • FreeRTOS SMP 内核特性
  • 多核调度机制
  • 在 ESP32、RISC-V 多核平台上的应用
  • 常见问题与优化经验

2025最新超详细FreeRTOS入门教程


一、AMP 与 SMP 简介

1. AMP(Asymmetric Multi-Processing,非对称多核)

  • 每个核独立运行自己的 FreeRTOS 内核或裸机程序
  • 核间通过 消息机制(Queue、Mailbox、共享内存) 通信
  • 适合 任务分工明确 的系统

2. SMP(Symmetric Multi-Processing,对称多核)

  • 所有核共享同一个 FreeRTOS 内核和调度器
  • 任务可以运行在任意 CPU 上
  • 系统负载更均衡,任务迁移灵活
AMP模式
CPU0: FreeRTOS
CPU1: 裸机/另一个RTOS
SMP模式
CPU0 + CPU1共享调度器
所有任务共享就绪队列

二、FreeRTOS 在 AMP 模式下

AMP 是传统 FreeRTOS 在多核平台最常见的运行模式:

  • CPU0 运行 FreeRTOS(负责任务调度、网络、应用逻辑)
  • CPU1 运行裸机任务或另一个 RTOS(如 DSP、专用控制)
  • 核间通信通常通过 共享内存 + 中断

示例:核间通信(ICU)

// CPU0 (FreeRTOS任务)
void vTaskCore0(void *pvParameters)
{
    for(;;)
    {
        sendMessageToCore1("Hello Core1!");
        vTaskDelay(1000);
    }
}

// CPU1 (裸机)
void Core1_Handler(void)
{
    char *msg = receiveMessageFromCore0();
    printf("Core1收到消息: %s\n", msg);
}

三、FreeRTOS SMP 内核

亚马逊官方在 FreeRTOS V10.4 之后引入了 SMP 内核(实验性),目前已在部分平台(如 RISC-V 多核、Linux 仿真环境)得到支持。

特点:

  • 共享全局调度器
  • 就绪队列为 全局队列
  • 任务可以在多个 CPU 上调度
  • 支持 负载均衡

调度方式:

  • 全局优先级调度:优先运行最高优先级任务
  • CPU 亲和性(Affinity):任务可绑定到特定 CPU

四、任务在多核系统中的调度

在 SMP 模式下,任务的状态机扩展为:

被调度
被调度
vTaskDelay/等待事件
事件满足
就绪队列
CPU0
CPU1
阻塞

五、FreeRTOS SMP API 扩展

1. 设置任务 CPU 亲和性

BaseType_t xTaskCreatePinnedToCore(
    TaskFunction_t pvTaskCode,
    const char * const pcName,
    const uint32_t usStackDepth,
    void *pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t *pxCreatedTask,
    const BaseType_t xCoreID
);
  • xCoreID = 0/1 → 固定到某核
  • xCoreID = tskNO_AFFINITY → 任意核

2. 查询当前运行的 CPU

BaseType_t xPortGetCoreID(void);

六、ESP32 双核 FreeRTOS

ESP32 是 FreeRTOS SMP 的一个典型应用平台:

  • CPU0(PRO CPU)
  • CPU1(APP CPU)

默认配置:

  • 系统任务固定在 CPU0
  • 用户任务可选择运行在 CPU0/CPU1 或任意核

示例:

void vTaskBlink(void *pvParameters)
{
    while(1)
    {
        printf("运行在核心 %d\n", xPortGetCoreID());
        vTaskDelay(1000);
    }
}

xTaskCreatePinnedToCore(vTaskBlink, "Blink", 2048, NULL, 1, NULL, 1);

七、RISC-V 多核 FreeRTOS

  • RISC-V 平台通常支持 多核共享内存
  • FreeRTOS SMP 内核已支持 RISC-V 架构
  • 使用 portGET_CORE_ID() 识别当前 CPU
void vTaskCoreAware(void *pvParameters)
{
    int core = portGET_CORE_ID();
    printf("任务运行在RISC-V核心 %d\n", core);
    vTaskDelay(500);
}

八、多核调试与优化

  1. 避免任务竞争同一资源
    • 使用互斥量(Mutex)保护共享外设
  2. 合理设置 CPU 亲和性
    • 实时任务绑定到固定 CPU
    • 非关键任务允许在任意核运行
  3. 减少核间通信开销
    • 使用轻量级机制(任务通知、共享内存)
  4. 调试技巧
    • Tracealyzer / SystemView 支持多核任务追踪
    • 打印当前任务运行的 CPU ID

九、常见问题与解决方法

问题 可能原因 解决方法
任务总是在同一个核运行 未开启 SMP 或任务亲和性设置固定 使用 tskNO_AFFINITY
多核竞争导致死锁 没有加锁保护共享资源 使用互斥量或信号量
性能未提升 高优先级任务阻塞了调度 优化任务优先级设计
核间通信延迟高 使用复杂队列传输 优化为共享内存 + 信号量

十、经验总结

📌 开发建议

  1. 小型 MCU → 通常采用 AMP 模式,让一个核跑 RTOS,另一个核处理专用任务
  2. ESP32/RISC-V → 建议使用 SMP 模式,充分利用双核/多核性能
  3. 实时任务建议绑定 CPU,避免任务迁移带来的抖动
  4. 调试时必须关注 核间同步,这是多核系统最容易出错的地方

十一、总结

通过本章学习,你已经掌握:

  • FreeRTOS 在 AMP 与 SMP 模式下的应用场景
  • SMP 内核的调度机制与任务 CPU 亲和性
  • 在 ESP32 与 RISC-V 多核平台上的应用
  • 多核系统的调试与优化方法

FreeRTOS 的多核支持让它能够从单核 MCU 扩展到更强大的多核 SoC,是未来物联网与边缘计算的重要方向。


🔗 FreeRTOS专栏 👉 下一章:2025最新超详细FreeRTOS入门教程:第十九章 FreeRTOS与中间件集成(TCP/IP、MQTT、文件系统) ——我们将学习如何在 FreeRTOS 上运行网络协议栈、消息队列遥测传输(MQTT)和 FAT 文件系统。


Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐