JTAG (三) jtag实例 riscv

  • jtag标准
jtag 是一个标准, IEEE1149.1,标准文件可以在 http://standards.ieee.org 获取
JTAG refers to IEEE Std 1149.1-2013. 

It is a standard that defines 
    test logic that can be included in an integrated circuit 
    	to test the interconnections between integrated circuits, test the integrated circuit itself, 
		and observe or modify circuit activity during the components normal operation. 

This specification uses the latter functionality. //  observe ...
The JTAG standard defines a Test Access Port (TAP) that can be used to read and write a few custom registers, 
which can be used to communicate with debug hardware in a component.
jtag 定义了什么
	1. 硬件接口
    标准JTAG采用四线方式,分别是TCK、TMS、TDI和TDO,有一个可选的TRST引脚  // 实测 andes 不支持 TRST
    2.寄存器
        2. 指令寄存器  //用 SHIFT-IR 时序 来写
            BSR
            BYPASS
            IDCODES
            EXTEST
            SAMPLE/PRELOAD
            INTEST
        3. 多个数据寄存器 //用 SHIFT-DR 时序 来写
    3. 芯片内部的jtag状态机
    
  • risv 的jtag
其他芯片引用jtag标准,具体实现是什么
    1. 硬件接口 	安全按照标准
    2. 寄存器 		不完全按照标准,但是 BYPASS,IDCODES 还是有的
    3. jtag状态机 	完全按照标准
riscv 的debug 引用了 jtag 标准  具体查看"RISC-V External Debug Support Version 0.13"
整体debug 架构为 // 带""的位于芯片内部
gdb <-> openocd <-> jlink <-> "DTM" <-> "DMI" <-> "DM"

DTM 中有定义 各个指令寄存器   // BYPASS IDCODE DTM DMI
DM  中有定义 DMI 的数据寄存器 // 访问前需要先选中 "DTM 中的 DMI" 
  • riscv-jtag 怎么 observe or modify circuit activity during the components normal operation.
目标都有什么
1. 通用寄存器
2. 核心寄存器
3. 内存
4. debug 内部的寄存器
怎么 能 observe or modify 这些目标
1. 外部 通过 "TCK、TMS、TDI和TDO" 改变芯片内部的 jtag 状态机 能够将数据 写入和将数据读出
2. "数据写入和将数据读出" 是在 Shift-IR(状态机的一个过程) 和  Shift-DR(状态机的一个过程) 中做的
  • riscv IDCODE 获取过程
参考代码 : https://gitee.com/liangkangnan/stm32_riscv_jtag_slave
一般过程
// IDCODE类寄存器 , 需要走两次链才能读取
1.走 IR链 选中指令寄存器并读取 
    // Shift-IR TDI 发送 以(0x1f)为掩码的数据(0x01)到芯片
    	// 芯片更新 ir_reg 为 IDCODE
    // Shift-IR TDO 发送一个无意义的 0x01
2.走 DR链 选中 该"指令寄存器" 下的 数据寄存器
    // Shift-DR TDI 发送 数据(芯片接收该数据,该数据不被关心)
    // Shift-DR TDO 发送 ir_reg(即IDCODE)的内容

  • DMI hartinfo 读取写入过程
//DMI 中的hartinfo类寄存器 , 需要 走3次链才能读取
1.走 IR链 选中指令寄存器
    // Shift-IR TDI 发送 以(0x1f)为掩码的数据(0x11)到芯片
    	// 芯片更新 ir_reg 为 DMI
    // Shift-IR TDO 发送一个无意义的 0x01
2.走 DR链 选中 该"指令寄存器" 下的 数据寄存器 // 选中DMI_HALTINFO
    // Shift-DR TDO 发送 exdata 的内容
    // 为了简化 exdata 的理解, 可以认为 Shift-DR TDO 走完 , Shift-DR TDI 才发生
    // 其实是  同一时刻发生的
    // Shift-DR TDI 发送 数据(dm_addr dm_data dm_op,芯片接收该数据,并做处理)
    	// 如果是读, 将 dm_addr 的内容 写入 exdata
    	// 如果是写, 将 dm_data 写入 dm_addr , 并将结果(成功为0)在 UPDATE_DR 时 写入 exdata
    
3.走 DR链 选中 该"指令寄存器" 下的 数据寄存器
    // Shift-DR TDO 发送 exdata 的内容
    // 为了简化 exdata 的理解, 可以认为 Shift-DR TDO 走完 , Shift-DR TDI 才发生
    // 其实是  同一时刻发生的
    // Shift-DR TDI 发送 数据(dm_addr dm_data dm_op,芯片接收该数据,并做处理)
    	// 如果是读, 将 dm_addr 的内容 写入 exdata
    	// 如果是写, 将 dm_data 写入 dm_addr , 并将结果(成功为0)在 UPDATE_DR 时 写入 exdata


其实关于 DR链 中的 exdata 更新的顺序是这样子的
   CAPTURE_DR
    	shift_data 被赋值为 exdata
   SHIFT_DR
    	接收tdi上的数据到 shift_data
    	发送 shift_data 中的数据到 tdo 
    		// shift_data 为 64 位, 装载了 这里要收的数据,和这次要发的数据
    		// shift_data 为了保存 这些数据 ,需要用到 移位操作
   UPDATE_DR上升沿
    	更新 dm_addr dm_data dm_op 和 exdata
  • DMI 通用寄存器 读取写入过程 : 该过程是 Abstract Command 中的 AccessRegister
//DMI 中的hartinfo类寄存器 , 需要 走4次链才能读取
1.走 IR链 选中指令寄存器
    // Shift-IR TDI 发送 以(0x1f)为掩码的数据(0x11)到芯片
    	// 芯片更新 ir_reg 为 DMI
    // Shift-IR TDO 发送一个无意义的 0x01
2.走 DR链 选中 该"指令寄存器" 下的 数据寄存器  // DMI_COMMAND
    // Shift-DR TDO 发送 exdata 的内容
    // 为了简化 exdata 的理解, 可以认为 Shift-DR TDO 走完 , Shift-DR TDI 才发生
    // 其实是  同一时刻发生的
    // Shift-DR TDI 发送 数据(dm_addr dm_data dm_op,芯片接收该数据,并做处理)
    	// 如果是读, 将 dm_addr 的内容 写入 exdata
    	// 如果是写, 将 dm_data 写入 dm_addr , 并将结果(成功为0)在 UPDATE_DR 时 写入 exdata , 将 通用寄存器的内容写入data0
    
3.走 DR链 选中 该"指令寄存器" 下的 数据寄存器 // 选中 DMI_DATA0  // data0 写入 exdata
    // Shift-DR TDO 发送 exdata 的内容
    // 为了简化 exdata 的理解, 可以认为 Shift-DR TDO 走完 , Shift-DR TDI 才发生
    // 其实是  同一时刻发生的
    // Shift-DR TDI 发送 数据(dm_addr dm_data dm_op,芯片接收该数据,并做处理)
    	// 如果是读, 将 dm_addr 的内容 写入 exdata
    	// 如果是写, 将 dm_data 写入 dm_addr , 并将结果(成功为0)在 UPDATE_DR 时 写入 exdata
4.走 DR链 选中 该"指令寄存器" 下的 数据寄存器 // 获取 exdata 中的 data0
    // Shift-DR TDO 发送 exdata 的内容
    // 为了简化 exdata 的理解, 可以认为 Shift-DR TDO 走完 , Shift-DR TDI 才发生
    // 其实是  同一时刻发生的
    // Shift-DR TDI 发送 数据(dm_addr dm_data dm_op,芯片接收该数据,并做处理)
    	// 如果是读, 将 dm_addr 的内容 写入 exdata
    	// 如果是写, 将 dm_data 写入 dm_addr , 并将结果(成功为0)在 UPDATE_DR 时 写入 exdata

riscv debug 所有功能

// RISC-V External Debug Support Version 0.13.2
1. 读写 debug 寄存器
	// IDCODE 类
	// DMI 下的寄存器 P20
2. 以第一种方法(Abstract Command 中的 Quick Access)执行 program buffer 中的指令(用于读写寄存器,读写内存)
	// program buffer 可以写入 16个指令 progbuf0 - progbuf15
	// 写入的指令必须以 "ebreak" 结束
3. 以第二种方法(Abstract Command 中的 Access Register 的 postexec)执行 program buffer 中的指令(用于读写寄存器,读写内存)
	// 
4. 以一种方法(Abstract Command 中的 Access Register 的 transfer)读写 Abstract Register(CSRs/GPRs/Floating point registers/Reserved for non-standard extensions and internal use.) 功能 
	// 寄存器列表在  的 P12

RISC-V External Debug Support Version 0.13.2 d5029366d59e8563c08b6b9435f82573b603e48e
读写寄存器的两种方法  // B.6 Accessing Registers P72
	Abstract Command 寄存器 // 具体在 "Abstract Commands" 中的 "Access Register" // P12
	program buffer 的执行 // 
读写内存的三种方法 // B.7 Reading Memory P73 B.8 Writing Memory P76
	system bus
	program buffer 的执行
	Abstract Command 寄存器 // 具体在 "Abstract Commands" 中的 "Access Memory" // P14
	

Guess you like

Origin blog.csdn.net/u011011827/article/details/121149113