3. ESS核心概念与标准体系

做嵌入式测试这么多年,我最大的体会是:不懂硬件架构,测试就是瞎蒙。你连被测对象长什么样、信号从哪进从哪出都不知道,怎么设计测试用例?这一章,咱们就把嵌入式系统的硬件骨架拆开看看。

3.1 典型嵌入式硬件架构

嵌入式处理器就那几大家族:MCU、DSP、FPGA。别看型号满天飞,核心架构就这三类。我习惯把它们比作三种工具:

  • MCU(微控制器)——瑞士军刀。啥都能干,但单项能力不突出。跑控制逻辑、读传感器、发指令,这是它的主场。
  • DSP(数字信号处理器)——手术刀。专为数学运算优化,一个时钟周期能干乘加。音频、雷达、电机控制,这些实时计算场景离不开它。
  • FPGA(现场可编程门阵列)——乐高积木。逻辑自己搭,并行度极高。接口协议转换、高速数据采集、硬件加速,这些活交给它最合适。

现在很多高端板子都是异构架构:MCU+DSP、ARM+FPGA,甚至三合一。我在一个工业视觉项目里就遇到过Zynq(ARM+FPGA),调试起来那叫一个酸爽——你得同时懂软件和硬件。

核心观点:测试策略必须跟着架构走。MCU侧重时序和协议,DSP侧重算法精度,FPGA侧重逻辑覆盖和时序收敛。

3.2 调试接口:JTAG与SWD

调试接口是测试工程师的生命线。没有它,你连芯片里跑的是啥都不知道。

3.4.1 JTAG(联合测试行动组)

JTAG最早是用来测PCB焊接的,后来被拿来调试芯片。它定义了5根线:

信号 全称 方向 说明
TCK Test Clock 输入 时钟,通常1-50MHz
TMS Test Mode Select 输入 状态机切换
TDI Test Data In 输入 数据输入
TDO Test Data Out 输出 数据输出
TRST Test Reset 输入 可选,复位TAP控制器

JTAG的核心是边界扫描(Boundary Scan)。每个IO引脚都串了一个移位寄存器,你可以通过TDI/TDO把数据灌进去,再读出来。说白了,就是用软件控制硬件引脚。

我的经验:JTAG链上挂多个芯片时,一定要检查TDI→TDO的菊花链是否连通。我曾经花了两天查一个焊接虚焊,最后发现是JTAG链中间断了一根线。

3.4.2 SWD(串行线调试)

SWD是ARM搞的简化版调试接口,只用了两根线:

  • SWDIO——双向数据线
  • SWCLK——时钟线

相比JTAG,SWD省了3根线,对PCB布局友好很多。现在Cortex-M系列基本都支持SWD。我个人的习惯是:板子上同时留JTAG和SWD焊盘,万一JTAG信号质量不好,还能切SWD救急。

注意:SWD虽然线少,但抗干扰能力不如JTAG。长线缆(超过20cm)或者高噪声环境,建议用JTAG。我在一个电机驱动项目里,SWD在电机启动时直接断连,换成JTAG就稳了。

3.3 测试总线:UART、I2C、SPI

调试接口搞定芯片内部,测试总线搞定芯片之间的通信。这三兄弟是嵌入式系统里最常见的。

3.3.1 UART(通用异步收发器)

UART是最简单的串行通信协议。两根线:TX(发送)、RX(接收)。异步,不需要时钟线。

关键参数:

  • 波特率:9600、115200、921600……越高越快,但误码率也越高
  • 数据位:通常8位
  • 停止位:1位或2位
  • 校验位:无、奇校验、偶校验

我在测试中常用UART做日志输出。把调试信息通过UART打到PC上,用串口助手看。这招虽然土,但极其有效。有一次系统死机,我就是在串口日志里发现是堆栈溢出。

测试要点:UART测试一定要做误码率测试。发一串已知数据,收回来对比。误码率超过10⁻⁶就要查原因——通常是波特率偏差或者信号质量差。

3.3.2 I2C(集成电路总线)

I2C是飞利浦搞的两线制总线:SCL(时钟)、SDA(数据)。支持多主多从,每个设备有唯一地址。

I2C的特点:

  • 半双工——同一时刻只能一个方向传数据
  • 开漏输出——需要上拉电阻
  • 速率:标准模式100kHz,快速模式400kHz,高速模式3.4MHz
  • 地址:7位或10位

I2C测试最头疼的是总线锁死。从机没释放SDA线,主机一直等。我遇到过好几次,最后发现是从机复位时序不对。解决办法:在测试用例里加总线恢复步骤——发9个时钟脉冲让从机释放总线。

// I2C总线恢复示例
void i2c_bus_recover(void) {
    // 拉高SDA
    SDA_HIGH();
    for (int i = 0; i < 9; i++) {
        SCL_LOW();
        delay_us(5);
        SCL_HIGH();
        delay_us(5);
    }
    // 发STOP条件
    SDA_LOW();
    delay_us(5);
    SCL_HIGH();
    delay_us(5);
    SDA_HIGH();
    delay_us(5);
}

3.3.3 SPI(串行外设接口)

SPI是Motorola搞的四线制总线:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。

SPI的特点:

  • 全双工——同时收发
  • 推挽输出——不需要上拉电阻
  • 速率:几十MHz很常见
  • 模式:4种(CPOL和CPHA组合)

SPI测试的坑主要在模式匹配。主从设备的CPOL/CPHA必须一致,否则数据全错。我建议在测试用例里加一个回环测试:把MOSI和MISO短接,发一串数据看能不能收回来。

避坑指南:我曾经在一个项目里,SPI通信时好时坏。查了两天,最后发现是CS信号毛刺——片选在时钟之前跳变,导致从机误触发。解决办法:CS信号加一个RC滤波,或者软件里加延时。

3.4 三种总线的对比

特性 UART I2C SPI
线数 2(TX/RX) 2(SCL/SDA) 4(SCLK/MOSI/MISO/CS)
通信方式 异步 同步 同步
传输方向 全双工 半双工 全双工
速率 低(典型115200bps) 中(典型400kHz) 高(典型10-50MHz)
从机数量 点对点 多从机(地址寻址) 多从机(片选)
硬件复杂度 低 中 高
典型用途 调试日志、GPS、蓝牙 传感器、EEPROM、RTC ADC、DAC、LCD、SD卡

3.5 测试接口架构总览

下面这张图把本章的核心内容串起来了。你可以看到:调试接口(JTAG/SWD)直通芯片内部,测试总线(UART/I2C/SPI)连接外设。测试工程师要做的就是从这两个入口获取信息。

嵌入式系统测试接口架构 核心处理器 MCU / DSP / FPGA 调试接口 JTAG / SWD 测试总线 UART / I2C / SPI 调试接口功能 • 边界扫描测试 • 断点/单步调试 • 内存/寄存器读写 测试总线功能 • 外设通信测试 • 协议一致性验证 • 数据吞吐量测试 测试策略:双通道并行验证 调试接口(内部状态) + 测试总线(外部通信)

3.6 测试接口选型建议

最后,我根据自己的项目经验,给几个选型建议:

  1. 调试接口优先选SWD——除非你需要边界扫描或者多芯片链,否则SWD够用且省引脚。
  2. 日志输出用UART——简单可靠,PC端工具多(Putty、SecureCRT、串口助手)。
  3. 传感器采集用I2C——线少,支持多设备,适合板内通信。
  4. 高速数据传输用SPI——ADC、DAC、LCD这些需要吞吐量的场景,SPI是首选。
  5. 测试接口要留测试点——板子上一定要留出测试焊盘或者排针,不然量产测试时你哭都来不及。

血的教训:我有个项目,为了省空间没留测试接口。结果量产时发现一批板子通信异常,只能飞线测。从那以后,我每个项目都强制要求:至少留一个UART和一个JTAG/SWD测试点。这是底线。