在RISCV前期验证和驱动开发阶段比较依赖DEBUG,甚至第一步就是要调通DEBUG使其能工作,否则早期都无法进行程序下载与调试验证。规格书RISC-V Debug Specification Version 1.0-STABLE 中介绍了RISCV的DEBUG实现,我们就分几篇来分享相关内容。其中Chapter 6 Debug Transport Module (DTM), non-ISA这一章节介绍了基于JTAG的DTM实现,我们这一篇就来分享下JTAG相关的基本知识。通过本文应该要能通过逻辑分析仪抓取JTAG信号,确认JTAG信号是否正常,知道JTAG正在进行什么操作,有了这部分基础知识才能为进一步调试做准备。
Joint Test Action Group (JTAG):联合测试行动小组.
boundary-scan test (BST):边界扫描测试
Boundary-scan cells(BSC):边界扫描单元
BST可以在不使用物理测试探针的情况下测试引脚连接,并在设备正常运行时捕获功能数据。设备中的边界扫描单元可以将信号施加到引脚上,或者从引脚或核心逻辑信号中捕获数据,即测试数据串行地移入边界扫描单元, 捕获的数据连续移出,这样就可以实现测试数据输入输出,输入控制行为,然后对输出与预期结果进行外部比较即可进行功能测试。
以下是一个简单的图示,
抽象一下即内部使用边界扫描寄存器和外部TDI,TDO交互,边界扫描寄存器即一个很长的串行移位寄存器,使用TDI引脚作为输入,TDO引脚作为输出。
示意如下,类似一个环形结构,TDI->边界扫描寄存器->TDO
从信号角度看JTAG是类似于SPI的同步串行接口。
高位在前,TCK下降沿发送端输出数据,上升沿接收端采集数据。
其中只有TDI、TDO、TMS和TCK四个信号是必需的。
具体的时序参数参考如下示意图,对应的参数可以参考JTAG标准,这里其实无需详细了解,除非需要去确认临界的时序参数是否有问题。平常只需要知道TCK下降沿发送端输出数据,上升沿接收端采集数据即可。
TDI:测试数据输入(输入输出是以TARGET的角度而言),TARGET内部弱上拉(如果没有则PCB上添加),在TCK的上升沿被TARGET采集。
比如如下波形,我们在TCK的上升沿看TDI的数据,传输的是10001,即0x11.
所以对于发送端,需要在TCK上升沿前准备好数据。
TDO:测试数据输出(输入输出是以TARGET的角度而言),TCK下降沿TARGET输出数据。在没有数据输出时,应该处于tri-stated状态。接收端在上升沿采集数据。
比如如下波形,我们在TCK的上升沿看TDO的数据,传输的是10001,即0x11。
注意我们不能在TCK下降沿去读数据,因为TCK下降沿只是理论上的开始输出数据,到数据输出到线上可能还有延迟,所以我们要等数据稳定,到TCK上升沿再去读数据,如下图所示,即要考虑数据的setup建立时间。
TDO引脚在除SHIFT_IR和SHIFT_DR状态之外的所有状态下都是三态的。TDO引脚在进入任一移位状态后,在TCK的第一个下降沿被激活,在离开任一移位状态时,在TCK的第一个x下降沿被三态化。
当SHIFT_IR状态被激活时,TDO不再是三态,指令寄存器的初始状态在TCK的下降沿被移出。只要shift_IR状态处于活动状态,TDO就会继续移出指令寄存器的内容。只要TMS保持低电平,TAP控制器就保持在SHIFT_IR状态。
在SHIFT_IR状态下,通过移动TCK上升沿TDI引脚上的数据来输入指令代码。操作码的最后一位必须与下一个状态EXIT1_IR激活的同时计时;EXIT1_IR是通过在TMS上设置逻辑高来输入的。一旦处于EXIT1_IR状态,TDO再次变为三态。
TMS:测试模式选择,TARGET的输入信号,TARGET内部弱上拉(如果没有则PCB上添加),用于决定状态机的状态流转。同样的发送端在TCK的下降沿输出数据,TARGET在上升沿采集数据。
比如如下波形:
开始位于状态TEST_LOGIC/RESET
在TCK的上升沿看TMS, 如下0->1->1
即对应状态
TEST_LOGIC/RESET->RUN_TEST/IDLE->SELECT_DR_SCAN->SELECT_IR_SCAN
TCK:测试时钟输入,TARGET的输入信号.TARGET内部弱下拉(如果没有则PCB上添加)。上升沿发送端输出数据,上升沿接收端采样数据。
以上几个引脚是必须的,还有一些引脚不是必须的,比如
nRESET: 仿真器的开漏输出,输出低复位目标系统(SOC,PCB上各种外设等)。该信号不能复位TARGET的DEBUG模块本身,这样才能保证在DEBUG模块本身不复位情况下复位SOC,DEBUG模块能捕获SOC复位后从开始执行第一条指令的过程。如果仅仅是复位SOC可以直接通过JTAG读写寄存器的方式进行配置复位,所以不是必须的。但是如果要复位PCB板上其他外设等,则建议最好加上这个信号。
nTRST: 仿真器的输出,输出低复位TARGET的DEBUG模块本身,让DEBUG模块处于复位正常状态。这个信号也不是必须的,也可以通过JTAG进行复位。
还有一些其他的引脚都不是必须的一般也很少用,可以参考具体的规格书。很多JTAG仿真器还会带一些扩展功能,比如虚拟串口等这个就要参考实际的产品的说明。
以上说明了JTAG的信号的基本内容,有了以上内容就可以直接根据信号解析对应的数据,虽然一般不需要手动解析。一般逻辑分析仪都会带JTAG的解码,可以直接查看。但是有了以上知识可以在调试阶段确认信号是否正确合理,帮助排查问题。
现在来看JTAG的最重要的内容,即其状态机。JTAG通过TMS来决定内部状态机的流转,
对应如下的状态图。在TCK的上升沿采集TMS的状态是0还是1,然后决定一个状态是什么。
首先状态机肯定要有一个最初始状态,这里即TEST_LOGIC/RESET,并且要能方便的回到初始状态,否则需要持续记录状态,且任意记录错误一次状态机器就会跑着跑着就乱了,这样容错性不高。
从上面状态机看到,每次只要TMS始终保持1,最终总是会回到TEST_LOGIC/RESET,且TEST_LOGIC/RESET在TMS为1时依旧是TEST_LOGIC/RESET。这个路径最深为5,也就是只要连续发5个TMS=1,最终肯定会回到TEST_LOGIC/RESET,这就是状态机复位的操作。
当处于TEST_LOGIC/RESET状态时,BST电路被禁用,设备正常运行,指令寄存器以IDCODE作为初始指令。上电时,TAP控制器初始化为该状态。
如下从SHIFT_IR发送5个TMS=1回到初始状态。
所以在不确定当前状态是,可以发至少5个TMS=1,进入TEST_LOGIC/RESET这个初始状态。
比如如下抓到的波形,就是复位状态机的操作,发了一长串TMS=1,多发是为了确保复位成功,避免偶尔的干扰。
平时操作并不需要回到TEST_LOGIC/RESET状态,因为该状态会默认重新选择指令寄存器为IDCODE了。如果每操作一次都回到该状态,又需要重新设置指令寄存器等,效率就低了。所以只有确实异常了才会回到该状态。
平时操作完一次只需要回到RUN_TEST/IDLE状态,该状态相当于空闲但是指令寄存器等不变。
如下所抓到波形所示
JTAG提供了IR和DR寄存器的概念,IR即需要进行操作的类别,DR则为对应的数据。
所以一个操作包括,设置IR和读写DR的过程。
其中IR寄存器需要至少实现以下寄存器
l指令寄存器,用于确定要执行的动作和要访问的数据寄存器
l旁路寄存器,一个1位长的数据寄存器,用于在TDI和TDO之间提供最小长度的串行路径
l边界扫描寄存器,器件的所有边界扫描单元组成的移位寄存器。
对应RISCV中的定义如下,主要选择的IR就是0x10和0x11,然后对应的DR就是分别对应的是dtmcs和dmi的数据寄存器。其中选择IDCODE则DR在TDO输出的是32位厂商代码。
在这里其实可以理解为只是使用了JTAG的这种硬件的数据链路,即选择IR对应不同的DR内容的操作形式。规格书中介绍了基于JTAG的DTM实现,实际上也不可以不用JTAG,可以任意设计一种接口比如基于USB等都可以,使用JTAG只是因为它已经成为了行业标准,有大量的硬件设备可以直接拿来就用。
示意如下:
读写IR寄存器即先进入CAPTURE_IR状态,通过TDI将数据移入IR寄存器(SHIFT_IR),同时TDO会移出TARGET中原来的IR寄存器内容(相当于是环形结构,一边IN,一边OUT)。
类似的读写DR寄存器则先进入CAPTURE_DR状态,通过TDI将数据移入DR寄存器(SHIFT_DR),同时TDO会移出TARGET中原来的DR寄存器内容(相当于是环形结构,一边IN,一边OUT)。
IR和DR的长度根据实现不同,完成IR和DR的移动,EXIT1_IR/UPDATE_IR,EXIT_DR/UPDATE_DR更新生效即可。
所以JTAG操作就是分解为IR和DR的交换,全双工模式,不需要区分是读还是写。
即写入的同时有读出(即交换), 即TDI->IR->TDO, TDI->DR->TDO。
设置IR过程为
对应状态转移如下
实测波形如下
RUN_TEST/IDLE->SELECT_DR_SCAN->SELECT_IR_SCAN->CAPTURE_IR->
SHIFT_IR(5位)->EXIT1_IR->UPDATE_IR->RUN_TEST/IDLE
最终又回到了RUN_TEST/IDLE以便继续操作DR。
以上操作完IR后,会进入RUN_TEST/IDLE,以便操作DR
操作DR的流程如下
对应状态转移如下
实测波形如下
RUN_TEST/IDLE->SELECT_DR_SCAN->CAPTURE_DR->
SHIFT_DR(44位)->EXIT1_DR->UPDATE_DR->RUN_TEST/IDLE
以上操作完DR后,会进入RUN_TEST/IDLE,以便继续操作
《IEEE Std 1149.1-2001 (Revision of IEEE Std 1149.1-1990)
IEEE Standard Test Access Port andBoundary-Scan Architecture》
《13. IEEE 1149.1 (JTAG) Boundary-Scan Testing for MAX II Devices》
https://mp.weixin.qq.com/s/fZohshp5bhtEhpC8DrmJNg?token=176082340&lang=zh_CN 使用JTAG边界扫描快速进行FPGA引脚对应关系逆向
https://mp.weixin.qq.com/s/biR6j9wt7YxQ2GSXs-UpbQ?token=176082340&lang=zh_CN
《基于“矿板”低成本学习FPGA》逆向扫描插座所有IO引脚映射
本文主要分享了JTAG的基本知识,为后续调试RISCV的DEBUG做准备,对照实际抓取的波形来看JTAG的IR,DR的操作。