单片机为什么要跑 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 路用户 LEDDS0 红 PI0DS1 绿 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不同周期闪烁假设场景用于讲解多周期冲突LED10.6s 闪烁一次LED20.8s 闪烁一次LED31.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()做延时。// 任务10.6s 闪烁voidLedTask1(void){while(1){LED1_TOGGLE();LOS_TaskDelay(600);}}// 任务20.8s 闪烁voidLedTask2(void){while(1){LED2_TOGGLE();LOS_TaskDelay(800);}}// 任务31.0s 闪烁voidLedTask3(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-MLOS_TaskDelay(tick)调用之后当前任务直接进入【阻塞态】主动让出 CPU 使用权。重点任务阻塞期间不再占用 CPU调度器把 CPU 分配给其他就绪任务延时时间到之后任务回到就绪队列等待调度器再次分配 CPU。一句话区分忙等延时占着 CPU 原地睡觉RTOS 任务 Delay放下 CPU 去睡觉别人先用闹钟响了再回来跑。除了延时等待消息队列、信号量、互斥锁时任务同样会进入阻塞、释放 CPU。任务之间还能通过队列、信号量做任务间通信实现数据交互。裸机忙等 vs RTOS 阻塞 —— 速查表对比项裸机HAL_Delay()RTOSLOS_TaskDelay()CPU 占用全程占用、原地空转主动让出CPU 去跑别的任务多任务友好否会卡死后续逻辑是阻塞期间其他任务照常跑代码写法状态机 / 时间戳手动管理每个任务独立while(1) Delay适用场景极简单单任务多业务并发、需通信/抢占RTOS 调度器怎么工作物理 CPU 只有一个RTOS 内核给我们虚拟出多个「虚拟 CPU」每个虚拟 CPU 跑一个任务。SysTick 系统节拍定时器产生中断触发 PendSV 异常完成任务上下文切换保存寄存器、栈再切到另一个任务。调度规则高优先级优先运行同优先级时间片轮转任务阻塞主动让出 CPU。高优先级任务就绪会抢占低优先级任务任务调用 Delay / 等待资源时主动让出 CPUCPU 去跑其他就绪任务没有任何就绪任务时就跑 Idle 空闲任务。四、回到我们的 STM32MP157 M4 LiteOS-M 移植课程我们实操的工程零物理裁剪移植 LiteOS-MCortex-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会发生什么欢迎评论区留言。

相关新闻

【PYTHON】使用代码执行js文件中的函数和独立页面执行自定义协议

【PYTHON】使用代码执行js文件中的函数和独立页面执行自定义协议

代码执行JS from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser p.chromium.launch(headlessFalse,executable_pathr"D:\download\chrome-win64\chrome-win64\chrome.exe",)page browser.new_page()# 监听浏览器console输出&…

2026/8/29 21:14:34 阅读更多 →
蓝桥杯国赛“扩散”题解:从暴力模拟到曼哈顿距离的算法思维跃迁

蓝桥杯国赛“扩散”题解:从暴力模拟到曼哈顿距离的算法思维跃迁

1. 项目概述:从一道国赛真题看算法思维的构建“扩散”这道题,是2020年第十一届蓝桥杯国赛C B组的一道经典题目。对于很多从省赛一路拼杀到国赛的选手来说,这道题像是一个分水岭,它考察的远不止是基础的语法或简单的算法模板&#…

2026/8/29 21:14:34 阅读更多 →
STM32G4 HAL库嵌入式开发实战:从外设驱动到系统设计

STM32G4 HAL库嵌入式开发实战:从外设驱动到系统设计

1. 从零到一:理解第九届蓝桥杯嵌入式国赛的挑战与机遇 第九届蓝桥杯嵌入式国赛,对于每一位参赛者而言,都是一场技术与心态的双重考验。它不仅仅是一次编程比赛,更像是一个浓缩的、高强度的嵌入式产品开发实战演练。当赛题下发&…

2026/8/29 21:14:34 阅读更多 →

最新新闻

2021小米秋招前端笔试深度解析:考点拆解与备考策略

2021小米秋招前端笔试深度解析:考点拆解与备考策略

2021年小米秋招前端方向第一场笔试,这个话题放到现在看,依然有很强的参考价值。大厂前端笔试的考察逻辑这些年虽然一直在变,但核心筛选标准没有变过:基础扎不扎实、思路清不清晰、代码能不能落地。我身边有不少人问过我当时这场笔…

2026/8/29 22:41:51 阅读更多 →
小米2020前端笔试题解析:从JS基础到浏览器原理的考点全拆解

小米2020前端笔试题解析:从JS基础到浏览器原理的考点全拆解

一份工作摆了四年,回头再看小米2020校招前端工程师笔试题二,依然觉得它把“基本功检测”这件事做得相当到位。很多同学在校招季疯狂刷LeetCode,却在这套题的选择题和简答题上翻了车,原因不在于难度,而在于考察的东西太…

2026/8/29 22:41:51 阅读更多 →
STM32 ADC与高级定时器实战:电压测量与互补PWM控制详解

STM32 ADC与高级定时器实战:电压测量与互补PWM控制详解

1. 项目背景与核心任务拆解最近在整理蓝桥杯嵌入式比赛的备赛资料,翻到了第六届决赛那道关于“电压测量与互补PWM信号输出”的真题。这道题可以说是把STM32的ADC和高级定时器TIM1/8的核心功能玩到了极致,综合性非常强。很多同学第一次看到题目要求&#…

2026/8/29 22:41:51 阅读更多 →
畅游引擎开发岗校招笔试复盘:从C++内存到渲染管线的硬核考点

畅游引擎开发岗校招笔试复盘:从C++内存到渲染管线的硬核考点

2020年秋招那阵子,我手里攥着一份投递列表,搜狐畅游的引擎开发工程师排在挺靠前的位置。游戏引擎岗在当年算得上竞争比较狠的方向,一方面是因为做游戏引擎的机会本身就少,另一方面是很多人对这个岗位的理解停留在“会写C就能上”&…

2026/8/29 22:41:51 阅读更多 →
搜狐畅游引擎开发校招笔试复盘:C++与图形学考点解析

搜狐畅游引擎开发校招笔试复盘:C++与图形学考点解析

一、聊聊那次笔试的整体印象前阵子整理电脑里的旧文件,翻到2020年参加搜狐畅游校招笔试的记录,顺手复盘了一遍。当时投的是引擎开发工程师方向,说实在的,这份卷子考察的面比预想中广,难度也足够筛掉一批人。如果你正准…

2026/8/29 22:41:51 阅读更多 →
前端校招笔试高频考点全解析:从异步原理到工程化实战

前端校招笔试高频考点全解析:从异步原理到工程化实战

“前端笔试”这四个字,对于2020年那会儿的应届生来说,基本等同于“八股文面试”的同义词。但其实回过头看,像乐信这种体量、业务又偏金融科技的公司,前端笔试题反而不是纯粹考背书的,它更看重你能不能把手上的JS和CSS用…

2026/8/29 22:40:50 阅读更多 →

日新闻

etc目录下的profile.d文件目录设置环境变量和全局脚本shell

etc目录下的profile.d文件目录设置环境变量和全局脚本shell

一、设置环境变量etc目录下的profile.d文件目录 /etc/profile.d1、编写 vi test.sh文件内容# jdk变量 export ZHK_HOME/root export PATH$PATH:$ZHK_HOME/test # 可以取出来ZHK_HOME变量给ZZZ_HOME赋值 export ZZZ_HOME${ZHK_HOME}/test2、刷新 执行source /etc/profile 命令使…

2026/8/29 0:00:24 阅读更多 →
【JavaScript】内存管理-垃圾回收机制-内存泄露

【JavaScript】内存管理-垃圾回收机制-内存泄露

内存管理 C 语言这样的底层语言一般都有底层的内存管理接口,比如 malloc()和free()。 而 JavaScript 是在创建变量(对象,字符串等)时自动进行了分配内存,并且在不使用它们时“自动”释放。释放的过程称为垃圾回收。 整…

2026/8/29 0:00:24 阅读更多 →
Labgrid-MCP:为嵌入式硬件实验室接入AI Agent操控能力

Labgrid-MCP:为嵌入式硬件实验室接入AI Agent操控能力

Labgrid-MCP 的目标是把 MCP(Model Context Protocol)能力延伸到真实嵌入式硬件实验室:AI Agent 通过一个标准化的 MCP Server,就能查看目标板状态、控制上电断电、复位开发板、读取串口日志,甚至执行镜像刷写。对于经…

2026/8/29 0:00:24 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/29 18:08:35 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/28 23:05:07 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/28 19:47:53 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/29 4:34:53 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/28 17:43:04 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/29 2:05:18 阅读更多 →