嵌入式系统调试接口JTAG与SWD协议时序实战 - 第1节
1.1 JTAG 的起源:从电路板测试到芯片调试
JTAG 这玩意儿,最早其实不是给嵌入式调试用的。
上世纪 80 年代,电路板越做越密,芯片引脚越来越多。你想啊,一块板子上几百个焊点,传统针床测试仪根本扎不进去。那时候修板子全靠老师傅拿示波器戳,效率低得吓人。
为了解决这个问题,几家大厂——飞利浦、西门子、英特尔这帮人——凑在一起搞了个联合测试行动组(Joint Test Action Group)。他们的目标很直接:能不能在芯片内部做个“测试电路”,让测试信号从芯片的引脚串行进出?
1985 年,这个想法落地了。1990 年,IEEE 正式把它收编为 IEEE 1149.1 标准,也就是我们今天说的 JTAG。
我早年做通信设备维修时,还见过那种老式针床治具。后来换了 JTAG 边界扫描,一个人就能测整板,效率翻了好几倍。说实话,那时候我就觉得这协议有前途。
1.2 IEEE 1149.1 标准:JTAG 的“宪法”
IEEE 1149.1 标准定义了 JTAG 的硬件接口、信号协议和状态机。说白了,它是一套通用规则,让不同厂家的芯片能通过同一套接口进行测试和调试。
1.2.1 标准信号线
JTAG 接口最少只需要 4 根信号线(加上 1 根可选复位线):
| 信号名 | 全称 | 方向 | 作用 |
|---|---|---|---|
| TCK | Test Clock | 输入 | 测试时钟,所有操作同步于此 |
| TMS | Test Mode Select | 输入 | 模式选择,控制 TAP 状态机跳转 |
| TDI | Test Data In | 输入 | 串行数据输入 |
| TDO | Test Data Out | 输出 | 串行数据输出 |
| TRST | Test Reset | 输入 | (可选)复位 TAP 控制器 |
嗯,这里要注意:TCK 是独立于系统时钟的。也就是说,芯片内核没跑起来,JTAG 照样能工作。这个特性在调试“死机”的板子时特别有用。
1.2.2 TAP 状态机:JTAG 的大脑
JTAG 的核心是一个有限状态机,叫 TAP(Test Access Port)控制器。它一共有 16 个状态,通过 TMS 信号在 TCK 上升沿驱动跳转。
我刚开始学 JTAG 时,最头疼的就是记这 16 个状态。后来发现,其实你只需要记住两条主路径:
- 数据寄存器路径(DR 路径):用于读写芯片内部的边界扫描寄存器、IDCODE 寄存器等。
- 指令寄存器路径(IR 路径):用于加载调试指令,告诉芯片“接下来要干什么”。
两条路径共享前 5 个状态,到 Select-DR-Scan 或 Select-IR-Scan 时才分叉。这个设计很巧妙——减少了状态数,也降低了硬件开销。
1.3 JTAG 在嵌入式调试中的角色
JTAG 从测试接口“跨界”到调试接口,其实是个很自然的过程。你想想看:既然 JTAG 能访问芯片内部的寄存器,那能不能用它来读写 CPU 的寄存器、内存、外设?
答案是肯定的。芯片厂商在 CPU 内核旁边加了一个 调试模块(Debug Module),通过 JTAG 接口暴露出来。调试器(比如 J-Link、ST-Link)就是通过这个模块,实现以下功能:
- 暂停/恢复 CPU:让内核停在某个指令处,方便查看现场。
- 读写寄存器:查看 R0-R15、PC、SP 等内核寄存器。
- 读写内存:查看变量值、堆栈内容。
- 设置断点:硬件断点(利用调试模块)或软件断点(插入 BKPT 指令)。
- 单步执行:一条指令一条指令地跑,观察程序流向。
我记得有一次,客户反馈设备偶发死机。用 JTAG 挂上去,设了个硬件断点在异常向量表入口。等了半天,终于抓到一次——是某个外设中断服务函数把栈指针写飞了。没有 JTAG,这种问题基本没法查。
1.4 JTAG 知识体系总览
下面这张图,是我梳理的 JTAG 知识体系。你可以把它当成本章的“地图”,后面几章会逐一展开。
这张图把 JTAG 拆成了三层:硬件接口、TAP 状态机、调试应用。后面几章,我们会从底层往上,一层一层把它吃透。