单片机为什么要跑 RTOS?从裸机痛点看懂 LiteOS-M(基于 STM32MP157 M4)
单片机为什么要跑 RTOS?从裸机痛点看懂 LiteOS-M(基于 STM32MP157 M4)
标签:
#LiteOS-M#OpenHarmony#STM32MP157#RTOS#嵌入式
阅读对象:刚接触 RTOS 的单片机开发者;准备把 LiteOS-M 移植到 STM32MP157 M4 内核的同学
前言
很多初学单片机的同学会有个疑问:单片机裸机 while(1) 大循环已经能跑程序了,我们为什么还要费劲去移植、学习 RTOS 实时操作系统?
很多教程一上来就讲 API、讲移植步骤,却很少讲清楚「RTOS 到底解决了裸机的什么痛点」。
本文从最简单的 LED 闪烁案例入手,对比裸机与 RTOS 的差异,再结合我们正在做的 STM32MP157 Cortex-M4 内核移植 OpenHarmony LiteOS-M,把 RTOS 的核心价值讲明白。
一、裸机开发的美好与痛点:多 LED 闪烁案例
我们手上的这块正点原子 STM32MP157 开发板,M4 内核引出了 2 路用户 LED(DS0 红 = PI0,DS1 绿 = PF3)。
场景1:只控制 1 颗 LED 闪烁
只让 1 颗 LED 周期性闪烁,裸机写起来非常简单:翻转 GPIO 输出,加上延时即可。
while (1)
{
GPIO_ResetBits(GPIOI, GPIO_PIN_0); // LED 亮(低电平点亮)
HAL_Delay(600);
GPIO_SetBits(GPIOI, GPIO_PIN_0); // LED 灭
HAL_Delay(600);
}
逻辑清晰、实现简单,这种单一周期的需求,裸机完全胜任。
💡 说明:正点原子 STM32MP157 开发板在 M4 侧实际引出的用户 LED 就是 2 路——
DS0(红,PI0)和DS1(绿,PF3)。下面「3 个 LED 不同周期」只是为把「多周期冲突」这个痛点讲清楚而设的假设场景;我们最终的 LiteOS-M 移植演示,就是用这 2 路物理 LED 做成 2 个独立任务(详见第四节)。
场景2:需求升级 —— 3 个 LED,不同周期闪烁(假设场景,用于讲解多周期冲突)
- LED1:0.6s 闪烁一次
- LED2:0.8s 闪烁一次
- LED3:1.0s 闪烁一次
问题来了:STM32MP157 的 M4 是单核 CPU,同一时刻只能执行一段代码,指令是顺序执行的。
如果直接写三段带阻塞延时的 while(1),代码会变成这样(示意,用来暴露问题):
// 示意:三段逻辑无法真正并行,CPU 只会执行第一段
while (1)
{
led1_toggle();
HAL_Delay(600);
}
while (1) // 以下两段永远进不去
{
led2_toggle();
HAL_Delay(800);
}
while (1)
{
led3_toggle();
HAL_Delay(1000);
}

现实很残酷:CPU 进入第一个 while 死循环之后就卡死在这里,后面两段代码永远得不到执行。
裸机怎么解决多周期闪烁?
裸机当然也能实现,有两条路:
- 手写状态机 + SysTick 毫秒计时:不用阻塞延时,把每一路 LED 的时间戳存下来,在主循环里判断时间是否到达再翻转 IO。
- 用定时器中断拆分业务逻辑。

但是!业务越多,状态变量、判断分支就会爆炸,代码逻辑越来越像「意大利面条」,可读性很差;新增、修改功能很容易引入 bug,维护成本急剧上升。
当产品同时要处理:LED 闪烁、按键扫描、串口收发、传感器采集、电机控制……裸机状态机写起来会非常折磨人。
二、RTOS 如何解决单核单片机「同时做多件事」?
RTOS 的核心思想:把业务拆成独立任务(Task),内核调度器自动在多个任务之间切换 CPU 使用权,宏观上模拟出「多线程并发」的效果。
注意:M4 依旧是单核,不是真正的并行,而是快速分时抢占 —— 宏观看起来多个任务在同时跑。
我们课程用的是 OpenHarmony 的轻量内核 LiteOS-M,思想和大家熟悉的 FreeRTOS 高度一致。
RTOS 版本:三个 LED 各自一个独立任务
每一路 LED 闪烁写成一个独立任务函数,每个任务内部直接写自己的死循环,用 LOS_TaskDelay() 做延时。
// 任务1:0.6s 闪烁
void LedTask1(void)
{
while (1)
{
LED1_TOGGLE();
LOS_TaskDelay(600);
}
}
// 任务2:0.8s 闪烁
void LedTask2(void)
{
while (1)
{
LED2_TOGGLE();
LOS_TaskDelay(800);
}
}
// 任务3:1.0s 闪烁
void LedTask3(void)
{
while (1)
{
LED3_TOGGLE();
LOS_TaskDelay(1000);
}
}
然后在初始化时调用 LOS_TaskCreate() 创建 3 个任务,指定:任务入口函数、栈大小、任务优先级、任务名字。
LOS_TaskCreate(&taskId1, &taskParam1); // 创建任务,交给 LiteOS-M 内核调度
LOS_TaskCreate(&taskId2, &taskParam2);
LOS_TaskCreate(&taskId3, &taskParam3);
LOS_Start(); // 启动调度器
✅ 优势非常直观:
- 业务解耦:每个 LED 的闪烁逻辑完全独立,一个任务的代码几乎不用关心其他任务;新增业务直接新增一个任务即可。
- 代码可读性高:逻辑就是我们人脑思考的业务流程,不需要手写复杂的状态机。
- 内核自动处理任务切换:开发者专注业务本身,不用手动维护时间戳、状态标志。
三、关键知识点:LOS_TaskDelay() 和 HAL_Delay() 根本不是一回事
很多新手会混淆这两个延时,而这正是理解 RTOS 的关键:
HAL_Delay()裸机忙等延时:CPU 空循环计数,全程占用 CPU,原地空转,别的代码无法运行。- LiteOS-M
LOS_TaskDelay(tick):调用之后,当前任务直接进入【阻塞态】,主动让出 CPU 使用权。
重点:任务阻塞期间不再占用 CPU,调度器把 CPU 分配给其他就绪任务;延时时间到之后,任务回到就绪队列,等待调度器再次分配 CPU。
一句话区分:
- 忙等延时:占着 CPU 原地睡觉;
- RTOS 任务 Delay:放下 CPU 去睡觉,别人先用,闹钟响了再回来跑。
除了延时,等待消息队列、信号量、互斥锁时,任务同样会进入阻塞、释放 CPU。任务之间还能通过队列、信号量做任务间通信,实现数据交互。
裸机忙等 vs RTOS 阻塞 —— 速查表
| 对比项 | 裸机 HAL_Delay() |
RTOS LOS_TaskDelay() |
|---|---|---|
| CPU 占用 | 全程占用、原地空转 | 主动让出,CPU 去跑别的任务 |
| 多任务友好 | 否(会卡死后续逻辑) | 是(阻塞期间其他任务照常跑) |
| 代码写法 | 状态机 / 时间戳手动管理 | 每个任务独立 while(1) + Delay |
| 适用场景 | 极简单单任务 | 多业务并发、需通信/抢占 |
RTOS 调度器怎么工作?
- 物理 CPU 只有一个;RTOS 内核给我们虚拟出多个「虚拟 CPU」,每个虚拟 CPU 跑一个任务。
- SysTick 系统节拍定时器产生中断,触发 PendSV 异常,完成任务上下文切换(保存寄存器、栈,再切到另一个任务)。
- 调度规则:高优先级优先运行;同优先级时间片轮转;任务阻塞主动让出 CPU。
- 高优先级任务就绪,会抢占低优先级任务;
- 任务调用 Delay / 等待资源时主动让出 CPU,CPU 去跑其他就绪任务;没有任何就绪任务时,就跑 Idle 空闲任务。
四、回到我们的 STM32MP157 M4 + LiteOS-M 移植课程
我们实操的工程:零物理裁剪移植 LiteOS-M,Cortex-M4 内核完全运行在 256KB 片内 SRAM。
- 内核源码一行不改,适配全部收敛到
targets目录;- Makefile 控制逻辑裁剪,不删除内核源文件;
- 最终实现两个 LED 任务交替闪烁,和本文案例原理一模一样。
裸机开发适合简单小项目;当你的项目有多个并发业务、需要任务间通信、对实时抢占有要求时,RTOS 的价值就体现出来了。
RTOS 不是魔法,底层依旧是汇编、中断、寄存器。但它把任务切换、内存管理、IPC 通信这些复杂底层机制封装好了,开发者只需要调用对应 API 写业务逻辑。
当你搞懂:任务状态、阻塞、调度、任务间通信这些基础概念之后,再去写 RTOS 业务代码,会发现本质就是调用 API,思路理清了,代码并不难写。
五、小结
- 单片机是单核 CPU,裸机多业务会陷入「状态机复杂度爆炸」;
- RTOS 把业务拆成独立 Task 任务,内核调度器自动做任务切换,宏观实现「多任务并发」;
- RTOS 的 Delay 不是忙等延时:任务进入阻塞、释放 CPU,这是 RTOS 高效的关键;
- 我们 STM32MP157 M4 移植 LiteOS-M 的课程,就是手把手把这套 RTOS 内核跑起来,从底层看懂 RTOS 如何工作。
思考小问题(留给读者)
如果一个 RTOS 任务里写了
while (1);,没有任何 Delay 或阻塞 API,会发生什么?欢迎评论区留言。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐





所有评论(0)