TAP/Chain/target/monitor的关系

在 OpenOCD 的语境下,这四个术语描述了从“物理硬件连接”到“软件调试指令”的不同层级。理解它们的区别对于配置 cv32e40p 这种嵌入式系统至关重要。
以下是它们的详细定义和关系:

1. TAP (Test Access Port)

定义:硬件层面的逻辑接口。
TAP 是 JTAG 协议中最基本的单元。每一个具有 JTAG 接口的芯片(或芯片内部的逻辑单元)在 JTAG 链上都表现为一个 TAP。
  • 物理上:它对应芯片内部的 JTAG 状态机。
  • 功能上:它负责处理指令(IR)和数据(DR)的移位。
  • 配置命令:在 OpenOCD 脚本中,你使用 jtag newtap <chip_name> <tap_name> -irlen 6 来定义它。
  • 类比:TAP 就像是进入大楼(芯片)的一个特定的大门

2. Chain (JTAG Chain)

定义:物理链路。
当你在电路板上通过线缆连接多个芯片(例如 FPGA、ARM 核心、电源管理芯片)时,它们的 TDI 和 TDO 首尾相连,就构成了一个
  • 特征:在一个 Chain 中,所有设备共享 TCK 和 TMS,但数据信号(TDI/TDO)是串联的。
  • 你的情况:在你当前的 bscan2jtag 实验中,FPGA 本身是一个 Chain 的起点,而你的 cv32e40p 内部的 dmi_jtag_tap 则是这个 Chain 上的一个特定节点。
  • 类比:Chain 就像是整条街道,上面排列着很多扇“大门”(TAP)。

3. Target

定义:调试的对象(通常是 CPU 核心)。
Target 是 OpenOCD 抽象出来的软件对象,代表了一个你可以下达“暂停”、“读取寄存器”或“单步执行”命令的实体。
  • 关系:一个 Target 必须绑定在一个特定的 TAP 上。TAP 负责数据的进出,而 Target 负责解释这些数据(例如将其识别为 RISC-V 的调试命令)。
  • 配置命令:使用 target create riscv.cpu riscv -chain-position <TAP_NAME>
  • 你的情况cv32e40p 核心就是 Target。
  • 类比:Target 就像是大楼里的住户。你想找住户聊天(调试),必须先通过正确的大门(TAP)。

4. Monitor

定义:GDB 与 OpenOCD 之间的桥梁指令。
当你在使用 GDB(GNU Debugger)进行调试时,GDB 本身并不知道什么是“JTAG”或“FPGA 寄存器”。
  • 功能monitor 是 GDB 的一个特殊前缀。当你输入 monitor reset 时,GDB 会将这个命令原封不动地传给 OpenOCD。
  • 用法
    • monitor reset halt:告诉 OpenOCD 重置 Target 并挂起。
    • monitor reg:查看 OpenOCD 层面的寄存器状态。
  • 类比:Monitor 就像是对讲机。你通过 GDB 发号施令,通过 Monitor 频道传达给现场的工作人员(OpenOCD)去动手操作硬件。

总结对比表

术语
范畴
描述
关键操作
TAP
硬件逻辑
JTAG 状态机入口
定义 IDCODE、IR 长度
Chain
物理物理
多个 TAP 的串联链路
确保 TDI/TDO 链路导通
Target
逻辑实体
被调试的 CPU/内核
读写内存、单步、断点
Monitor
交互接口
GDB 发往 OpenOCD 的命令
执行硬件复位、读写 CSR
为什么你之前的 Log 报错 Target not examined yet
这意味着 OpenOCD 已经识别到了 Chain 上的 TAP(所以你能看到 IDCODE),但是它在尝试将这个 TAP 关联到 Target(CPU)并进行初始化握手时失败了。这通常是因为 IR 长度不匹配或复位信号(TRST/SRST)配置不当导致的。
既然你正在修改 bscan2jtag,确保你的 target 配置指向的是你新定义的那个 -irlen 6 的 TAP。

cfg文件各语句含义?

在这份 config_openocd.cfg 配置文件中,代码可以被划分为四个维度,分别对应物理连接、逻辑设备、调试对象以及操作指令。
以下是详细的代码归类与解释:

1. Chain (JTAG 链路层)

这些语句定义了 OpenOCD 如何通过物理硬件(调试器)与 FPGA 上的 JTAG 链路建立通信。它们规定了“路”是怎么修的,以及信号的物理特性。
  • adapter driver ftdi: 指定使用的物理适配器驱动。
  • ftdi vid_pid / channel / layout_init / layout_signal: 这些语句在定义物理引脚的映射(哪根线是 TCK,哪根是 TMS 等)。它们决定了如何驱动物理 Chain
  • adapter speed 1000: 定义 JTAG 时钟TCK的频率(1000KHz=1MHz),影响整个 Chain 的数据传输速率。

2. TAP (JTAG 逻辑节点)

这部分定义了链路上具体存在的“门”。
  • jtag newtap $_CHIPNAME cpu -irlen 5:
    • 性质:这是定义 TAP 的核心命令。
    • 关键参数irlen 5 声明了这个 TAP 指令寄存器的长度。这必须与你硬件(dmi_jtag.sv)中的参数完全匹配。
    • 作用:它在逻辑链路上“占了一个位”,告诉 OpenOCD:“这里有一个设备,它的名字叫 riscv.cpu”。

3. Target (调试对象层)

这部分定义了你要调试的“人”(CPU 内核),以及它与“门”(TAP)之间的绑定关系。
  • target create $_TARGETNAME riscv -chain-position $_TARGETNAME:
    • 交互:这是 TargetTAP 之间的关键交互。chain-position 告诉 OpenOCD:“这个 RISC-V 核心就在刚才定义的那个 TAP 后面”。
    • 性质:定义了调试目标的类型(riscv),使 OpenOCD 知道该用哪套协议(如 RISC-V 的 DMI)来跟它交流。
  • riscv set_mem_access / set_reset_timeout_sec:
    • 性质:这些是 Target 的特定属性配置,决定了 OpenOCD 读写内存的方式和容忍超时的时间。

4. Monitor / Command (交互操作层)

这些是动作指令,通常是你手动在 Telnet 窗口输入或者 GDB 通过 monitor 前缀发送的指令。
  • init:
    • 交互:这是一个“分水岭”指令。它触发 OpenOCD 去扫描物理 Chain,验证 TAP 的 IDCODE,并尝试对 Target 进行初始检查(Examine)。
  • halt:
    • 性质:一个具体的控制指令。它要求 Target(CPU)进入暂停状态。

总结对照表

代码语句
归属类别
说明
adapter ... / ftdi ...
Chain
定义物理调试器如何连接到 JTAG 链路
jtag newtap ... -irlen 5
TAP
定义链路上有一个 IR 长度为 5 的节点
target create ... -chain-position ...
Target & TAP 交互
将 CPU 对象挂载到指定的 JTAG 节点上
riscv set_mem_access ...
Target
设置 CPU 调试时的具体行为参数
init / halt
Monitor / 操作
启动连接流程并下达控制指令

数据如何在GDB和dmi模块之间一层一层发送?

理解这个过程,可以把它看作是一条跨越多个协议层级的“数据传输链”。你的调试请求从电脑的 GDB 出发,经过了多种转换,最终到达 CPU 核心内部。

数据传递路径与层级结构

第一层:GDB 与 OpenOCD (软件层)

  • 交互协议GDB Remote Serial Protocol (RSP)
  • 通信状况:逻辑上的串行通信。GDB 通过 TCP 端口(通常是 3333)发送文本指令(如 vContm 内存读取命令)给 OpenOCD。

第二层:OpenOCD 与 USB 调试器 (指令层)

  • 交互协议USB 控制协议 / FTDI 驱动协议
  • 通信状况:高速串行通信(USB 链路)。OpenOCD 将 GDB 的指令翻译为 JTAG 命令序列。例如,它会计算出需要移位多少个 TCK 时钟周期,以及 TMS 需要在何时从 0 变 1 以控制状态机。

第三层:调试器与 FPGA 引脚 (JTAG 物理层)

  • 交互协议IEEE 1149.1 JTAG 标准
  • 通信状况:同步串行通信。
    • 时钟 (TCK):作为所有同步的基准。
    • TMS:控制状态机(Test Access Port Controller)。
    • TDI/TDO:数据输入/输出引脚。
  • FPGA 内部处理:你在 dmi_jtag_tap.sv 中看到的,正是这个状态机。它根据 TMS 的变化,在 Shift-IRShift-DR 状态下完成指令或数据的移位。

第四层:FPGA 内的 JTAG 到 DMI (隧道协议层)

  • 协议Debug Transport Module (DTM) 协议
  • 通信状况:这是 bscan2jtag 模块在处理的部分。
    • 它将 JTAG 的数据移位转换成了 dmi_req_t 这种结构化数据(包含 addrdataop 等)。
    • CDC (时钟域交叉)dmi_cdc.sv 非常重要。JTAG 信号运行在 TCK 时钟域,而 CPU 的调试模块(DM)运行在系统时钟域 (clk_i)。CDC 通过双触发器(Two-phase handshaking)确保数据在两个频率不等的域之间安全传递。

第五层:DMI 到 DM (内部总线层)

  • 协议DMI (Debug Module Interface) 接口
  • 通信状况:并行握手。
    • 这是模块间的直接连接,不再是“位移”式的串行发送,而是基于 valid/ready 握手的并行信号传递。
    • dm_top.sv 收到 DMI 请求后,根据 addr 命中 dm_csrs.sv(寄存器读写)或者 dm_mem.sv(程序缓冲区访问)。

总结:数据形式的转换历程

阶段
数据形态
通信类型
GDB
文本指令 (RSP)
逻辑串行 (TCP)
OpenOCD
JTAG 位流序列
物理串行 (USB)
FPGA (JTAG TAP)
位移流 (Shift Register)
同步串行 (TCK/TMS/TDI/TDO)
FPGA (DTM/CDC)
结构化请求 (dmi_req_t)
同步/异步握手
DM 内部
并行总线数据
并行信号

接口状况的关键点

  • 串行转并行:整个过程的核心在于JTAG 移位寄存器。它将电脑端发送的、在时间序列上排列的 32 位甚至更多位的数据,在硬件中变成物理上的并行触发器状态。
  • 性能瓶颈:通信最慢的环节通常是 JTAG 位移速度。这就是为什么你修改 adapter speed 会直接影响调试响应速度。
  • 同步关键:如果你修改了 irlen(IR 长度),JTAG 状态机移位的数据位数就会变动,导致 OpenOCD 认为收到的 IDCODE 是错误的,进而触发 Target not examined yet
理解你的硬件修改方向:
你正在修改的 bscan2jtag,本质上是在 第三层(JTAG 物理层)第四层(隧道协议层) 之间添加了一层自定义的逻辑。通过硬编码 tap_cnt_ok = 1,你实际上是在告诉 OpenOCD:“不要再试图通过隧道协议跟我协商了,直接按我给的 irlen = 6 进行移位操作吧”,从而极大地简化了同步过程。
 
Loading...