3. 烧录协议基础:UART、SPI、I2C、SWD/JTAG
烧录这件事,说白了就是上位机跟芯片里的 Bootloader 或调试接口「对话」。对话得用双方都懂的语言,这就是协议。我见过不少工程师,日志报错看不懂,其实根子是不清楚底层协议在干什么。
这一章,咱们把四种最常见的烧录协议过一遍。不扯太深的理论,重点讲清楚:它长什么样、怎么传数据、烧录时容易在哪翻车。
核心观点:烧录日志里 80% 的「通信超时」「校验失败」「ACK 错误」,追到物理层都能找到答案。协议基础越扎实,看日志越像看剧本。
3.1 UART 协议基础
UART 是异步串行通信。什么叫异步?就是没有单独的时钟线。收发双方得事先约好一个「节奏」——波特率。我遇到过有人把 115200 配成 9600,日志全是乱码,还以为是芯片坏了。
UART 烧录一般只用三根线:TX、RX、GND。有些板子还要加上 DTR/RTS 做自动复位和 Boot 模式切换。
| 参数 | 常见值 | 烧录时的坑 |
|---|---|---|
| 波特率 | 9600 / 115200 / 921600 | 两边不一致 → 乱码或超时 |
| 数据位 | 8 | 极少用 7 位,别乱改 |
| 停止位 | 1 | 2 停止位偶尔用,但烧录器默认 1 |
| 校验位 | None | 开了校验但芯片不支持 → 无响应 |
| 流控 | None | 硬件流控没接对应引脚 → 卡死 |
我的习惯:调试阶段先用 115200 8N1,这是最通用的配置。如果日志出现连续相同的 0x00 或 0xFF,先量 TX 引脚电平——大概率是线没接对或者芯片没上电。
UART 烧录的典型流程:上位机发特定同步头(比如 0x7F),芯片 Bootloader 收到后回 ACK,然后开始传固件数据。日志里看到 Sync OK 说明握手过了,后面再报错就是数据帧的问题。
3.2 SPI 协议基础
SPI 是同步串行,有专门的时钟线(SCLK)。主设备产生时钟,从设备跟着节奏走。SPI 烧录通常用四根线:SCLK、MOSI、MISO、CS(片选)。
SPI 比 UART 快得多,适合大固件。但它的坑也不少。
- 极性和相位(CPOL / CPHA):模式 0 到模式 3,烧录器和芯片必须匹配。我见过最离谱的一次,两边都是模式 0,但 CS 拉低时机差了半个时钟周期,数据全错位。
- 片选控制:CS 必须在整个数据包传输期间保持低电平。有些上位机驱动在每字节之间拉高了 CS,芯片直接复位接收状态机。
- 时钟频率:芯片 Bootloader 的 SPI 时钟通常有限制,不是主设备能跑多快就设多快。超过 20 MHz 经常丢数据。
我曾经踩过的坑:用 SPI 烧录一块新板子,日志报 CRC Error。查了两天,最后用示波器一看,MISO 线上的数据在时钟下降沿跳变,但芯片是在上升沿采样的。CPHA 差了一拍,所有字节都右移了一位。
3.3 I2C 协议基础
I2C 也是同步串行,但只用两根线:SCL(时钟)和 SDA(数据)。它是半双工的,主设备通过设备地址选择从机。
I2C 烧录在 EEPROM、传感器类芯片里很常见。它的特点是有 ACK/NACK 机制——每个字节后面接收方都要回一个应答位。
日志里常见的 I2C 错误:
NACK on address:芯片没响应。地址错了,或者芯片处于复位状态。NACK on data:芯片收到了数据但没法处理。可能是写保护、忙状态、或者不支持该命令。Clock stretching timeout:芯片拉低 SCL 表示「我还没准备好」,但主设备等太久了。
| I2C 速度模式 | 时钟频率 | 适用场景 |
|---|---|---|
| 标准模式 | 100 kHz | 兼容性最好,烧录首选 |
| 快速模式 | 400 kHz | 大部分芯片支持,注意上拉电阻 |
| 高速模式 | 3.4 MHz | 烧录器很少支持,别轻易用 |
我建议:I2C 烧录遇到问题,先量 SCL 和 SDA 的上拉电压。很多开发板忘了焊上拉电阻,或者上拉电阻太大导致信号上升沿太缓。100 kHz 下 4.7 kΩ 通常没问题。
3.4 SWD / JTAG 协议基础
这两种是调试接口,烧录只是它们的功能之一。JTAG 用 5 根线(TMS、TCK、TDI、TDO、nTRST),SWD 用 2 根线(SWDIO、SWCLK)。
SWD 是 ARM 公司搞的简化版,现在主流 Cortex-M 芯片都支持。JTAG 更通用,FPGA、DSP 也用它。
SWD 烧录的核心是 DP(Debug Port)和 AP(Access Port)。DP 负责协议层,AP 负责访问芯片内部的总线和存储器。日志里看到 DP IDR 读出来是 0x2BA01477 之类的值,说明 SWD 通信已经通了。
JTAG 的边界扫描(Boundary Scan)在烧录时用得不多,但调试断点、单步执行全靠它。我遇到过 JTAG 链上有多个器件,IDCODE 读出来全是 0xFFFFFFFF——原来是 TDI 到 TDO 的链路断了。
注意:SWD 和 JTAG 的引脚通常和 GPIO 复用。如果芯片固件把 SWDIO 配成了普通输出,调试器就连不上了。解决办法是拉高 nRESET 的同时发送 SWD 连接序列,或者用硬件复位让芯片回到默认状态。
3.5 协议对比与选型建议
| 协议 | 线数 | 速度 | 典型烧录场景 | 日志常见报错 |
|---|---|---|---|---|
| UART | 3 | 慢(~1 Mbps) | MCU Bootloader | 超时、乱码、Sync 失败 |
| SPI | 4 | 快(~50 Mbps) | Flash、大固件 | CRC 错误、片选异常 |
| I2C | 2 | 中(~400 kbps) | EEPROM、小固件 | NACK、时钟拉伸超时 |
| SWD | 2 | 快(~10 Mbps) | ARM MCU 调试烧录 | IDR 读不到、连接失败 |
| JTAG | 5 | 快(~50 Mbps) | FPGA、DSP、多器件链 | IDCODE 异常、TDO 无输出 |
选协议其实看芯片和工具链。ST 的芯片用 UART 串口烧录最方便,但速度慢;用 SWD 快,但需要调试器。我个人习惯:开发阶段用 SWD,量产用 UART 或 SPI,因为 SWD 引脚少、速度快,量产时 UART 的线更少、成本更低。
总结一下:协议基础是烧录日志分析的「底层语言」。你看到 Timeout,脑子里要立刻反应——是波特率不对?时钟极性反了?还是地址没对上?这些判断都来自对协议细节的理解。下一层,我们就要拿着这些知识去读真正的烧录日志了。