1. 嵌入式系统架构概述

各位同学,咱们今天聊聊嵌入式系统架构。说实话,这词儿听起来挺唬人,但说白了,它就是一套组织代码的规矩。

我做了十几年嵌入式开发,见过太多项目因为一开始没想清楚架构,后期改得痛不欲生。嗯,咱们今天就把这事儿掰扯清楚。

1.1 什么是嵌入式系统架构

嵌入式系统架构,就是你把软件拆成哪些模块,模块之间怎么打招呼,数据怎么流转。

打个比方,你要盖一栋楼。架构就是这栋楼的承重墙、水电管道、房间布局。没有它,你也能把砖垒起来,但垒到三层可能就塌了。

我个人习惯把架构理解成三件事:

  • 模块划分:哪些功能放一起,哪些必须分开
  • 接口定义:模块之间怎么传数据、怎么触发动作
  • 层次关系:谁依赖谁,谁不能依赖谁

举个例子,一个简单的温控器:

// 不好的架构:所有代码揉在一起
void main() {
    while(1) {
        temp = read_sensor();       // 读传感器
        if(temp > 30) {             // 业务逻辑
            turn_on_fan();
        }
        delay(1000);
        send_to_uart(temp);         // 通信
    }
}

// 好的架构:分层清晰
void main() {
    sensor_init();
    comm_init();
    while(1) {
        temp = sensor_read();       // 驱动层
        cmd = temp_control(temp);   // 业务层
        comm_send(cmd);             // 通信层
        os_delay(1000);             // 系统层
    }
}

核心观点:架构不是写出来的,是设计出来的。好的架构让代码像乐高积木,坏的架构让代码像一团乱麻。

1.2 为什么需要架构设计

你可能觉得,小项目要什么架构?直接开干不就完了?

我曾经也这么想。直到有一次,我接手一个智能家居项目,代码量大概5万行。前任工程师把所有逻辑都写在main.c里,一个函数3000行。改一个bug要花三天,因为根本不知道改这里会不会炸了那里。

那次之后,我彻底明白了架构设计的价值:

维度 没有架构 有架构
可维护性 改一处,崩一片 改模块内部,不影响外部
可测试性 必须上硬件才能测 可以单独mock测试
可移植性 换芯片,重写全部 只换驱动层,业务层不动
团队协作 一个人改文件,其他人等着 各改各的模块,接口对齐就行
可复用性 每个项目从零开始 通用模块直接拿来用

你想想看,如果你的代码能像搭积木一样,换一个积木不影响其他积木,那该多爽?

避坑指南:我曾经见过一个团队,为了"快速出活",前三个月完全不考虑架构。结果到了第六个月,一个简单的功能迭代需要两周。嗯,后来他们花了两个月重构,比一开始就设计架构多花了三倍时间。

1.3 常见架构模式

嵌入式领域常用的架构模式,我挑三个最典型的讲讲。

1.3.1 分层架构

这是最经典的模式,也是我个人最常用的。说白了,就是把软件按职责分成几层,上层依赖下层,下层不依赖上层。

典型的嵌入式分层:

+-------------------+
|    应用层         |  <- 业务逻辑,比如温控策略
+-------------------+
|    中间件层       |  <- 协议栈、文件系统、RTOS
+-------------------+
|    硬件抽象层     |  <- HAL,屏蔽硬件差异
+-------------------+
|    驱动层         |  <- 直接操作寄存器
+-------------------+
|    硬件           |  <- MCU、外设
+-------------------+

好处很明显:换芯片只改驱动层和HAL层,应用层代码纹丝不动。我在一个项目中,把STM32换成GD32,只改了驱动层,应用层一行代码没动。

注意:分层架构最大的坑是"跨层调用"。有些人图方便,应用层直接调驱动层。短期看省事,长期看就是给自己埋雷。记住:层与层之间只能通过接口通信,不能越级。

1.3.2 事件驱动架构

这种模式适合响应式系统,比如按键、传感器中断、网络消息等。

核心思想:系统不主动轮询,而是等待事件发生,然后触发对应的处理函数。

// 事件驱动架构示例
typedef enum {
    EVT_BUTTON_PRESS,
    EVT_SENSOR_READY,
    EVT_TIMER_EXPIRED,
    EVT_UART_RX
} event_id_t;

typedef struct {
    event_id_t id;
    uint32_t   data;
} event_t;

void event_handler(event_t *evt) {
    switch(evt->id) {
        case EVT_BUTTON_PRESS:
            handle_button(evt->data);
            break;
        case EVT_SENSOR_READY:
            handle_sensor(evt->data);
            break;
        // ...
    }
}

这种架构的好处是低耦合、高响应。坏处是事件多了,调试起来有点头疼。我曾经在一个项目中,事件种类超过50种,事件追踪成了噩梦。后来加了个事件日志模块,才把问题搞定。

1.3.3 微服务架构

你可能觉得微服务是后端的事。其实嵌入式也能用,尤其是复杂的物联网网关、边缘计算设备。

每个功能模块独立运行,通过消息队列或RPC通信。比如:

  • 传感器服务:负责采集数据
  • 控制服务:负责执行控制逻辑
  • 通信服务:负责网络收发
  • 日志服务:负责记录运行状态

每个服务可以独立开发、独立测试、独立升级。一个服务挂了,不影响其他服务。

但要注意,微服务在嵌入式上有代价:需要RTOS支持,内存开销大,通信延迟增加。所以一般只在资源丰富的平台上用,比如Cortex-A系列。

架构模式 适用场景 资源需求 复杂度
分层架构 大多数嵌入式系统 低 低
事件驱动 响应式系统、UI、传感器网络 中 中
微服务 复杂网关、边缘计算、多核系统 高 高

我的建议:新手从分层架构入手,别一上来就搞微服务。先把分层玩明白了,再考虑其他模式。记住,架构是为业务服务的,不是为了炫技。

1.4 本章知识体系

下面这张图,把咱们这章的核心内容串起来了。你可以把它当成一个思维导图,方便以后复习。

嵌入式系统架构知识体系 嵌入式系统架构 什么是架构 模块划分 接口定义 层次关系 为什么需要架构 可维护性 可测试性 可移植性 团队协作 常见架构模式 分层架构 事件驱动架构 微服务架构 核心原则 高内聚、低耦合 接口清晰、层次分明、职责单一

这张图把咱们这章的核心内容串起来了。你可以把它当成一个思维导图,方便以后复习。