第2章 嵌入式系统基础:嵌入式定义、特点、分类,RTOS与裸机对比
各位同学,咱们今天聊聊嵌入式系统的基础。说实话,这个领域看着门槛不高,但坑是真不少。我做了十年轨道交通牵引系统,从最早的8位单片机一路干到现在的多核ARM,有些体会想跟你们分享。
2.1 到底什么是嵌入式系统?
嵌入式系统,说白了就是「专门干一件事的计算机系统」。你想想看,你手机里的CPU能跑安卓、能打游戏、能刷视频,这叫通用计算机。但咱们牵引系统里的控制器,它这辈子就只干一件事——控制电机转得快一点、慢一点、正着转、反着转。
我个人习惯把嵌入式系统拆成三块看:
- 硬件层:CPU、内存、外设接口。嗯,这是骨架。
- 软件层:裸机程序或者RTOS,加上应用代码。这是血肉。
- 中间层:驱动、协议栈、Bootloader。这是连接骨架和血肉的筋。
我在项目中遇到过一件事:有同事把嵌入式系统和单片机划等号。其实不对。单片机只是嵌入式系统的核心处理器之一,现在很多高端系统用的都是ARM Cortex-A系列,甚至跑Linux。别把眼界局限了。
2.2 嵌入式系统的特点
做嵌入式开发和写桌面程序,完全是两码事。我总结了几条核心特点,你们记一下:
| 特点 | 说明 | 我的经验 |
|---|---|---|
| 资源受限 | RAM可能只有几KB到几MB,Flash也有限 | 我曾经为了省4个字节的RAM,把代码重构了三遍 |
| 实时性要求 | 必须在规定时间内响应外部事件 | 牵引系统里,中断响应超过10微秒就可能出事故 |
| 可靠性高 | 不能死机,不能跑飞,7×24小时运行 | 我记得有一次现场调试,系统跑了72小时突然复位,查了整整一周才发现是看门狗喂晚了 |
| 功耗敏感 | 电池供电的设备尤其明显 | 虽然咱们牵引系统不愁电,但散热问题一样头疼 |
| 专用性强 | 硬件和软件高度耦合,换一个MCU可能代码全废 | 所以选型的时候一定要慎重,别拍脑袋 |
核心要点:嵌入式系统的本质是「在有限的资源下,可靠地完成特定任务」。记住这句话,后面所有设计思路都围绕它展开。
2.3 嵌入式系统的分类
按实时性要求,嵌入式系统可以分成三类。这个分类很重要,因为它直接决定了你选裸机还是RTOS。
- 硬实时系统:错过截止时间 = 系统失效。比如咱们的牵引系统,PWM波必须精确到微秒级,晚一点都不行。
- 软实时系统:偶尔错过截止时间还能接受,但性能会下降。比如车载娱乐系统,视频卡顿一下还能忍。
- 非实时系统:没有严格的时间要求。比如一些数据采集器,慢个几毫秒无所谓。
你想想看,如果拿一个非实时系统去控制列车牵引,会是什么后果?嗯,那画面太美我不敢看。
2.4 RTOS与裸机对比
这是新手最容易纠结的问题。我直接给你们一个判断标准:任务多了,用RTOS;任务少了,用裸机。
裸机程序,说白了就是一个大循环:
void main(void)
{
while(1)
{
read_sensor(); // 读传感器
calculate_speed(); // 算速度
update_pwm(); // 更新PWM
delay_ms(10); // 延时
}
}
这种写法简单直观,但有个致命问题——如果calculate_speed()执行时间长了,update_pwm()就会延迟。在牵引系统里,PWM更新延迟意味着电机电流失控,后果很严重。
RTOS就不一样了。它把任务拆开,每个任务有自己的优先级:
void task_pwm(void *arg)
{
while(1)
{
update_pwm(); // 高优先级,每1ms执行一次
vTaskDelay(pdMS_TO_TICKS(1));
}
}
void task_control(void *arg)
{
while(1)
{
read_sensor();
calculate_speed();
vTaskDelay(pdMS_TO_TICKS(10));
}
}
你看,PWM更新任务优先级高,就算控制任务算得再慢,PWM也能准时输出。这就是RTOS的价值。
我的建议:刚开始学的时候,先用裸机把基础打牢。等你发现裸机代码里全是状态机、标志位、定时器中断嵌套的时候,就该上RTOS了。
2.5 避坑指南
我曾经犯过一个低级错误:在裸机程序里用了while(1)死等某个外设就绪。结果那个外设因为硬件故障一直没就绪,整个系统卡死了。看门狗都没救回来,因为CPU还在跑,只是卡在循环里。
所以记住:裸机程序里,绝对不要用死等。要么加超时机制,要么用状态机轮询。
还有一个坑:RTOS的任务栈大小。我见过有人把栈设成128字节,结果任务一运行就栈溢出,系统随机崩溃。排查了三天才发现。嗯,从那以后我每个任务至少给512字节,关键任务给1KB以上。
2.6 怎么选?
我给你们一个简单的决策树:
- 任务数 ≤ 3,且没有严格实时要求 → 裸机
- 任务数 4-10,有中等实时要求 → RTOS(FreeRTOS或uC/OS-II)
- 任务数 > 10,或硬实时要求 → RTOS(RT-Thread或VxWorks)
- 需要文件系统、网络协议栈 → 上Linux,别折腾RTOS了
当然,这只是经验之谈。具体选什么,还得看项目需求、团队能力、成本预算。我见过有人用裸机写出了堪比RTOS的调度器,也见过有人用RTOS写出了比裸机还烂的代码。工具只是工具,关键看用的人。
警告:不要为了用RTOS而用RTOS。引入RTOS意味着要处理任务同步、资源竞争、优先级反转等问题。如果裸机能搞定,就别给自己找麻烦。
好了,这一章就讲到这里。下一章咱们聊聊嵌入式开发环境搭建,包括编译器、调试器、仿真器的选择。这些东西看着简单,但选错了能让你多加班一个月。到时候我给你们讲讲我踩过的坑。