2. JTAG 与 SWD 接口详解

调试接口,说白了就是调试器和芯片之间的“通信管道”。ARMv8 内核最常用的两种接口,就是 JTAG 和 SWD。JTAG 是个老牌标准,SWD 是 ARM 后来推出的精简版。很多工程师刚接触时容易混淆,我当年也踩过坑——拿着 JTAG 的线序去接 SWD,结果死活连不上。

这一节,咱们就把这两个接口彻底讲透。

2.1 JTAG 信号定义与链式扫描

JTAG(Joint Test Action Group)最初是为了电路板测试而生的,后来被 ARM 拿来做调试接口。它至少需要 4 根信号线,加上可选的第 5 根,一共 5 根。

信号名 方向 功能描述
TCK 调试器 → 芯片 时钟信号,所有操作同步于此
TMS 调试器 → 芯片 模式选择,控制 TAP 状态机跳转
TDI 调试器 → 芯片 数据输入,串行送入指令或数据
TDO 芯片 → 调试器 数据输出,串行读出响应
nTRST 调试器 → 芯片 (可选)TAP 复位,低电平有效

JTAG 的核心机制是 TAP 状态机。调试器通过 TMS 信号在 TCK 的上升沿驱动状态跳转,完成“指令扫描”或“数据扫描”。

链式扫描(Daisy Chain):当多个 JTAG 设备串联时,TDO 接下一个的 TDI,形成一条扫描链。调试器通过一条链就能访问所有设备。我在调试多核 ARMv8 芯片时,经常用链式扫描同时挂起所有核心,效率很高。

链式扫描的典型流程:

  1. 调试器通过 TMS 驱动状态机进入 Shift-IR 状态,送入指令码。
  2. 切换到 Shift-DR 状态,送入或读出数据。
  3. 每个设备在链中占据固定长度的寄存器位,调试器需要知道链上所有设备的 ID 和寄存器长度。
  4. 扫描完成后,回到 Run-Test/Idle 状态,等待下一次操作。

注意:链式扫描时,如果某个设备的 TAP 状态机跑飞了,整条链都会卡死。我曾经遇到过一颗芯片的 nTRST 引脚虚焊,导致链上所有设备都无法正常扫描。排查了整整一天,最后用示波器量 nTRST 电平才发现问题。

2.2 SWD 双线协议

SWD(Serial Wire Debug)是 ARM 在 Cortex-M 时代推出的精简接口,后来 ARMv8 也全面支持。它只用了两根线:SWDIO(双向数据线)和 SWCLK(时钟线)。

你想想看,JTAG 至少 4 根线,SWD 只要 2 根。对于引脚紧张的芯片,SWD 简直是救星。我做过一个 IoT 项目,芯片封装只有 8 个引脚,硬是挤出了 SWD 接口,省掉了 JTAG 的 TDI 和 TDO。

SWD 协议的核心是 数据包(Packet) 结构:

字段 长度 说明
起始位 1 bit 固定为 0
AP/DP 选择 1 bit 0 = DP(调试端口),1 = AP(访问端口)
读写标志 1 bit 0 = 写,1 = 读
寄存器地址 2 bits 选择 DP/AP 内部的寄存器
奇偶校验 1 bit 对前 5 bits 做偶校验
停止位 1 bit 固定为 0
Park 位 1 bit 固定为 1

SWD 的读写操作是半双工的。调试器发送请求包后,芯片在下一个 SWCLK 周期返回响应包。响应包包含 ACK(应答)、数据(读操作时)和奇偶校验位。

个人经验:SWD 的时钟频率可以很高,但实际调试时我习惯先降到 1 MHz 以下,确认连接稳定后再逐步提高。有些廉价的调试线在高速下容易丢包,表现为“连接断开”或“校验错误”。

2.3 JTAG 与 SWD 的切换机制

ARMv8 芯片通常同时支持 JTAG 和 SWD。但芯片上电后默认处于哪种模式?答案是 JTAG 模式。为什么?因为 JTAG 是 IEEE 标准,兼容性更好。

切换机制其实很简单:调试器通过 JTAG 的 TMS 和 TCK 发送一串特定的序列,芯片检测到后就会切换到 SWD 模式。这个序列叫做 SWJ-DP 切换序列(SWJ-DP Switch Sequence)。

具体流程如下:

  1. 调试器在 TCK 上输出 50 个以上的时钟周期,同时 TMS 保持高电平。这会让 JTAG TAP 状态机进入 Test-Logic-Reset 状态。
  2. 然后发送 16 位的切换序列:0xE79E(二进制:1110 0111 1001 1110)。
  3. 芯片检测到序列后,内部从 JTAG 逻辑切换到 SWD 逻辑。
  4. 之后,SWCLK 和 SWDIO 开始按 SWD 协议通信。

关键点:切换序列必须在 TCK 的上升沿采样,且 TMS 的时序必须严格对齐。我见过不少工程师用逻辑分析仪抓波形,发现 TMS 的建立时间不够,导致切换失败。嗯,这里要注意:切换完成后,JTAG 的 TDI 和 TDO 引脚可以复用为 GPIO 或其他功能。

下面这张图展示了 JTAG 和 SWD 的切换流程:

JTAG ↔ SWD 切换流程 芯片上电 默认 JTAG 模式 需要切换 SWD? 否 继续 JTAG 调试 是 发送切换序列 0xE79E 进入 SWD 模式 切换条件 1. TMS 保持高电平 ≥ 50 TCK 2. 发送 16 位序列 0xE79E 3. 序列在 TCK 上升沿采样

切换完成后,调试器可以通过 SWD 协议访问 DP(Debug Port)和 AP(Access Port)。DP 负责控制调试逻辑,AP 负责访问系统总线(如 AXI、AHB)。

避坑指南:我曾经在一个项目里,芯片的 SWD 接口死活切不过去。查了半天,发现是 PCB 上 SWCLK 和 SWDIO 的走线太长,导致信号反射。后来在调试器端加了 22Ω 的串联电阻,问题就解决了。所以,如果你遇到切换失败,先检查信号质量。

2.4 JTAG 与 SWD 的对比

特性 JTAG SWD
信号线数量 4~5 根 2 根
通信方式 全双工 半双工
链式扫描 原生支持 不支持
最大时钟频率 通常 ≤ 50 MHz 通常 ≤ 50 MHz
引脚复用 TDI/TDO 可复用 SWDIO 可复用
调试速度 较快(全双工) 略慢(半双工)
适用场景 多核、多设备链式调试 引脚受限、单核调试

我个人习惯:如果芯片引脚够用,优先用 JTAG,因为全双工在批量读写内存时更快。但如果引脚紧张,或者只需要调试一个核心,SWD 完全够用,而且布线简单。

小技巧:很多调试器(如 J-Link、ST-Link)都支持自动检测接口类型。你插上 SWD 线,它会先尝试 JTAG 连接,失败后自动发送切换序列。但我不建议完全依赖自动检测——手动指定接口类型更可靠,尤其是在调试刚上电的芯片时。