以下是对这两种 RTOS 的简要介绍和关键特性的对比,供你参考:


1. uC/OS(Micro-Controller Operating System)

由 Jean J. Labrosse 开发,是一个可移植、可裁剪、抢占式实时内核,广泛用于嵌入式系统。

主要特点:
  • 抢占式调度:高优先级任务可立即抢占低优先级任务。
  • 确定性:响应时间可预测,适合硬实时系统。
  • 模块化设计:内核小巧(通常 <10KB),可按需裁剪。
  • 任务管理:支持多达 64 个任务(uC/OS-II)或更多(uC/OS-III 支持任意数量任务)。
  • 资源管理:提供信号量、互斥锁、消息队列、事件标志组等 IPC 机制。
  • 商业授权:uC/OS-II/III 原为商业软件(现部分版本已开源,如 uC/OS under Apache 2.0)。
典型应用场景:
  • 工业控制
  • 医疗设备
  • 航空航天

2. FreeRTOS

由 Richard Barry 开发,现由 Amazon 维护(称为 AWS FreeRTOS),是开源(MIT 许可)且广泛使用的轻量级 RTOS。

主要特点:
  • 开源免费:MIT 许可,可自由用于商业项目。
  • 高度可移植:支持 40+ 种 MCU 架构(ARM Cortex-M、RISC-V、ESP32 等)。
  • 轻量级:内核仅需几 KB RAM/ROM。
  • 任务与调度:支持优先级调度、时间片轮转(需配置)。
  • 丰富的中间件:支持 TCP/IP、文件系统、OTA、安全库(通过 AWS FreeRTOS 扩展)。
  • 活跃社区:文档完善,示例丰富。
典型应用场景:
  • IoT 设备(如智能传感器、网关)
  • 消费电子
  • 教学与原型开发

对比简表:

特性 uC/OS FreeRTOS
授权 原商业(部分开源) MIT 开源(完全免费)
调度方式 抢占式 抢占式(可配时间片)
最大任务数 uC/OS-II: 64;III: 无限制 仅受内存限制
内存占用 极小(可 <5KB)
社区与生态 较小,偏工业 非常活跃,IoT 生态强
中间件支持 有限 丰富(尤其 AWS 扩展)

如果你有具体问题,比如:

  • 如何在 STM32 上移植 FreeRTOS?
  • uC/OS-III 的任务间通信机制如何使用?
  • RTOS 中优先级反转问题怎么解决?

2.UCoS

你提到的 UCoS,通常是指 μC/OS(Micro-Controller Operating System),由 Jean J. Labrosse 于 1991 年首次发布。它是嵌入式领域最具影响力的实时操作系统(RTOS)之一,尤其在对确定性、可靠性、可认证性要求高的工业和安全关键系统中广泛应用。

目前主要有两个主流版本:


μC/OS-II

  • 发布于 1998 年
  • 固定最多支持 64 个任务(优先级 0~63,其中 0 和 63 通常保留)
  • 每个任务必须有唯一优先级(不支持同优先级多任务)
  • 抢占式调度,硬实时
  • 内核代码清晰,适合教学与小型系统
  • 曾广泛用于医疗设备、工业控制器等

⚠️ 注意:μC/OS-II 已停止官方更新,但仍在大量 legacy 系统中运行。


μC/OS-III

  • 发布于 2009 年
  • 支持任意数量任务(仅受限于 RAM)
  • 允许多个任务共享同一优先级(可配置为时间片轮转调度)
  • 支持更灵活的任务调度策略
  • 增强了内核服务(如时间戳、任务寄存器、运行时统计等)
  • 更适合现代复杂嵌入式应用

🔧 μC/OS 核心特性

功能 说明
任务管理 创建、删除、挂起、恢复任务;基于优先级抢占
时间管理 提供 OSTimeDly()OSTimeDlyHMSM() 等延时函数
同步与通信 信号量(二值/计数)、互斥锁(带优先级继承防反转)、消息队列、事件标志组、邮箱(μC/OS-II)
内存管理 固定大小内存块分配(避免碎片),通过内存分区(OS_MEM)实现
中断处理 中断服务程序(ISR)可发送信号或消息给任务,但不能直接调用阻塞 API
可裁剪性 通过 os_cfg.h 配置所需功能,最小内核可 <5KB

📌 典型代码结构(μC/OS-II 示例)

#include "includes.h"

#define TASK_STK_SIZE 512
OS_STK TaskStartStk[TASK_STK_SIZE];
OS_STK TaskUserStk[TASK_STK_SIZE];

void TaskStart(void *pdata);
void TaskUser(void *pdata);

int main(void)
{
    OSInit();                          // 初始化 μC/OS-II
    OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
    OSStart();                         // 启动多任务调度
    return 0;
}

void TaskStart(void *pdata)
{
    (void)pdata;
    OSStatInit();                      // 初始化统计任务(可选)
    OSTaskCreate(TaskUser, (void *)0, &TaskUserStk[TASK_STK_SIZE - 1], 1);
    for (;;) {
        OSTimeDly(OS_TICKS_PER_SEC);   // 每秒执行一次
    }
}

void TaskUser(void *pdata)
{
    (void)pdata;
    while (1) {
        // 用户任务逻辑
        OSTimeDly(100);                // 延时 100 个 tick
    }
}

📚 开源状态(重要更新!)

  • 2020 年,Silicon Labs(收购了 Micrium)宣布将 μC/OS 内核开源,采用 Apache 2.0 许可证
  • 开源项目托管在 GitHub:
    👉 https://github.com/weston-embedded/uC-OS3
    (包含 μC/OS-II、μC/OS-III、以及中间件如 USB、TCP/IP、文件系统等)

这意味着你现在可以免费用于商业产品,无需授权费用!


💡 使用建议

  • 学习/教学:μC/OS-II 代码简洁,适合理解 RTOS 原理。
  • 新项目开发:推荐使用 μC/OS-III(功能更强,且已开源)。
  • 安全认证需求(如 ISO 26262、IEC 61508):μC/OS 提供认证包(需联系 Weston Embedded)。

3.UCoS的架构

μC/OS(Micro-Controller Operating System)是由 Jean J. Labrosse 开发的一款实时操作系统(RTOS),广泛用于嵌入式系统。其架构设计强调可移植性、可裁剪性、抢占式多任务调度确定性响应。目前主流版本包括 μC/OS-II 和 μC/OS-III。

以下是 μC/OS 的核心架构组成:


1. 内核(Kernel)

μC/OS 的核心,负责任务管理、调度、同步与通信等基本功能。

  • 任务管理:支持多个任务(线程),每个任务是一个无限循环的 C 函数。
  • 任务状态:就绪(Ready)、运行(Running)、挂起(Pending)、休眠(Dormant)等。
  • 任务控制块(TCB, Task Control Block):每个任务对应一个 TCB,存储任务堆栈指针、优先级、状态等信息。

2. 调度器(Scheduler)

  • 基于优先级的抢占式调度:高优先级任务一旦就绪,立即抢占低优先级任务。
  • μC/OS-II:每个优先级只能有一个任务(固定优先级数量,通常为 8~255)。
  • μC/OS-III:支持同优先级多任务,并引入时间片轮转调度(Round-Robin)。

3. 时间管理(Time Management)

  • 依赖系统节拍(Tick),由硬件定时器定期产生中断(如每 1ms 一次)。
  • 提供延时函数(如 OSTimeDly())、超时机制等。
  • 系统节拍中断服务程序(OSTickISR)更新系统时间并处理延时任务唤醒。

###4. 任务间通信与同步机制
μC/OS 提供多种内核对象用于任务协作:

对象类型 功能说明
信号量(Semaphore) 用于资源计数或任务同步
互斥信号量(Mutex) 支持优先级继承,防止优先级反转
消息邮箱(Mailbox) 单消息传递(μC/OS-II)
消息队列(Message Queue) 多消息 FIFO 传递
事件标志组(Event Flags) 多条件同步(μC/OS-III 增强)

5. 内存管理

  • 固定大小内存块分配:通过内存分区(Memory Partition)避免碎片。
  • 分配/释放操作是确定性的(O(1) 时间复杂度),适合实时系统。

6. 可移植层(Portability Layer)

μC/OS 架构分为与处理器无关代码(ANSI C)和与处理器相关代码(汇编/C):

  • OS_CPU.H:定义数据类型、堆栈增长方向、临界区宏等。
  • OS_CPU_C.C:实现任务切换钩子、节拍钩子等。
  • OS_CPU_A.ASM:用汇编实现上下文切换(如保存/恢复寄存器)。

这使得 μC/OS 可轻松移植到 ARM Cortex-M、RISC-V、MIPS、x86 等架构。


7. 中断处理

  • 中断服务程序(ISR)应尽量短,可通过向任务发送信号/消息来延迟处理。
  • 进入/退出 ISR 需调用 OSIntEnter() / OSIntExit()
  • 支持中断嵌套(取决于硬件和移植实现)。

8. 确定性与实时性

  • 所有内核服务具有可预测的执行时间
  • 无动态内存分配(避免不确定延迟)。
  • 任务切换时间通常在微秒级。

μC/OS-II vs μC/OS-III 主要区别

特性 μC/OS-II μC/OS-III
同优先级任务 不支持 支持(可配置时间片)
任务数量 固定(≤255) 动态(仅受 RAM 限制)
内核对象数量 编译时固定 运行时可创建
事件标志 支持
调试与统计功能 有限 更丰富(任务执行时间统计等)

总结

μC/OS 的架构体现了简洁、高效、确定性的嵌入式 RTOS 设计哲学,特别适合对实时性、可靠性要求高的工业控制、医疗设备、航空航天等领域。自 2020 年起,Micrium(原开发商)被 Silicon Labs 收购后,μC/OS 已开源(Apache 2.0 许可),可在 GitHub 获取源码。

4.FreeRTOS详解

FreeRTOS(Free Real-Time Operating System)是一款轻量级、开源免费嵌入式实时操作系统内核,专为资源受限的微控制器(MCU)设计。它由 Real Time Engineers Ltd 开发,采用 MIT 许可证发布,广泛应用于物联网(IoT)、工业控制、医疗设备、消费电子等领域。


一、为什么需要 FreeRTOS?

在没有 RTOS 的“裸机”开发中,程序通常以单线程顺序执行,难以高效处理多个并发事件(如按键响应、传感器读取、网络通信等)。而 FreeRTOS 提供了:

  • 多任务并发:逻辑上“同时”运行多个任务。
  • 确定性响应:高优先级任务能及时抢占 CPU,满足实时性要求。
  • 模块化设计:任务、队列、信号量等组件解耦,便于维护和扩展。

🍳 通俗比喻
想象你是一个厨师,要同时煎牛排和煮意大利面。

  • 裸机模式:你只能先煎一会儿牛排,再去看看面,来回切换——容易糊或煮过头。
  • FreeRTOS 模式:你安排两个“虚拟助手”分别负责牛排和面条,你只需在关键时刻介入(如翻面、捞面),效率高且不冲突。

二、FreeRTOS 核心架构

FreeRTOS 架构分为三层:

层级 功能
硬件抽象层(HAL) 屏蔽底层差异,提供统一接口(如时钟、中断)
内核层(Kernel) 核心组件:任务调度器、内存管理、同步机制等
应用层 用户创建的任务、业务逻辑

三、核心组件详解

1. 任务(Task)

  • 是 FreeRTOS 的基本执行单元。
  • 每个任务有独立的堆栈空间优先级
  • 状态包括:
    • Running(运行)
    • Ready(就绪)
    • Blocked(阻塞,等待事件/延时)
    • Suspended(挂起,手动暂停)
void vTaskFunction(void *pvParameters) {
    for (;;) {
        // 任务逻辑
        vTaskDelay(pdMS_TO_TICKS(100)); // 阻塞100ms
    }
}

// 创建任务
xTaskCreate(vTaskFunction, "MyTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

2. 调度器(Scheduler)

  • 默认使用抢占式调度:高优先级任务就绪时立即抢占 CPU。
  • 支持时间片轮转:相同优先级任务轮流执行(需配置 configUSE_TIME_SLICING)。

3. 队列(Queue)

  • 用于任务间通信ISR 与任务通信
  • FIFO 结构,支持中断安全操作。
QueueHandle_t xQueue = xQueueCreate(10, sizeof(int));

// 发送
xQueueSend(xQueue, &value, portMAX_DELAY);

// 接收
xQueueReceive(xQueue, &received, portMAX_DELAY);

4. 信号量与互斥量(Semaphore / Mutex)

  • 二进制信号量:用于任务同步(如 ISR 通知任务)。
  • 计数信号量:管理多个资源。
  • 互斥量:保护共享资源,支持优先级继承防止优先级反转。
SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
xSemaphoreTake(xMutex, portMAX_DELAY); // 获取锁
// 访问共享资源
xSemaphoreGive(xMutex); // 释放锁

5. 事件组(Event Group)

  • 一个 32 位变量,每位代表一个事件。
  • 任务可等待多个事件组合(AND/OR 条件)。
EventBits_t uxBits = xEventGroupWaitBits(
    xEventGroup,
    BIT_0 | BIT_1,   // 等待 bit0 和 bit1
    pdTRUE,          // 自动清除标志
    pdFALSE,         // OR 条件(任一触发即可)
    portMAX_DELAY
);

6. 任务通知(Task Notification)

  • 轻量级通信机制(FreeRTOS v8.2.0+)。
  • 每个任务内置一个 32 位通知值,无需额外 RAM。
  • 比信号量快 45%,但不能用于 ISR → ISR 或任务 → ISR
// 通知任务
xTaskNotifyGive(xTaskToNotify);

// 等待通知
ulNotificationValue = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

7. 软件定时器(Software Timer)

  • 周期性或一次性回调函数,由守护任务执行。
  • 不占用硬件定时器资源。
TimerHandle_t xTimer = xTimerCreate("MyTimer", pdMS_TO_TICKS(1000), pdTRUE, NULL, vTimerCallback);
xTimerStart(xTimer, 0);

8. 内存管理

FreeRTOS 提供 5 种堆管理方案(heap_1.c ~ heap_5.c):

  • heap_4.c:最常用,支持碎片合并。
  • heap_5.c:支持非连续内存区域。

四、典型应用场景

  1. IoT 设备

    • 同时处理传感器采集、Wi-Fi 通信、OTA 更新。
    • 结合 AWS IoT Core 实现远程管理。
  2. 工业控制

    • 实时响应紧急停机信号(高优先级任务)。
    • 使用互斥量保护电机控制寄存器。
  3. 智能终端

    • 多任务:UI 刷新、按键扫描、数据上传。

五、优势总结

特性 说明
开源免费 MIT 许可,商用无限制
轻量级 内核仅 6–12 KB ROM,RAM 占用极低
跨平台 支持 ARM Cortex-M、RISC-V、ESP32、AVR 等 40+ 架构
实时性强 抢占式调度,微秒级响应
生态完善 官方文档齐全,社区活跃,IDE(如 STM32CubeIDE)集成支持

六、学习建议

  1. 入门实验

    • 使用 STM32F103/F407 + STM32CubeMX 配置 FreeRTOS。
    • 实现双任务:LED 闪烁 + 串口打印。
  2. 进阶实践

    • 用队列传递 ADC 采样数据。
    • 通过互斥量保护 I2C 总线。
    • 使用任务通知替代二进制信号量优化性能。
  3. 官方资源

    • FreeRTOS 官网
    • 《Mastering the FreeRTOS Real Time Kernel》(官方书籍)

5.FreeRTOS架构

FreeRTOS 是一个开源、轻量级、可移植的实时操作系统(RTOS),专为嵌入式系统设计。其架构简洁高效,适用于资源受限的微控制器(MCU)。以下是 FreeRTOS 的核心架构组成和关键特性:


一、整体架构概览

FreeRTOS 的架构可分为以下几个主要部分:

  1. 内核(Kernel)

    • 调度器(Scheduler)
    • 任务管理(Task Management)
    • 时间管理(Time Management)
    • 队列(Queues)、信号量(Semaphores)、互斥量(Mutexes)等 IPC 机制
    • 软件定时器(Software Timers)
  2. 硬件抽象层(Port Layer)

    • 与具体 CPU 架构相关的代码(如 Cortex-M、RISC-V、AVR 等)
    • 包含上下文切换、中断处理、临界区保护等底层实现
    • 通常位于 portable/ 目录下,按编译器和 MCU 分类
  3. 配置层(Configuration)

    • 通过 FreeRTOSConfig.h 文件进行裁剪和配置
    • 可启用/禁用功能(如动态内存分配、软件定时器、协程等)
    • 设置堆栈大小、优先级数量、时钟节拍频率等参数
  4. 内存管理(Memory Management)

    • 提供多种堆管理方案(heap_1 到 heap_5)
    • 支持静态或动态内存分配(从 FreeRTOS v9 开始支持静态分配)

二、核心组件详解

1. 任务(Tasks)

  • 每个任务是一个独立的函数,具有自己的堆栈。
  • 支持优先级抢占式调度(默认)或协作式调度。
  • 任务状态:运行(Running)、就绪(Ready)、阻塞(Blocked)、挂起(Suspended)。

2. 调度器(Scheduler)

  • 基于优先级的抢占式调度。
  • 同优先级任务采用时间片轮转(Round-Robin)调度(若启用)。
  • 调度由系统节拍(Tick)中断驱动。

3. 系统节拍(Tick)

  • 由硬件定时器定期产生中断(通常 1ms ~ 10ms)。
  • 用于任务延时、时间片轮转、软件定时器计时等。
  • 节拍频率由 configTICK_RATE_HZ 定义。

4. 通信与同步机制

  • 队列(Queue):任务间传递数据,支持阻塞读写。
  • 信号量(Semaphore):用于任务同步或资源计数。
  • 互斥量(Mutex):带优先级继承机制,防止优先级反转。
  • 事件组(Event Groups):轻量级广播通知机制。
  • 流/消息缓冲区(Stream/Message Buffers):基于单生产者-单消费者模型的高效通信。

5. 软件定时器(Software Timers)

  • 在守护任务(Timer Service Task)上下文中执行回调函数。
  • 节省硬件定时器资源,适合非高精度定时需求。

三、可移植性设计

FreeRTOS 采用“内核 + 移植层”结构:

  • 内核代码(tasks.c, queue.c 等)是平台无关的 C 代码。
  • 移植层(port.c, portmacro.h)针对不同 CPU 架构实现:
    • 上下文切换(使用汇编)
    • 中断使能/禁止
    • 临界区保护(如 portENTER_CRITICAL()
    • 堆栈对齐与初始化

四、典型应用场景

  • 微控制器(如 STM32、ESP32、PIC、AVR)
  • 物联网设备(传感器节点、网关)
  • 工业控制、汽车电子、医疗设备等实时性要求较高的嵌入式系统

五、优势与特点

✅ 轻量(最小内核仅 6–10 KB)
✅ 源码开放(MIT 许可证)
✅ 高可移植性(支持 40+ 架构)
✅ 丰富的中间件生态(如 FreeRTOS+TCP、+CLI、+Trace 等)
✅ 被 Amazon 接管后整合进 AWS IoT 生态(现称 Amazon FreeRTOS)


6.如何在 STM32 上移植 μC/OS-III

在 STM32 上移植 μC/OS-III(Micro-Controller Operating System III)涉及以下几个关键步骤。μC/OS-III 是一个可抢占式实时操作系统(RTOS),由 Jean J. Labrosse 开发,现由 Silicon Labs 维护。它具有模块化、可配置、确定性强等特点。

以下是在 STM32(以常见的 Cortex-M 系列,如 STM32F4/F1 为例)上移植 μC/OS-III 的基本流程:


一、准备工作

1. 获取源码

  • 从官方渠道(如 Silicon Labs Micrium OS)获取 μC/OS-III 源代码。
  • 包含以下目录:
    • uCOS-III/Source:内核源码
    • uC-CPU:CPU 相关抽象层
    • uC-LIB:标准 C 库替代或补充
    • uCOS-III/Ports:已有处理器的移植层(可能包含 ARM Cortex-M)

注意:μC/OS-III 自 v3.03 起已开源并采用 Apache 2.0 许可(部分组件仍需授权,请确认许可状态)。

2. 开发环境

  • IDE:STM32CubeIDE / Keil MDK / IAR EWARM
  • 工具链:ARM GCC / ARMCC / ICCARM
  • HAL/LL 库:使用 STM32CubeMX 生成初始化代码

二、项目结构搭建

将以下文件加入你的工程:

Project/
├── uCOS-III/
│   ├── Source/        ← 内核源文件(os_core.c, os_task.c 等)
│   └── Ports/ARM-Cortex-Mx/GNU|IAR|RealView/ ← 移植层(汇编 + C)
├── uC-CPU/
│   ├── cpu_core.c
│   └── ARM-Cortex-Mx/cpu_a.asm, cpu_c.c
├── uC-LIB/
│   └── lib_*.c
├── app/
│   └── app.c (你的应用代码)
└── os_cfg.h, app_cfg.h (配置头文件)

三、关键移植文件说明(Cortex-M 通用)

1. os_cpu.h

  • 定义数据类型(如 OS_STK, OS_CPU_SR
  • 声明临界区宏:OS_ENTER_CRITICAL(), OS_EXIT_CRITICAL()
  • 声明任务切换函数:OS_TASK_SW(), OSIntCtxSw()

2. os_cpu_c.c

  • 实现钩子函数(如 OSTaskStkInit()
  • OSTaskStkInit():初始化任务堆栈,模拟异常返回堆栈帧(含 R0-R3, R12, LR, PC, xPSR)

3. os_cpu_a.asm

  • 实现 PendSV 异常处理(上下文切换核心)
  • 实现 OSStartHighRdy():启动第一个任务
  • 可能包含 OSCtxSw()OSIntCtxSw()(但在 Cortex-M 中通常通过触发 PendSV 实现)

Cortex-M 架构利用 PendSV 作为上下文切换的统一入口,避免在中断中直接切换。


四、系统时钟与 Tick 配置

μC/OS-III 依赖周期性时钟节拍(通常 1–1000 Hz)。

方法 1:使用 SysTick(推荐)

  • SysTick_Handler() 中调用 OSTimeTick()
  • main() 初始化后调用 OS_CPU_SysTickInit() 设置重装载值
void SysTick_Handler(void) {
    OSIntEnter();           // 进入中断
    OSTimeTick();           // 通知 OS 发生一次 tick
    OSIntExit();            // 退出中断(可能触发任务切换)
}

方法 2:使用其他定时器(如 TIM2)

  • 若 SysTick 被 HAL 占用(如 HAL_Delay),可改用通用定时器
  • 需自行配置中断并调用 OSTimeTick()

五、配置文件

1. os_cfg.h

  • 启用/禁用功能(信号量、消息队列、内存管理等)
  • 设置最大任务数 OS_CFG_MAX_TASKS
  • 设置时间片、任务栈大小等

2. app_cfg.h

  • 应用层配置(如任务优先级、堆栈大小)

六、主函数示例

#include "includes.h"  // 包含所有 μC/OS-III 头文件

static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];

int main(void)
{
    OS_ERR err;

    HAL_Init();
    SystemClock_Config();

    // 初始化 μC/OS-III
    OSInit(&err);
    if (err != OS_ERR_NONE) while(1);

    // 创建起始任务
    OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,
                 (CPU_CHAR   *)"App Task Start",
                 (OS_TASK_PTR )AppTaskStart,
                 (void       *)0,
                 (OS_PRIO     )APP_TASK_START_PRIO,
                 (CPU_STK    *)&AppTaskStartStk[0],
                 (CPU_STK_SIZE)APP_TASK_START_STK_SIZE / 10u,
                 (CPU_STK_SIZE)APP_TASK_START_STK_SIZE,
                 (OS_MSG_QTY  )0u,
                 (OS_TICK     )0u,
                 (void       *)0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&err);

    // 启动 OS
    OSStart(&err);
    while(1); // 不应到达此处
}

void AppTaskStart(void *p_arg)
{
    (void)p_arg;
    CPU_Init();          // 初始化 CPU 模块(来自 uC-CPU)
    Mem_Init();          // 初始化内存管理(来自 uC-LIB)
    OS_CPU_SysTickInit(SystemCoreClock / OS_CFG_TICK_RATE_HZ);

    // 创建其他任务...
    
    while (DEF_ON) {
        OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_HMSM_STRICT, &err); // 1秒延时
    }
}

七、注意事项

  1. 堆栈对齐:Cortex-M 要求 8 字节对齐,确保 OSTaskStkInit() 正确设置。
  2. 中断优先级:PendSV 和 SysTick 必须设为最低优先级(数值最大),确保不会打断其他 ISR。
    • 使用 NVIC_SetPriority(PendSV_IRQn, 0xFF);
  3. 临界区实现:通常通过关闭/开启中断(CPSID/CPSIE)实现。
  4. 调试支持:可启用 OS_CFG_STAT_TASK_ENOS_CFG_DBG_EN 辅助调试。
  5. 内存分配:建议静态分配任务控制块(TCB)和堆栈,避免动态分配问题。

八、参考资源

  • 《嵌入式实时操作系统 μC/OS-III》— Jean J. Labrosse
  • Micrium 官方 GitHub(部分开源版本):https://github.com/weston-embedded/uC-OS3
  • ST 官方 AN4027 应用笔记(关于 RTOS 在 STM32 上的使用)

7.如何在 STM32 上移植 FreeRTOS

在 STM32 上移植 FreeRTOS 是嵌入式开发中常见的任务。虽然现在大多数情况下可以直接使用官方或厂商提供的 FreeRTOS 包(如 STM32CubeMX 集成的 FreeRTOS),但理解其移植原理对调试和定制非常有帮助。以下是详细步骤:


一、准备工作

1. 硬件平台

  • 任意 STM32 微控制器(如 STM32F103、STM32F407、STM32H7 等)

2. 软件工具

  • STM32CubeMX(用于生成初始化代码,可选)
  • STM32 HAL 库 或 LL 库(推荐 HAL)
  • FreeRTOS 源码(从 FreeRTOS 官网 下载)
  • 开发环境(如 STM32CubeIDE、Keil MDK、IAR 等)

二、获取 FreeRTS 源码

FreeRTOS 核心源码位于 FreeRTOS/Source 目录,主要包括:

  • croutine.c
  • event_groups.c
  • list.c
  • queue.c
  • stream_buffer.c
  • tasks.c
  • timers.c
  • portable/关键目录,包含各平台的移植层
  • include/:头文件

注意:你 不需要 修改 Source 下的核心 C 文件,只需关注 portable/ 中与你的芯片和编译器相关的部分。


三、添加 FreeRTOS 到项目

1. 将 FreeRTOS 源码加入工程

  • Source 下的所有 .c 文件加入工程(除 portable/MemMang 外)
  • 选择一个内存管理方案(如 heap_4.c),加入 portable/MemMang/heap_4.c
  • 选择对应处理器和编译器的 port 层:
    • 对于 Cortex-M3/M4/M7,通常使用:
      portable/GCC/ARM_CM4F(GCC)
      portable/RVDS/ARM_CM4F(ARMCC/Keil)
      portable/IAR/ARM_CM4F(IAR)

示例:STM32F4 + STM32CubeIDE(基于 GCC) → 使用 portable/GCC/ARM_CM4F

2. 添加 include 路径

  • 工程需包含:
    • FreeRTOS/Source/include
    • FreeRTOS/Source/portable/GCC/ARM_CM4F(根据实际路径调整)

四、配置 FreeRTOS

创建或修改 FreeRTOSConfig.h 文件(通常放在工程根目录或 inc 文件夹中)。

该文件定义了系统时钟、任务优先级数量、堆大小等关键参数。可参考 FreeRTOS/Demo 中类似平台的配置。

关键配置项示例:

#define configCPU_CLOCK_HZ          (SystemCoreClock)
#define configTICK_RATE_HZ          ((TickType_t)1000)
#define configMAX_PRIORITIES        (5)
#define configMINIMAL_STACK_SIZE    ((unsigned short)128)
#define configTOTAL_HEAP_SIZE       ((size_t)(10 * 1024))
#define configUSE_PREEMPTION        1
#define configUSE_IDLE_HOOK         0
#define configUSE_TICK_HOOK         0
#define configUSE_TIMERS            1

⚠️ SystemCoreClock 必须正确初始化(通常由 HAL 初始化后设置)


五、系统时钟与 SysTick 配置

FreeRTOS 默认使用 SysTick 定时器 作为系统节拍(tick)源。

  • 如果你使用 HAL 库,注意 不要启用 HAL_IncTick() 的 SysTick 中断,否则会与 FreeRTOS 冲突。
  • 正确做法:禁用 HAL 的 tick 功能,让 FreeRTOS 接管 SysTick。

main() 初始化前添加:

// 禁用 HAL 的 SysTick
HAL_SuspendTick();

或者,在 stm32fxxx_hal_conf.h 中注释掉 #define USE_HAL_SYSTICK_REGISTER_CALLBACKS 并避免调用 HAL_InitTick()

FreeRTOS 的 port 层会自动配置 SysTick(通过 xPortSysTickHandler())。


六、中断优先级设置(Cortex-M 关键!)

Cortex-M 内核使用 NVIC 管理中断,FreeRTOS 要求:

  • 所有使用 FreeRTOS API 的 ISR(如发送队列、释放信号量)必须运行在低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的优先级(即数值更大)。
  • STM32 的优先级分组建议设为 4 bits 抢占优先级,0 bits 子优先级(即 NVIC_PriorityGroup_4

设置方法:

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

并在 FreeRTOSConfig.h 中定义:

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY     15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

#define configKERNEL_INTERRUPT_PRIORITY         \
    (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - __NVIC_PRIO_BITS))

#define configMAX_SYSCALL_INTERRUPT_PRIORITY    \
    (configLIBibrary_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - __NVIC_PRIO_BITS))

这样,优先级数值 0~4 的中断可以安全调用 FreeRTOS API;5~15 的中断不能调用。


七、启动 FreeRTOS

main() 函数中:

int main(void)
{
    HAL_Init();
    SystemClock_Config(); // 配置系统时钟

    // 可选:禁用 HAL 的 tick
    HAL_SuspendTick();

    // 创建任务
    xTaskCreate(vTask1, "Task1", 128, NULL, 1, NULL);
    xTaskCreate(vTask2, "Task2", 128, NULL, 2, NULL);

    // 启动调度器
    vTaskStartScheduler();

    // 不应到达这里
    for(;;);
}

注意:一旦调用 vTaskStartScheduler(),控制权交给 FreeRTOS,main() 不会继续执行。


八、常见问题排查

问题 原因 解决方法
程序卡死在 vTaskStartScheduler 堆空间不足 / 任务栈太小 增大 configTOTAL_HEAP_SIZE 或任务栈
任务不切换 SysTick 未正确配置 确保 FreeRTOS 接管 SysTick,关闭 HAL tick
中断导致系统崩溃 中断优先级过高 检查 configMAX_SYSCALL_INTERRUPT_PRIORITY 设置
编译报错找不到 vPortSVCHandler 中断向量表未重定向 stm32fxxx_it.c 中注释掉默认的 SVC/PendSV/SysTick 处理函数,或确保链接器使用 FreeRTOS 的版本

✅ 建议:使用 STM32CubeMX 自动生成 FreeRTOS 工程,再手动替换为最新 FreeRTOS 版本,可避免大部分配置错误。


九、推荐方式(快速上手)

  1. 打开 STM32CubeMX
  2. 配置 MCU 和时钟
  3. Middleware 中启用 FREERTOS
  4. 选择 CMSIS_V2 接口(更标准)
  5. 生成代码(MDK/STM32CubeIDE 等)
  6. 如需更新 FreeRTOS 版本,替换 Middlewares/Third_Party/FreeRTOS 目录

8.μC/OS 与 FreeRTOS 在任务切换开销上的差异

μC/OS(特别是 μC/OS-II 和 μC/OS-III)与 FreeRTOS 在任务切换开销方面存在一些差异,这些差异主要源于它们的内核设计哲学、调度机制、上下文保存方式以及对硬件平台的依赖程度。以下是两者在任务切换开销方面的关键对比:


1. 上下文切换机制

特性 μC/OS FreeRTOS
上下文保存位置 通常使用任务控制块(TCB)+ 系统栈保存上下文;部分架构下使用独立的任务栈保存完整寄存器状态 上下文通常直接保存在任务自己的栈中(包括寄存器、PC、SP 等)
切换方式 使用汇编语言实现精确的寄存器压栈/弹栈,代码高度优化 同样使用汇编实现,但为了可移植性,部分通用寄存器通过 C 函数辅助处理
中断嵌套处理 μC/OS-II 不支持中断嵌套(除非修改),μC/OS-III 支持 FreeRTOS 原生支持中断嵌套(通过 portSET_INTERRUPT_MASK_FROM_ISR() 等机制)

影响:μC/OS 的上下文切换通常更“确定”和“精简”,尤其在资源受限的 MCU 上表现更优;FreeRTOS 因强调可移植性,可能引入少量额外开销。


2. 任务切换触发方式

  • μC/OS

    • 任务切换通常由PendSV(ARM Cortex-M) 或等效的软件中断触发。
    • 调度器被显式调用(如 OSSched()),或在系统调用(如信号量、延时)后自动触发。
    • 切换逻辑集中、路径短。
  • FreeRTOS

    • 也使用 PendSV(Cortex-M)或类似机制。
    • 但调度可能在 ISR 中通过 portYIELD_FROM_ISR() 触发,需处理更多边界情况(如临界区、中断优先级)。
    • 为支持多种架构,调度入口逻辑稍复杂。

影响:μC/OS 的切换路径通常更直接,延迟更低且更可预测;FreeRTOS 因通用性牺牲少量效率。


3. 实测数据参考(Cortex-M 系列)

平台 μC/OS-III 任务切换时间 FreeRTOS 任务切换时间
Cortex-M3 @ 72MHz ~1.5 – 2.0 µs ~2.0 – 3.0 µs
Cortex-M4 @ 168MHz ~0.8 – 1.2 µs ~1.0 – 1.8 µs

注:具体数值取决于编译器优化等级、是否启用 FPU、是否使用 MPU 等。但总体趋势是 μC/OS 切换开销略小且更稳定


4. 设计哲学差异

  • μC/OS

    • 强调确定性、实时性、可认证性(如 DO-178C、IEC 61508)。
    • 代码结构清晰,无动态内存分配(默认),适合安全关键系统。
    • 切换开销被严格控制。
  • FreeRTOS

    • 强调可移植性、灵活性、社区生态
    • 支持动态任务创建/删除、丰富的中间件(TCP/IP、文件系统等)。
    • 为兼容多平台,部分优化让位于通用性。

5. 总结:任务切换开销对比

维度 μC/OS FreeRTOS
切换速度 ⭐ 更快(通常低 10%~30%) 稍慢但仍在微秒级
确定性 ⭐ 极高(硬实时) 高(软实时,依赖配置)
可预测性 ⭐ 优秀 良好(受配置影响大)
适用场景 航空航天、工业控制、医疗设备 消费电子、IoT、通用嵌入式

补充建议

  • 若项目对任务切换延迟极其敏感(如电机控制、高速采样),μC/OS-III 可能是更优选择。
  • 若需要快速开发、丰富组件、活跃社区FreeRTOS 是更实用的选择,其开销在大多数应用中完全可以接受。

如需具体平台(如 STM32、RISC-V)的实测对比,可进一步提供硬件信息。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐