μC/OS vs FreeRTOS:嵌入式实时操作系统深度对比

一、引言

在嵌入式实时操作系统(RTOS)领域,μC/OS和FreeRTOS是最具代表性的两大开源内核。两者都遵循RTOS的核心设计原则------确定性调度、低延迟中断响应、可抢占式多任务,但在实现理念、功能特性、生态授权等方面存在显著差异。本文将从内核架构、API设计、同步机制、内存管理、授权模式等维度进行系统对比,帮助开发者做出技术选型决策。


二、项目背景与定位

2.1 发展历史

维度 μC/OS (Micrium OS) FreeRTOS
创始人 Jean J. Labrosse (1992) Richard Barry (2003)
当前维护 Silicon Labs (收购) Amazon Web Services (收购)
最新版本 μC/OS-III v3.08+ FreeRTOS v10.4+ / Kernel v11.x
代码规模 ~15,000行 (III) ~4,000-9,000行 (依配置)
设计目标 商业级可靠性、可认证性 极致轻量、广泛兼容
认证支持 DO-178C, IEC 61508, ISO 26262 通过SafeRTOS商业版提供

2.2 核心定位差异

复制代码
┌─────────────────────────────────────────────────────────────┐
│  μC/OS 定位:商业级、可认证、功能完备的企业级RTOS              │
├─────────────────────────────────────────────────────────────┤
│  • 航空电子 (DO-178C)                                        │
│  • 汽车电子 (ISO 26262)                                      │
│  • 工业控制 (IEC 61508)                                      │
│  • 医疗仪器 (IEC 62304)                                      │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│  FreeRTOS 定位:开源免费、极致轻量、生态广泛的通用RTOS         │
├─────────────────────────────────────────────────────────────┤
│  • 物联网终端设备                                            │
│  • 消费电子产品                                              │
│  • 教育学习与原型开发                                        │
│  • 快速产品迭代                                              │
└─────────────────────────────────────────────────────────────┘

三、内核架构对比

3.1 调度器设计

μC/OS-III:固定优先级 + 时间片轮转
复制代码
// μC/OS-III 调度器特性演示
#include "os.h"

#define TASK_HIGH_PRIO   5u
#define TASK_MED_PRIO    6u   // 同优先级,启用时间片
#define TASK_LOW_PRIO    7u

OS_TCB  TCB_High, TCB_Med1, TCB_Med2, TCB_Low;
CPU_STK Stk_High[512], Stk_Med1[512], Stk_Med2[512], Stk_Low[512];

void TaskHigh(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    
    while (1) {
        // 最高优先级,一旦就绪立即抢占
        HAL_GPIO_TogglePin(LED_HIGH_GPIO_Port, LED_HIGH_Pin);
        OSTimeDly(50u, OS_OPT_TIME_DLY, &err);
    }
}

void TaskMed(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    
    while (1) {
        // 同优先级任务按时间片轮流执行
        HAL_GPIO_TogglePin(LED_MED_GPIO_Port, LED_MED_Pin);
        OSTimeDly(1u, OS_OPT_TIME_DLY, &err);  // 主动让出
    }
}

void SystemInit(void)
{
    OS_ERR err;
    
    OSInit(&err);
    
    // 创建同优先级任务,启用时间片轮转
    OSTaskCreate(&TCB_High, "TaskHigh", TaskHigh, 0, TASK_HIGH_PRIO,
                 Stk_High, 50, 512, 0, 10, 0,  // time_quanta = 10 ticks
                 OS_OPT_TASK_STK_CHK, &err);
    
    OSTaskCreate(&TCB_Med1, "TaskMed1", TaskMed, 0, TASK_MED_PRIO,
                 Stk_Med1, 50, 512, 0, 10, 0,
                 OS_OPT_TASK_STK_CHK, &err);
                 
    OSTaskCreate(&TCB_Med2, "TaskMed2", TaskMed, 0, TASK_MED_PRIO,
                 Stk_Med2, 50, 512, 0, 10, 0,
                 OS_OPT_TASK_STK_CHK, &err);
    
    OSStart(&err);
}
FreeRTOS:灵活配置调度策略
复制代码
// FreeRTOS 调度器特性演示
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

#define TASK_HIGH_PRIO   (configMAX_PRIORITIES - 2)
#define TASK_MED_PRIO    (configMAX_PRIORITIES - 3)
#define TASK_LOW_PRIO    (configMAX_PRIORITIES - 4)

// 堆栈大小以字为单位(非字节!)
#define STACK_SIZE       128

void vTaskHigh(void *pvParameters)
{
    (void)pvParameters;
    
    while (1) {
        HAL_GPIO_TogglePin(LED_HIGH_GPIO_Port, LED_HIGH_Pin);
        vTaskDelay(pdMS_TO_TICKS(500));  // 500ms延时
    }
}

void vTaskMed(void *pvParameters)
{
    (void)pvParameters;
    
    while (1) {
        HAL_GPIO_TogglePin(LED_MED_GPIO_Port, LED_MED_Pin);
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

void SystemInit(void)
{
    // FreeRTOS 配置通过 FreeRTOSConfig.h 进行
    
    xTaskCreate(vTaskHigh, "TaskHigh", STACK_SIZE, NULL,
                TASK_HIGH_PRIO, NULL);
                
    xTaskCreate(vTaskMed, "TaskMed1", STACK_SIZE, NULL,
                TASK_MED_PRIO, NULL);
                
    xTaskCreate(vTaskMed, "TaskMed2", STACK_SIZE, NULL,
                TASK_MED_PRIO, NULL);
    
    // 同优先级时间片在 FreeRTOSConfig.h 中配置:
    // #define configUSE_TIME_SLICING  1
    
    vTaskStartScheduler();  // 永不返回
}

// 可选:协程支持(Co-routines,已较少使用)
// 可选:对称多处理 SMP 支持(FreeRTOS v10+)

3.2 调度器特性对比

特性 μC/OS-III FreeRTOS
调度算法 固定优先级抢占式 + 可选时间片 固定优先级抢占式 + 可选时间片
同优先级调度 时间片轮转(可配置) 时间片轮转(可配置)
空闲任务 内置,可配置钩子 内置,可配置钩子
** tickless 模式** 支持 ✅ 原生支持(低功耗)
多核SMP ❌ 不支持 ✅ v10.4+ 支持
对称多处理 单核设计 ✅ 支持多核均衡负载
调度点 系统调用返回、中断退出 系统调用返回、中断退出

四、任务与同步机制对比

4.1 任务管理

μC/OS-III:显式TCB管理
复制代码
#include "os.h"

// μC/OS-III:用户声明所有内核对象
OS_TCB  AppTaskTCB;
CPU_STK AppTaskStk[512];

void AppTask(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    
    while (1) {
        // 任务内建信号量/消息队列
        OSTaskSemPend(0, OS_OPT_PEND_BLOCKING, NULL, &err);
        // ...
    }
}

void CreateTask(void)
{
    OS_ERR err;
    
    OSTaskCreate(&AppTaskTCB,
                 "AppTask",           // 任务名(调试可见)
                 AppTask,
                 (void *)0,
                 5u,                  // 优先级
                 &AppTaskStk[0],
                 50u,                 // 栈限制(水线)
                 512u,                // 栈大小
                 0u,                  // 消息队列大小
                 0u,                  // 时间片
                 (void *)0,           // 扩展
                 OS_OPT_TASK_STK_CHK,
                 &err);
}
FreeRTOS:动态/静态可选
复制代码
#include "FreeRTOS.h"
#include "task.h"

// 方式1:动态分配(默认)
void CreateTaskDynamic(void)
{
    TaskHandle_t xHandle = NULL;
    
    xTaskCreate(
        vTaskFunction,      // 任务函数
        "TaskName",         // 任务名
        STACK_SIZE,         // 栈深度(字)
        (void *)param,      // 参数
        tskIDLE_PRIORITY + 1, // 优先级
        &xHandle            // 任务句柄
    );
}

// 方式2:静态分配(无需堆内存,适合安全关键系统)
static StaticTask_t xTaskBuffer;
static StackType_t xStack[STACK_SIZE];

void CreateTaskStatic(void)
{
    TaskHandle_t xHandle = xTaskCreateStatic(
        vTaskFunction,
        "StaticTask",
        STACK_SIZE,
        (void *)param,
        tskIDLE_PRIORITY + 1,
        xStack,             // 预分配栈
        &xTaskBuffer        // 预分配TCB
    );
}

4.2 同步机制对比

机制 μC/OS-III FreeRTOS 说明
二进制信号量 OSSem xSemaphoreCreateBinary 任务同步
计数信号量 OSSem xSemaphoreCreateCounting 资源计数
互斥锁 OSMutex(优先级继承) xSemaphoreCreateMutex(优先级继承) 互斥访问
递归互斥锁 ❌ 不支持 xSemaphoreCreateRecursiveMutex 递归锁定
事件标志组 OSFlagGrp(原生) xEventGroup 多条件等待
消息队列 OSQ xQueue 消息传递
流缓冲区 ❌ 不支持 xStreamBuffer 字节流通信
消息缓冲区 ❌ 不支持 xMessageBuffer 变长消息
任务通知 OSTaskSem/OSTaskQ xTaskNotify 轻量级同步
软件定时器 OS_TMR(原生) TimerHandle_t 回调定时器

4.3 同步代码对比

互斥锁使用
复制代码
// ========== μC/OS-III ==========
#include "os.h"

OS_MUTEX g_sensorMutex;
SensorData_t g_sensorData;

void SensorTask(void *p_arg)
{
    OS_ERR err;
    p_arg = p_arg;
    
    OSMutexCreate(&g_sensorMutex, "SensorMutex", &err);
    
    while (1) {
        OSMutexPend(&g_sensorMutex, 0, OS_OPT_PEND_BLOCKING, 0, &err);
        
        // 读取传感器...
        g_sensorData.temperature = ReadTemp();
        
        OSMutexPost(&g_sensorMutex, OS_OPT_POST_NONE, &err);
        
        OSTimeDly(100, OS_OPT_TIME_DLY, &err);
    }
}

// ========== FreeRTOS ==========
#include "FreeRTOS.h"
#include "semphr.h"

SemaphoreHandle_t g_sensorMutex;
SensorData_t g_sensorData;

void SensorTask(void *pvParameters)
{
    (void)pvParameters;
    
    g_sensorMutex = xSemaphoreCreateMutex();
    configASSERT(g_sensorMutex != NULL);
    
    while (1) {
        if (xSemaphoreTake(g_sensorMutex, portMAX_DELAY) == pdTRUE) {
            
            // 读取传感器...
            g_sensorData.temperature = ReadTemp();
            
            xSemaphoreGive(g_sensorMutex);
        }
        
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}
事件标志组使用
复制代码
// ========== μC/OS-III ==========
#include "os.h"

OS_FLAG_GRP g_eventFlags;

#define EVT_WIFI_CONNECTED  0x01
#define EVT_SERVER_READY    0x02
#define EVT_DATA_RECEIVED   0x04

void InitEvents(void)
{
    OS_ERR err;
    OSFlagCreate(&g_eventFlags, "NetEvents", 0, &err);
}

void NetworkTask(void *p_arg)
{
    OS_ERR err;
    OS_FLAGS flags;
    
    p_arg = p_arg;
    
    while (1) {
        // 等待多个事件:WiFi连接 且 服务器就绪
        flags = OSFlagPend(&g_eventFlags,
                           EVT_WIFI_CONNECTED | EVT_SERVER_READY,
                           0,
                           OS_OPT_PEND_FLAG_SET_ALL | OS_OPT_PEND_FLAG_CONSUME,
                           NULL,
                           &err);
        
        if (err == OS_ERR_NONE) {
            // 网络就绪,开始传输
        }
    }
}

void WifiCallback(void)
{
    OS_ERR err;
    OSFlagPost(&g_eventFlags, EVT_WIFI_CONNECTED, OS_OPT_POST_FLAG_SET, &err);
}

// ========== FreeRTOS ==========
#include "FreeRTOS.h"
#include "event_groups.h"

EventGroupHandle_t g_eventFlags;

#define EVT_WIFI_CONNECTED  (1 << 0)
#define EVT_SERVER_READY    (1 << 1)
#define EVT_DATA_RECEIVED   (1 << 2)

void InitEvents(void)
{
    g_eventFlags = xEventGroupCreate();
    configASSERT(g_eventFlags != NULL);
}

void NetworkTask(void *pvParameters)
{
    (void)pvParameters;
    EventBits_t flags;
    
    while (1) {
        // 等待多个事件
        flags = xEventGroupWaitBits(
                    g_eventFlags,
                    EVT_WIFI_CONNECTED | EVT_SERVER_READY,
                    pdTRUE,         // 清除位
                    pdTRUE,         // 等待所有位
                    portMAX_DELAY);
        
        if ((flags & (EVT_WIFI_CONNECTED | EVT_SERVER_READY)) 
            == (EVT_WIFI_CONNECTED | EVT_SERVER_READY)) {
            // 网络就绪
        }
    }
}

void WifiCallback(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xEventGroupSetBitsFromISR(g_eventFlags, EVT_WIFI_CONNECTED, 
                              &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

五、内存管理对比

5.1 μC/OS-III:固定分区 + 静态分配

复制代码
#include "os.h"

// 方案1:固定大小内存分区(推荐)
OS_MEM  g_memPartition;
CPU_INT08U g_memPool[10][256];  // 10个256字节块

void InitMemory(void)
{
    OS_ERR err;
    
    OSMemCreate(&g_memPartition,
                "MemPool",
                &g_memPool[0][0],
                10u,
                256u,
                &err);
}

void* AllocateBlock(void)
{
    OS_ERR err;
    return OSMemGet(&g_memPartition, &err);
}

void FreeBlock(void *p_blk)
{
    OS_ERR err;
    OSMemPut(&g_memPartition, p_blk, &err);
}

// 方案2:完全静态分配(安全关键系统)
// μC/OS-III 所有对象均可静态声明,无需堆

5.2 FreeRTOS:多种堆算法可选

复制代码
#include "FreeRTOS.h"

// FreeRTOS 提供5种堆实现(heap_1.c ~ heap_5.c):

// heap_1.c: 只分配不释放(最简单,无碎片)
// heap_2.c: 最佳匹配算法(有碎片)
// heap_3.c: 包装标准库 malloc/free(线程安全)
// heap_4.c: 首次匹配算法 + 合并相邻空闲块(推荐)
// heap_5.c: heap_4 + 跨多个非连续内存区域

// 配置选择:FreeRTOSConfig.h
// #define configUSE_HEAP_SCHEME  4

// 使用示例
void* pvBuffer = pvPortMalloc(256);  // 使用FreeRTOS堆
vPortFree(pvBuffer);

// 静态分配(无需堆)
static StaticTask_t xTaskBuffer;
static StackType_t xStack[128];
TaskHandle_t xHandle = xTaskCreateStatic(...);

// 静态队列
static StaticQueue_t xQueueBuffer;
static uint8_t ucQueueStorage[10 * sizeof(MyMsg)];
QueueHandle_t xQueue = xQueueCreateStatic(10, sizeof(MyMsg), 
                                          ucQueueStorage, &xQueueBuffer);

5.3 内存管理对比

特性 μC/OS-III FreeRTOS
固定分区 ✅ 原生支持 ❌ 需自行实现
动态分配 有限支持 ✅ 5种堆算法可选
静态分配 ✅ 完全支持 ✅ 完全支持
内存碎片处理 无(固定大小无碎片) heap_4/5合并相邻块
跨RAM区域 ❌ 不支持 ✅ heap_5支持
内存保护 ❌ 无MPU支持 ✅ FreeRTOS-MPU
堆溢出检测 栈检查 configCHECK_FOR_STACK_OVERFLOW

六、中断与低功耗

6.1 中断处理模型

μC/OS-III:传统中断嵌套
复制代码
// μC/OS-III 中断处理
#include "os.h"

void TIM2_IRQHandler(void)
{
    OS_ERR err;
    
    OSIntEnter(&err);  // 进入中断
    
    // 清除中断标志
    TIM2->SR &= ~TIM_SR_UIF;
    
    // 发布信号量
    OSSemPost(&g_timSem, OS_OPT_POST_NONE, &err);
    
    OSIntExit(&err);   // 退出中断,可能触发调度
}
FreeRTOS:更灵活的中断安全API
复制代码
// FreeRTOS 中断处理
#include "FreeRTOS.h"
#include "task.h"

void TIM2_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    // 清除中断标志
    TIM2->SR &= ~TIM_SR_UIF;
    
    // 从中断安全地释放信号量
    xSemaphoreGiveFromISR(g_timSem, &xHigherPriorityTaskWoken);
    
    // 上下文切换(如果使用portYIELD_FROM_ISR)
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

6.2 Tickless 低功耗模式

复制代码
// ========== FreeRTOS 原生支持 Tickless ==========
// FreeRTOSConfig.h
#define configUSE_TICKLESS_IDLE  1
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP  2

// 可选:自定义低功耗实现
void vApplicationSleep(TickType_t xExpectedIdleTime)
{
    // 进入MCU低功耗模式
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}

// ========== μC/OS-III 需自行实现 ==========
// 无原生tickless支持,需通过钩子实现

void App_OS_IdleTaskHook(void)
{
    // 检测空闲时间,手动进入低功耗
    if (SystemIdleTime() > MIN_SLEEP_TIME) {
        EnterLowPowerMode();
    }
}

6.3 中断与功耗对比

特性 μC/OS-III FreeRTOS
中断嵌套 支持 支持
中断安全API *Post函数 *FromISR后缀函数
延迟中断处理 直接发布 xHigherPriorityTaskWoken机制
Tickless低功耗 ❌ 需自行实现 ✅ 原生支持
低功耗钩子 空闲任务钩子 vApplicationSleep
中断延迟 ~12-25个时钟周期 ~12-20个时钟周期

七、调试与诊断

7.1 μC/OS-III:内置统计与追踪

复制代码
#include "os.h"

// μC/OS-III 内置丰富的统计功能

void InitDiagnostics(void)
{
    OS_ERR err;
    
    // 启用统计任务(计算CPU使用率)
    OSStatTaskCPUUsageInit(&err);
}

void PrintStats(void)
{
    OS_ERR err;
    
    // 获取CPU使用率
    CPU_USAGE usage = OSStatTaskCPUUsage;
    
    // 获取中断禁用时间
    CPU_TS int_dis_time = OSIntDisTimeMax;
    
    // 获取调度锁定时间
    CPU_TS sched_lock_time = OSSchedLockTimeMax;
    
    // 遍历所有任务,打印状态
    OS_TCB *p_tcb;
    OS_ERR err_local;
    
    p_tcb = OSTCBList;  // 任务链表头
    while (p_tcb != (OS_TCB *)0) {
        printf("Task: %s, Prio: %d, CPU%%: %d, StkUsed: %d\n",
               p_tcb->NamePtr,
               p_tcb->Prio,
               p_tcb->CPUUsage,
               p_tcb->StkUsed);
        p_tcb = p_tcb->NextPtr;
    }
}

// 内置内核感知调试支持
// 兼容IAR、Keil、Segger等调试器的RTOS插件

7.2 FreeRTOS:可配置追踪

复制代码
#include "FreeRTOS.h"
#include "task.h"

// FreeRTOS 通过配置启用统计

// FreeRTOSConfig.h
#define configUSE_TRACE_FACILITY          1
#define configUSE_STATS_FORMATTING_FUNCTIONS  1
#define configGENERATE_RUN_TIME_STATS     1

// 提供时间基准
volatile uint32_t ulHighFrequencyTimerTicks;

void ConfigureTimerForRunTimeStats(void)
{
    // 初始化高精度定时器
}

uint32_t GetRunTimeCounterValue(void)
{
    return ulHighFrequencyTimerTicks;
}

void PrintTaskStats(void)
{
    // 分配缓冲区
    static char pcWriteBuffer[512];
    
    // 获取任务状态表
    vTaskList(pcWriteBuffer);
    printf("Task Name\tState\tPrio\tStack\tNum\n%s", pcWriteBuffer);
    
    // 获取CPU使用率
    vTaskGetRunTimeStats(pcWriteBuffer);
    printf("Runtime Stats:\n%s", pcWriteBuffer);
}

// 第三方追踪:FreeRTOS+Trace, SystemView
// 商业方案:Percepio Tracealyzer

7.3 调试能力对比

特性 μC/OS-III FreeRTOS
任务状态查看 内置链表遍历 vTaskList()
CPU使用率统计 内置统计任务 需配置运行时统计
栈溢出检测 OS_OPT_TASK_STK_CHK configCHECK_FOR_STACK_OVERFLOW
中断禁用时间 自动测量 需自行实现
内核感知调试 原生支持主流IDE 需插件/配置
第三方追踪工具 Micrium工具链 Tracealyzer, SystemView
断言机制 OS_ASSERT configASSERT

八、授权模式与商业生态

8.1 许可证对比

维度 μC/OS (Micrium OS) FreeRTOS
开源许可证 Apache 2.0 (2016年后) MIT
商业授权 需购买(旧版本) 无需
闭源使用 ✅ 允许 ✅ 允许
修改后分发 ✅ 允许 ✅ 允许
专利授权 Apache 2.0明确授予 MIT隐含
安全认证版 包含在授权中 SafeRTOS需单独购买

8.2 生态与中间件

复制代码
┌─────────────────────────────────────────────────────────────┐
│  μC/OS 生态(Silicon Labs)                                │
├─────────────────────────────────────────────────────────────┤
│  内核:μC/OS-III / Micrium OS                              │
│  文件系统:μC/FS(FAT/exFAT)                              │
│  网络协议:μC/TCP-IP(IPv4/IPv6)                          │
│  USB协议:μC/USB-Host/Device/OTG                           │
│  GUI:μC/GUI(emWin)                                      │
│  安全:μC/Crypto, μC/SSL-TLS                              │
│  认证:DO-178C, IEC 61508, ISO 26262(完整包)             │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│  FreeRTOS 生态(AWS)                                       │
├─────────────────────────────────────────────────────────────┤
│  内核:FreeRTOS Kernel                                      │
│  库:FreeRTOS-Plus(TCP, FAT, CLI, Trace)                 │
│  AWS集成:AWS IoT, AWS OTA, AWS Jobs                        │
│  安全:AWS IoT Device Defender, mbedTLS                    │
│  认证:SafeRTOS(WITTENSTEIN,单独购买)                    │
│  社区:极其活跃的GitHub社区,大量第三方库                   │
└─────────────────────────────────────────────────────────────┘

九、完整应用示例对比

9.1 传感器数据采集系统

μC/OS-III 实现
复制代码
// sensor_system_ucos.c
#include "os.h"
#include "bsp.h"

#define TASK_SENSOR_PRIO    5u
#define TASK_FILTER_PRIO    6u
#define TASK_UPLOAD_PRIO    7u
#define TASK_MONITOR_PRIO   8u

// 内核对象声明
OS_TCB  TCB_Sensor, TCB_Filter, TCB_Upload, TCB_Monitor;
CPU_STK Stk_Sensor[512], Stk_Filter[512], Stk_Upload[512], Stk_Monitor[256];

OS_MUTEX    g_dataMutex;
OS_Q        g_rawQueue;
OS_FLAG_GRP g_sysFlags;
OS_TMR      g_sampleTmr;

#define EVT_SAMPLE_READY    0x01
#define EVT_NETWORK_OK      0x02
#define EVT_ERROR_FLAG      0x04

typedef struct {
    uint32_t timestamp;
    float    temperature;
    float    humidity;
    float    pressure;
} SensorData_t;

void *g_msgPool[16];  // 消息队列缓冲区

// 采样定时器回调
void SampleTimerCallback(void *p_tmr, void *p_arg)
{
    OS_ERR err;
    (void)p_tmr; (void)p_arg;
    
    // 触发采样任务
    OSFlagPost(&g_sysFlags, EVT_SAMPLE_READY, OS_OPT_POST_FLAG_SET, &err);
}

void TaskSensor(void *p_arg)
{
    OS_ERR err;
    OS_FLAGS flags;
    SensorData_t *p_data;
    
    p_arg = p_arg;
    
    while (1) {
        // 等待采样信号
        flags = OSFlagPend(&g_sysFlags,
                           EVT_SAMPLE_READY,
                           0,
                           OS_OPT_PEND_FLAG_SET_ANY | OS_OPT_PEND_FLAG_CONSUME,
                           NULL,
                           &err);
        
        // 从内存池分配
        p_data = OSMemGet(&g_memPool, &err);
        if (err != OS_ERR_NONE) continue;
        
        // 读取传感器
        p_data->timestamp = OSTimeGet(&err);
        p_data->temperature = BSP_TempRead();
        p_data->humidity = BSP_HumiRead();
        p_data->pressure = BSP_PresRead();
        
        // 发送到处理队列
        OSQPost(&g_rawQueue,
                (void *)p_data,
                sizeof(SensorData_t),
                OS_OPT_POST_FIFO,
                &err);
    }
}

void TaskFilter(void *p_arg)
{
    OS_ERR err;
    OS_MSG_SIZE msg_size;
    CPU_TS ts;
    SensorData_t *p_data;
    
    p_arg = p_arg;
    
    while (1) {
        p_data = (SensorData_t *)OSQPend(&g_rawQueue,
                                          0,
                                          OS_OPT_PEND_BLOCKING,
                                          &msg_size,
                                          &ts,
                                          &err);
        
        // 卡尔曼滤波处理
        OSMutexPend(&g_dataMutex, 0, OS_OPT_PEND_BLOCKING, 0, &err);
        KalmanFilter(p_data);
        OSMutexPost(&g_dataMutex, OS_OPT_POST_NONE, &err);
        
        // 通知上传任务
        OSTaskSemPost(&TCB_Upload, OS_OPT_POST_NONE, &err);
    }
}

void SystemInit(void)
{
    OS_ERR err;
    
    OSInit(&err);
    BSP_Init();
    
    // 创建同步对象
    OSMutexCreate(&g_dataMutex, "DataMutex", &err);
    OSQCreate(&g_rawQueue, "RawQueue", 16, &err);
    OSFlagCreate(&g_sysFlags, "SysFlags", 0, &err);
    OSMemCreate(&g_memPool, "DataPool", g_memBuf, 16, sizeof(SensorData_t), &err);
    
    // 创建定时器:100ms周期采样
    OSTmrCreate(&g_sampleTmr, "SampleTmr", 10, 10,
                OS_TMR_OPT_PERIODIC, SampleTimerCallback, 0, &err);
    
    // 创建任务
    OSTaskCreate(&TCB_Sensor, "Sensor", TaskSensor, 0,
                 TASK_SENSOR_PRIO, Stk_Sensor, 50, 512, 0, 0, 0,
                 OS_OPT_TASK_STK_CHK, &err);
    // ... 其他任务
    
    OSTmrStart(&g_sampleTmr, &err);
    OSStart(&err);
}
FreeRTOS 实现
复制代码
// sensor_system_freertos.c
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
#include "timers.h"

#define TASK_SENSOR_PRIO    (configMAX_PRIORITIES - 2)
#define TASK_FILTER_PRIO    (configMAX_PRIORITIES - 3)
#define TASK_UPLOAD_PRIO    (configMAX_PRIORITIES - 4)

#define EVT_SAMPLE_READY    (1 << 0)
#define EVT_NETWORK_OK      (1 << 1)

typedef struct {
    uint32_t timestamp;
    float    temperature;
    float    humidity;
    float    pressure;
} SensorData_t;

// 静态分配所有对象
static StaticTask_t xSensorTCB, xFilterTCB, xUploadTCB;
static StackType_t xSensorStk[128], xFilterStk[128], xUploadStk[128];

static StaticSemaphore_t xMutexBuffer;
static StaticQueue_t xQueueBuffer;
static StaticEventGroup_t xEventBuffer;
static StaticTimer_t xTimerBuffer;

static uint8_t ucQueueStorage[16 * sizeof(SensorData_t)];

SemaphoreHandle_t xDataMutex;
QueueHandle_t xRawQueue;
EventGroupHandle_t xSysEvents;
TimerHandle_t xSampleTimer;

// 采样定时器回调
void vSampleTimerCallback(TimerHandle_t xTimer)
{
    (void)xTimer;
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    
    xEventGroupSetBitsFromISR(xSysEvents, EVT_SAMPLE_READY, 
                              &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void vTaskSensor(void *pvParameters)
{
    (void)pvParameters;
    EventBits_t xBits;
    SensorData_t xData;
    
    while (1) {
        xBits = xEventGroupWaitBits(xSysEvents,
                                    EVT_SAMPLE_READY,
                                    pdTRUE,     // 清除位
                                    pdFALSE,    // 等待任意
                                    portMAX_DELAY);
        
        if (xBits & EVT_SAMPLE_READY) {
            xData.timestamp = xTaskGetTickCount();
            xData.temperature = BSP_TempRead();
            xData.humidity = BSP_HumiRead();
            xData.pressure = BSP_PresRead();
            
            // 发送到队列(复制数据)
            xQueueSend(xRawQueue, &xData, portMAX_DELAY);
        }
    }
}

void vTaskFilter(void *pvParameters)
{
    (void)pvParameters;
    SensorData_t xData;
    
    while (1) {
        if (xQueueReceive(xRawQueue, &xData, portMAX_DELAY) == pdTRUE) {
            
            xSemaphoreTake(xDataMutex, portMAX_DELAY);
            KalmanFilter(&xData);
            xSemaphoreGive(xDataMutex);
            
            // 通知上传任务
            xTaskNotifyGive(xUploadHandle);
        }
    }
}

void SystemInit(void)
{
    // 静态创建所有对象(无需堆)
    xDataMutex = xSemaphoreCreateMutexStatic(&xMutexBuffer);
    xRawQueue = xQueueCreateStatic(16, sizeof(SensorData_t),
                                   ucQueueStorage, &xQueueBuffer);
    xSysEvents = xEventGroupCreateStatic(&xEventBuffer);
    xSampleTimer = xTimerCreateStatic("SampleTmr",
                                      pdMS_TO_TICKS(100),
                                      pdTRUE,
                                      NULL,
                                      vSampleTimerCallback,
                                      &xTimerBuffer);
    
    // 静态创建任务
    xTaskCreateStatic(vTaskSensor, "Sensor", 128, NULL,
                      TASK_SENSOR_PRIO, xSensorStk, &xSensorTCB);
    xTaskCreateStatic(vTaskFilter, "Filter", 128, NULL,
                      TASK_FILTER_PRIO, xFilterStk, &xFilterTCB);
    // ... 其他任务
    
    xTimerStart(xSampleTimer, 0);
    vTaskStartScheduler();
}

十、选型决策指南

10.1 选择 μC/OS 的场景

场景 理由
航空/汽车/医疗认证 原生支持DO-178C、ISO 26262、IEC 61508
严格确定性要求 内核行为更可预测,适合硬实时系统
商业技术支持 Silicon Labs提供专业技术支持
完整中间件栈 文件系统、网络、USB、GUI一体化
团队熟悉度 已有μC/OS开发经验和代码积累

10.2 选择 FreeRTOS 的场景

场景 理由
成本敏感项目 MIT许可证,完全免费商用
极致资源受限 最小内核仅需4-9KB ROM
多核处理器 原生SMP支持
低功耗物联网 原生Tickless,AWS IoT深度集成
快速原型开发 社区庞大,示例丰富,移植简单
需要动态内存 多种堆算法,支持跨RAM区域分配

10.3 快速决策流程图

复制代码
                    ┌─────────────────┐
                    │  开始RTOS选型    │
                    └────────┬────────┘
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
        ┌─────────┐   ┌──────────┐   ┌──────────┐
        │需要安全  │   │资源极度  │   │需要多核  │
        │认证?    │   │受限?    │   │SMP?     │
        └────┬────┘   └────┬─────┘   └────┬─────┘
             │             │              │
           是│           是│            是│
             ▼             ▼              ▼
        ┌─────────┐   ┌──────────┐   ┌──────────┐
        │ μC/OS   │   │FreeRTOS  │   │FreeRTOS  │
        │ + 认证包 │   │最小配置  │   │SMP版本   │
        └─────────┘   └──────────┘   └──────────┘
             │             │              │
             └─────────────┴──────────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │  需要完整中间件? │
                    └────────┬────────┘
                             │
                    ┌────────┴────────┐
                    ▼                 ▼
                   是                否
                    │                 │
                    ▼                 ▼
              ┌─────────┐      ┌──────────┐
              │ μC/OS   │      │ FreeRTOS │
              │ 全家桶   │      │ + 社区库 │
              └─────────┘      └──────────┘

十一、总结

对比维度 μC/OS-III FreeRTOS
代码体积 较大(功能丰富) 较小(可裁剪)
RAM占用 较高 较低
功能完备性 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
类型安全 强(显式错误码) 中等(返回码检查)
静态分配支持 完全 完全
动态分配 有限 丰富
低功耗 需自行实现 原生Tickless
多核支持 ✅ SMP
安全认证 ✅ 原生 需SafeRTOS
授权成本 免费(Apache 2.0) 免费(MIT)
社区活跃度 中等 ⭐⭐⭐⭐⭐
学习曲线 较陡 平缓
调试工具 专业级 丰富多样

最终建议:

  • 新项目、通用嵌入式 :优先评估 FreeRTOS,生态活跃,社区支持好

  • 安全关键、认证项目 :选择 μC/OS + 认证包,确定性更强

  • 资源极度受限(<8KB Flash)FreeRTOS 最小配置

  • 需要完整中间件栈μC/OS 全家桶或 FreeRTOS + 第三方库

相关推荐
石山代码1 小时前
c++类型判断
开发语言·c++
froginwe111 小时前
传输对象模式
开发语言
振南的单片机世界1 小时前
电机反电动势:断电瞬间的“高压反击”,续流二极管挡驾
单片机·嵌入式硬件
绝世唐门三哥1 小时前
ES6 --- import/export 全解析
开发语言·前端·javascript
yqcoder1 小时前
JavaScript 异步基石:Promise 完全指南
开发语言·前端·javascript
wangl_921 小时前
初探 C# 15 的 Union Types
java·开发语言·算法·c#·.net·.net core
故事和你911 小时前
洛谷-【图论2-1】树2
开发语言·数据结构·c++·算法·动态规划·图论
折哥的程序人生 · 物流技术专研1 小时前
Java面试85题图解版 · 全系列总目录
java·开发语言·后端·面试·职场和发展
gf13211112 小时前
飞书长连接_事件订阅(接收消息,审批任务状态变更)
开发语言·python·飞书