系统架构设计:嵌入式系统硬件架构与软件架构设计原则

做嵌入式开发这么多年,我越来越觉得,系统架构设计才是整个项目的灵魂。说白了,硬件选型和软件框架定下来,后面80%的工作量基本就锁死了。今天咱们就聊聊这块硬骨头——MCU/MPU怎么选,RTOS和Linux怎么权衡。

一、硬件架构:MCU与MPU的选型博弈

先说说硬件选型。很多新手上来就问:「哪个芯片性能最强?」其实这是个伪命题。我见过太多项目,选了个性能过剩的芯片,结果成本压不住,功耗也下不来。

核心原则:选型不是选最强的,而是选最合适的。

1. MCU vs MPU:你该怎么选?

这个问题我经常被问到。我的回答很简单:看你的任务复杂度。

对比维度 MCU(微控制器) MPU(微处理器)
典型代表 STM32、ESP32、GD32 i.MX6、RK3399、AM335x
运行频率 几十MHz ~ 几百MHz 几百MHz ~ 几GHz
内存 片上Flash+SRAM,通常<2MB 外挂DDR,通常512MB以上
操作系统 裸机或RTOS Linux或大型RTOS
实时性 微秒级中断响应 毫秒级(受Linux调度影响)
功耗 低(mW级) 高(W级)
成本 几元到几十元 几十元到几百元

嗯,这里要注意。如果你只是做个传感器采集、电机控制,MCU完全够用。但如果你要跑复杂的图形界面、做网络协议栈、处理视频流,那还是老老实实上MPU吧。

我的经验:我曾经在一个智能家居项目中,硬要用STM32跑TCP/IP协议栈+Web服务器。结果内存爆了,调试了两个月才勉强跑起来。后来换成i.MX6,一周就搞定了。选型时别太自信,留点余量。

2. MCU选型的几个关键指标

选MCU时,我一般按这个顺序看参数:

  • 主频:别只看数字。Cortex-M4和Cortex-M0跑同样的频率,性能差好几倍。我习惯看DMIPS/MHz这个指标。
  • Flash和RAM:保守估计,代码量翻倍算。你想想看,后期加功能、加日志、加OTA,空间很快就吃紧了。
  • 外设接口:SPI、I2C、UART、CAN、USB...数清楚你需要几个。我踩过坑——选了个只有2个UART的芯片,结果要接GPS、蓝牙、调试串口,硬生生少了一个。
  • 功耗模式:电池供电的项目,一定要看stop/standby模式的电流。有些芯片号称低功耗,实际待机电流几十微安,根本没法用。

避坑指南:我曾经选了一款国产MCU,手册上写着「兼容STM32F103」。结果代码移植过去,ADC采样值死活不对。查了三天,发现是内部参考电压的精度差了一个数量级。所以,国产芯片一定要亲自验证关键参数。

3. MPU选型的核心考量

MPU选型,说白了就是选生态。硬件性能固然重要,但更关键的是:

  • BSP支持:官方有没有提供完整的Linux BSP?驱动好不好移植?我见过某些厂商的BSP,内核版本还停留在3.10,连主线都合不进去。
  • 内存接口:DDR3还是DDR4?LPDDR还是普通DDR?布线难度差很多。LPDDR的PCB走线要求高,两层板基本搞不定。
  • 散热方案:MPU功耗高,散热片、风扇、甚至热管都得考虑。别等样机做出来才发现芯片烫得能煎鸡蛋。

二、软件架构:RTOS与Linux的设计原则

硬件选完了,接下来就是软件架构。这个选择直接影响你的开发效率和系统稳定性。

1. RTOS:什么时候用?

RTOS适合那些对实时性要求极高的场景。比如电机控制、无人机飞控、工业PLC。我个人习惯,只要中断响应时间要求小于100微秒,就优先考虑RTOS。

常用的RTOS有:FreeRTOS、RT-Thread、uC/OS-III。我推荐FreeRTOS,生态好,资料多,而且免费。

RTOS设计原则:

  • 任务优先级不要超过5级。太多优先级反而增加调度开销。
  • 中断服务程序要短。我习惯在ISR里只做标记,具体处理放到任务里。
  • 信号量和消息队列要合理使用。别滥用,否则容易死锁。
// 一个典型的FreeRTOS任务结构
void vTaskExample(void *pvParameters)
{
    // 初始化硬件
    hardware_init();
    
    for(;;)
    {
        // 等待事件
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        
        // 处理数据
        process_data();
        
        // 发送结果
        xQueueSend(xQueue, &data, 0);
    }
}

2. Linux:什么时候用?

Linux适合功能复杂、需要丰富生态的场景。比如智能网关、HMI人机界面、边缘计算节点。你想想看,Linux上有现成的网络协议栈、文件系统、图形框架,开发效率高得多。

但Linux的实时性是个硬伤。标准Linux内核的调度延迟在几毫秒到几十毫秒之间。如果你需要硬实时,可以考虑RT-Linux或Xenomai。

我的建议:如果项目需要联网、存储、显示,直接上Linux。别想着用MCU+RTOS去硬扛这些功能。我见过有人用STM32跑FATFS+LWIP+emWin,结果代码量超过200K,调试起来生不如死。

3. 混合架构:MCU+MPU双核方案

有些场景,单一架构搞不定。比如一个工业控制器,既要实时控制电机,又要跑HMI界面和网络通信。这时候,MCU+MPU的双核方案就派上用场了。

我做过一个项目:MCU(STM32F4)负责电机控制和传感器采集,MPU(i.MX6)负责人机交互和云端通信。两者通过SPI或共享内存通信。这样既保证了实时性,又兼顾了功能复杂度。

注意:双核方案的通信协议一定要设计好。我曾经因为SPI通信的握手协议没处理好,导致MCU和MPU互相等待,系统直接卡死。后来加了超时机制和状态机才解决。

三、架构设计的几个通用原则

不管选什么硬件、用什么系统,有些原则是通用的:

  1. 模块化:每个功能模块独立,接口清晰。别搞成「意大利面条式代码」。
  2. 可测试性:设计时就考虑怎么测试。我习惯给每个模块留一个测试接口。
  3. 可扩展性:预留20%的硬件资源。别把Flash和RAM用满,后期加功能会哭的。
  4. 可靠性:看门狗、异常处理、日志系统,一个都不能少。

嗯,今天就聊到这儿。架构设计这东西,没有标准答案。关键是多做项目,多踩坑,慢慢就有感觉了。下一章咱们聊聊详细设计阶段,怎么把架构落地成具体的代码。