JTAG 是嵌入式系统中常用的调试接口,常见的 ARM、CPLD 和 FPGA 等,都带有 JTAG 接口,可以用于更新固件、测试 IC 和 IO 功能。为了更清楚的探究 JTAG,这篇博文就从 JTAG 的结构和工作时序介绍一下 JTAG 接口。
一、JTAG 的接口
JTAG(Joint Test Action Group,联合测试工作组)是一种国际标准测试协议(IEEE 1149.1 兼容),JTAG 的设计初衷是用于芯片内部测试,现已广泛应用调试及下载功能。现在多数的高级器件都支持 JTAG 协议,如 DSP、FPGA 器件等。标准的 JTAG 接口是 4 线:TMS、TCK、TDI、TDO,分别为模式选择、时钟、数据输入和数据输出线。
JTAG 接口一般包含 4 根线:TCK(Test Clock)、TMS(Test Mode State)、TDI(Test Data Input)、TDO(Test Data Output)。
引脚 | 作用 |
TCK(Test Clock) | 时钟,上升沿捕获输入,下降沿变更输出 |
TMS(Test Mode State) | 状态选择,仿真器在 TCK 下降沿输出,被测芯片在 TCK 上升沿捕获 |
TDI(Test Data Input) | 串行数据输入,仿真器在 TCK 下降沿输出,被测芯片在 TCK 上升沿捕获 |
TDO(Test Data Output) | 串行数据输出,被测芯片在 TCK 下降沿输出,仿真器在 TCK 上升沿捕获 |
JTAG 的物理接口:
图 2 是 FPGA 开发板或产品上常见的 2 种接口,14pin 的采用交叉地线,所以信号的稳定性要比 10 线的好一点。不过一般连线都不会超过 10cm,所以可以不用考虑了。
- TCK 应接下拉电阻,按照 IEEE 1149.1 的要求,被测芯片在 TCK 保持低电平的情况下将保持原有的状态,所以 TCK 应该拉低,确保在没有接仿真器时 TCK 是低电平状态。
- TMS 应接上拉电阻,根据 TAP 状态机,任意状态下,只要 TMS 保持高电平 5 个时钟,那么就会进入复位状态,所以 TMS 拉高是安全的。
- TDI 和 TDO 应接上拉电阻,提高驱动能力。
二、JTAG 接口的结构
JTAG 的结构如图 3 所示,包含了 1 个 TAP 状态机,3 个主要的寄存器:IR(Instruction Register)、DR(Data Register)、BSC(Boundary Scan Chain)。
- 分布在内核电路和 pin 之间的 BSC,BSC 是一种多模式的寄存器,有几种控制模式。
- 指令寄存器和数据寄存器。
- TAP 控制器。
这 3 个部分是 JTAG 硬件实现的必须电路。其中 BSC 尤为重要,它是一种寄存器,在内核正常工作时无效,在调试模式时有效,它可以被赋值,也可以给内核和 pin 赋值,它是实现边界扫描的基础。支持 JTAG 的芯片都有这个模块。
图 4 是 IO 扫描链的实现:
TAP 状态机
JTAG 接口由一个通用的时序:TAP 状态机。
总共 16 个状态,由 TCK 和 TMS 来切换 TAP 的状态。其中 TEST-LOGIC-RESET 是所有 IC 复位后的状态,在每个 TCK 的上升沿会根据 TMS 的电平确定下一个状态,而且这个状态机的设计包含了复位的功能:拉低 TMS,给 5 个 TCK,就可以把 TAP 状态切换到 TEST-LOGIC-RESET。所以JTAG 的可选 RESET 引脚一般可以省掉。
需要注意的是 SHIFT-IR、SHIFT-DR 这两个状态,因为JTAG 是在 TCK 上升沿的时候采样 TMS 然后更新 TAP 的状态,所以从 CAPTURE 切换到 SHIFT 的时候其实在 TCK 上升沿的时候 TAP 是在 CAPTURE 状态的,所以不会执行 SHIFT 的动作!但是 CAPTURE 状态下给一个 TCK 时钟会捕获当前的值(IR 或 DR)然后更新到 TDO,所以在 CAPTURE 进入 SHIFT 状态后,经过一个特定的延时后 TDO 已经是有数据了,这个是 D 触发器+组合逻辑的特性。
三、JTAG 接口的时序
JTAG 接口的时序主要分为两个部分:指令寄存器扫描和数据寄存器扫描。根据 IEEE 1149.1 的文档中可以找到指令寄存器扫描的时序图和数据寄存器扫描的时序图,分别如图 6 和图 7 所示。
3.1 指令寄存器扫描
从图 6 可以清晰地看出,仿真器在 TCK 下降沿改变 TMS、TDI 电平,被测芯片在 TCK 上升沿捕获输入并更新内部状态。被测芯片在 TCK 下降沿改变 TDO 电平,仿真器在 TCK 上升沿捕获 TDO 数据。
需要特别注意的是:最后一位数据是在进入 Exit1-IR 状态的那个上升沿捕获的,数据寄存器也同样存在这个特点。
3.2 数据寄存器扫描
3.3 读 IDCODE 时序分析实例
例如,IDCODE=0x0001_0000_0000_0000_0000_0010_0100_0011
当 TAP 处于 Shift-DR 状态时,在第一个时钟上升沿,将 TDI 移入到数据寄存器,同时在下降沿串行移出数据寄存器中最低位(LSB)。
在第 32 个时钟下降沿,数据寄存器移出最高位(HSB),同时在第 32 个上升沿拉高 TMS,TAP 从 Shift-DR 切换到 Update-DR 状态,将数据寄存器的值更新到指定寄存器中。
3.4 RV-LINK 的实现
TCK 周期驱动
rvl_tap_tick
函数执行一个 TCK 周期,四个阶段:低电平半周期、上升沿、高电平半周期、下降沿。
int rvl_tap_tick(int tms, int tdi) { int tdo; /* * ___ * ___| | */ // 1. 低电平半周期,首先输出 TMS、TDI 然后延时半个周期 rvl_jtag_tms_put(tms); rvl_jtag_tdi_put(tdi); rvl_jtag_delay_half_period(); // 2. 上升沿,上升沿之后读取 TDO rvl_jtag_tck_put(1); tdo = rvl_jtag_tdo_get(); // 3. 高电平半周期 rvl_jtag_delay_half_period(); // 4. 下降沿 rvl_jtag_tck_put(0); return tdo; }
3.5 实测波形
读取 id 和 dtmcs 的完整波形:
IR 扫描的波形:
DR 扫描的波形:
进入 Shift-IR 状态的细节:
退出 Shift-IR 状态的细节: