2. 嵌入式系统基础:嵌入式处理器选型(MCU vs MPU vs DSP)、实时操作系统(RTOS)选型、嵌入式软件分层架构
好,咱们进入正题。这一章聊的是嵌入式系统的基础,但基础不等于简单。处理器选型、RTOS选型、软件分层,这三件事要是没想清楚,后面ADAS系统做出来,轻则跑不稳,重则直接翻车。我这些年踩过的坑,十有八九都跟这几个选择有关。
2.1 嵌入式处理器选型:MCU vs MPU vs DSP
先说说处理器。ADAS系统里,处理器是大脑。选错了,后面全白搭。我见过不少团队,上来就选个最强的MPU,结果功耗压不住,散热成问题。也见过为了省钱选了个低端MCU,结果算法跑不动,帧率上不去。
这三种处理器,说白了就是三个方向:
- MCU(微控制器):集成度高,片内带Flash和RAM,适合做控制类任务。实时性好,功耗低。但算力有限,跑不了复杂的视觉算法。
- MPU(微处理器):算力强,通常需要外接DDR和存储。能跑Linux这种复杂OS。适合做感知、融合这类计算密集型任务。但功耗高,启动慢。
- DSP(数字信号处理器):专为信号处理设计。做滤波、FFT、音频处理特别快。但在通用控制上比较弱。
我个人的习惯是:能用MCU解决的问题,绝不上MPU。为什么?成本、功耗、可靠性,MCU都有优势。但ADAS系统里,很多时候MCU确实扛不住。
核心观点:ADAS系统往往是异构架构。MCU做安全控制和执行,MPU做感知和决策,DSP做信号预处理。各司其职,别指望一个芯片包打天下。
举个例子。我之前做过一个AEB(自动紧急制动)项目。感知部分用了MPU跑深度学习模型,但最终的刹车控制指令,必须由MCU发出。为什么?因为MPU万一死机了,MCU还能独立工作,保证安全。这叫功能安全隔离。
选型时,我建议你重点关注这几个参数:
| 参数 | MCU | MPU | DSP |
|---|---|---|---|
| 主频 | 几十MHz ~ 几百MHz | 几百MHz ~ 几GHz | 几百MHz ~ 1GHz+ |
| 片内存储 | KB ~ MB级 | 通常无,需外接 | KB ~ MB级 |
| 实时性 | 极好(硬实时) | 一般(软实时) | 好 |
| 典型应用 | 控制、执行、传感器采集 | 感知、融合、决策 | 雷达信号处理、音频处理 |
| 功耗 | 低(mW级) | 高(W级) | 中等 |
注意:别只看主频。MCU的实时性优势,不是靠主频堆出来的,而是靠中断响应时间和任务切换的确定性。我曾经在一个项目里,MPU主频1.5GHz,但中断响应抖动达到几十微秒,根本没法做精确的PWM控制。最后换了个200MHz的MCU,问题解决了。
2.2 实时操作系统(RTOS)选型
选完处理器,接下来就是操作系统。ADAS系统里,RTOS是标配。为什么?因为ADAS对时间的要求极其苛刻。你想想看,摄像头采集到障碍物,到刹车执行,中间只有几十毫秒。这期间,操作系统必须保证任务按时完成。
RTOS选型,我主要看三点:
- 实时性:中断延迟、任务切换时间,必须可预测。不能出现“这次10微秒,下次100微秒”的情况。
- 生态:驱动支持、中间件、工具链。没人想从头写一个CAN驱动吧?
- 认证:功能安全认证(比如ISO 26262 ASIL-D)。没有认证,车厂根本不认。
市面上常见的RTOS,我简单列一下:
| RTOS | 特点 | 适用场景 |
|---|---|---|
| FreeRTOS | 开源、轻量、生态好 | 中小型MCU项目,非安全关键 |
| RT-Thread | 国产、组件丰富、支持POSIX | 物联网、消费电子 |
| QNX | 微内核、高可靠、有ASIL-D认证 | ADAS、自动驾驶、医疗 |
| VxWorks | 老牌、稳定、认证齐全 | 航空航天、工业控制 |
| SafeRTOS | FreeRTOS的安全认证版 | 需要功能安全的MCU项目 |
我个人在ADAS项目里,用得最多的是QNX和SafeRTOS。QNX用在MPU上,做感知和决策;SafeRTOS用在MCU上,做控制和执行。为什么这么分?因为QNX的微内核架构,天然适合做功能安全隔离。而SafeRTOS有认证,可以直接用在ASIL-D级别的系统里。
一个小技巧:如果你用的是FreeRTOS,又想上功能安全,可以考虑SafeRTOS。它和FreeRTOS的API几乎一样,迁移成本很低。我有个项目就是这么干的,省了不少时间。
选RTOS时,还有一个容易忽略的点:任务优先级和堆栈分配。我曾经在一个项目里,因为堆栈分配太小,导致任务跑着跑着就栈溢出,系统随机崩溃。查了三天才找到原因。嗯,从那以后,我每个任务的堆栈都至少留30%的余量。
2.3 嵌入式软件分层架构
最后说说软件架构。ADAS系统的软件,复杂度很高。如果不分层,代码就是一锅粥。我见过最夸张的项目,一个.c文件上万行,改个功能要改十几个地方。这种代码,别说维护了,看着都头疼。
好的分层架构,应该是这样的:
- 硬件抽象层(HAL):屏蔽硬件差异。换芯片时,只需要改这一层。
- 驱动层:直接操作外设。比如CAN、SPI、I2C。
- 中间件层:提供通用服务。比如通信协议栈、诊断服务、存储管理。
- 应用层:业务逻辑。比如AEB算法、LKA控制。
我习惯用这种分层方式:
+-------------------+
| 应用层 | <-- AEB、LKA、ACC等算法
+-------------------+
| 中间件层 | <-- DDS、SOME/IP、UDS诊断
+-------------------+
| 驱动层 | <-- CAN、SPI、GPIO驱动
+-------------------+
| 硬件抽象层 | <-- MCU/MPU寄存器封装
+-------------------+
| 硬件 | <-- 芯片、外设
+-------------------+
每一层只和相邻层通信。应用层不能直接调驱动,必须通过中间件。这样做的好处是:
- 可移植性:换芯片时,只改HAL和驱动层。
- 可测试性:每一层都可以单独测试。
- 可维护性:改一个功能,不影响其他层。
避坑指南:我曾经在一个项目里,为了省事,让应用层直接操作GPIO寄存器。结果后来换芯片,所有应用代码都要重写。从那以后,我强制要求:任何硬件操作,必须经过HAL层。哪怕只是读一个引脚电平,也要封装成函数。
还有一个常见的坑:层间耦合。比如,应用层直接调用驱动层的函数,或者驱动层里包含了业务逻辑。这种代码,看着就乱。我建议你定一个规则:层间只能通过接口函数通信,不能直接访问数据结构。这样,即使以后要重构,影响范围也有限。
嗯,这一章的内容就这些。处理器选型、RTOS选型、软件分层,这三件事是ADAS系统可靠性的基石。选对了,后面事半功倍;选错了,后面全是坑。下一章,咱们聊聊功能安全标准ISO 26262,那才是ADAS系统的“法律”。