Riscv debug release框图
仿真环境下的Riscv debug框图
平头哥调试环境
XuanTie DebugServer是一个调试代理软件,它通过CKLINK,以JTAG的方式连接目标板,并支持“GDB Remote Protocol” 。开发者可以通过GDB对运行在玄铁800系列和玄铁900系列处理器上的软件程序进行在线调试。
OpenOCD & GDB
OpenOCD 是一款支持多种芯片体系结构的开源调试和编程工具,它可以连接到不同的调试适配器,例如 J-Link、ST-LINK、CMSIS-DAP 等。通过 OpenOCD,我们可以在嵌入式系统上执行调试命令,例如读取寄存器的值、往 Flash中下载程序、启动或停止运行等。
GDB(GNU Debugger)是一个强大的命令行调试器,它支持多种体系结构和编程语言,并且可以与多种编程工具和 IDE 集成。GDB 可以识别多种调试器协议,并进行远程调试,它允许我们在嵌入式系统上调试代码,并且可以与 OpenOCD 集成使用。
OpenOCD 和 GDB 通常一起使用,通过 OpenOCD 连接到调试适配器,然后使用 GDB 发送调试命令到 OpenOCD,这样我们就可以在嵌入式系统上执行调试命令来调试代码了。在调试中,我们可以设置断点、单步执行、查看变量、观察程序状态等,这些调试功能可以帮助我们快速定位代码中的问题并进行调试和优化。
OpenOCD & GDB 的启动步骤
- 配置硬件连接:连接调试目标设备和调试工具(例如 JTAG 调试器),确保硬件连接正确。
- 准备配置文件: 创建 OpenOCD 的配置文件,该文件描述了调试目标设备的连接方式、芯片型号、调试器类型等信息。配置文件通常是一个 .cfg 文件,如下C920.cfg。
debug_level 3
adapter speed 20000
gdb_port 3333
telnet_port 4444
if {$::env(USE_JTAG_DPI)} {puts "debug point USE_JTAG_DPI"adapter driver remote_bitbangremote_bitbang host localhostremote_bitbang port 9999
}
if {$::env(USE_JTAG_VPI)} {puts "debug point USE_JTAG_VPI"adapter driver jtag_vpi# Set the VPI JTAG server portif { [info exists VPI_PORT] } {set _VPI_PORT $VPI_PORT} else {set _VPI_PORT 5555}# Set the VPI JTAG server addressif { [info exists VPI_ADDRESS] } {set _VPI_ADDRESS $VPI_ADDRESS} else {set _VPI_ADDRESS "127.0.0.1"}jtag_vpi set_port $_VPI_PORTjtag_vpi set_address $_VPI_ADDRESS
}set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10000b6fset _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAMEinit
puts "init done"halt
puts "Ready for Remote Connections"
- 启动 OpenOCD:在终端中运行 OpenOCD,并指定配置文件。例如:
openocd -f C920.cfg
- 连接 GDB:在另一个终端中启动 GDB,并连接到 OpenOCD 的远程调试服务器。例如:
target remote localhost:3333
- 加载程序:在 GDB 中加载要调试的程序,设置断点等。
- 开始调试:通过 GDB 发送调试命令,如单步执行、断点设置等,与目标设备进行交互。
- 退出:完成调试后,可以退出 GDB 和 OpenOCD。
运行log:
Debug: 20 2 command.c:154 script_debug(): command - gdb_port 3333
Debug: 21 2 command.c:154 script_debug(): command - telnet_port 4444
Debug: 22 2 command.c:154 script_debug(): command - adapter driver jtag_vpi
Info : 23 2 transport.c:107 allow_transports(): only one transport option; autoselecting ‘jtag’
Debug: 24 2 command.c:154 script_debug(): command - jtag_vpi set_port 5555
Info : 25 2 jtag_vpi.c:602 jtag_vpi_set_port(): jtag_vpi: server port set to 5555
Debug: 26 2 command.c:154 script_debug(): command - jtag_vpi set_address 127.0.0.1
Info : 27 2 jtag_vpi.c:617 jtag_vpi_set_address(): jtag_vpi: server address set to 127.0.0.1
Debug: 28 2 command.c:154 script_debug(): command - jtag newtap riscv cpu -irlen 5 -expected-id 0x10000b6f
Debug: 29 2 tcl.c:419 handle_jtag_newtap_args(): Creating New Tap, Chip: riscv, Tap: cpu, Dotted: riscv.cpu, 4 params
Info : 53 2 jtag_vpi.c:565 jtag_vpi_init(): jtag_vpi: Connection to 127.0.0.1 : 5555 successful
Info : 66 134793 core.c:1133 jtag_examine_chain_display(): JTAG tap: riscv.cpu tap/device found: 0x10000b6f (mfg: 0x5b7 (T-HEAD Semiconductor Co Ltd), part: 0x0000, ver: 0x1)
Info : 487 3662279 gdb_server.c:3888 gdb_target_start(): starting gdb server for riscv.cpu on 3333
Info : 488 3662279 server.c:298 add_service(): Listening on port 3333 for gdb connections
Info : 522 3888663 server.c:298 add_service(): Listening on port 6666 for tcl connections
Info : 523 3888663 server.c:298 add_service(): Listening on port 4444 for telnet connections
Info : 535 3931037 server.c:90 add_connection(): accepting ‘gdb’ connection on tcp/3333
关于riscv-tests/debug 测试框架
测试框架链接: riscv-tests
debug需要许多系统组件协同工作。这里的测试执行端到端测试,与 GDB 和 OpenOCD 通信。
如果仿真或硬件通过了所有这些测试,那么你就可以确信实际调试接口运行正常。
我们采用仿真的方式,进行所有这些测试
riscv-tests/debug是一套python脚本,testlib.py中提供了Gdb Openocd VcsSim类,
Gdb类调用subprocess启动GDB,且提供了Riscv 合规测试和debug测试常用命令的函数,例如gdb.c()中实现了continue命令
Openocd类调用subprocess启动OpenOCD,等待OpenOCD完成riscv_examine且监测如下信息Listening on port .* for gdb connections
Info : 475 3675417 riscv-013.c:2137 examine(): [riscv.cpu] Examined RISC-V core; found 4 harts
Info : 476 3675417 riscv-013.c:2138 examine(): [riscv.cpu] XLEN=64, misa=0x800000000094112f
User : 477 3675417 target.c:724 target_examine_one(): [riscv.cpu] Target successfully examined.
Info : 488 3675417 server.c:298 add_service(): Listening on port 3333 for gdb connections
VcsSim类调用subprocess启动PICOsim仿真,循环监测^Listening on port (\d+)$信息(jtag_vpi server中打印的)说明带有jtag server的testbench启动成功,退出循环,然后就启动OpenOCD了
OpenOCD的vpi client通过socket和testbench中jtag_vpi server连接,jtag_vpi server中有如下代码:
int jtag_server_create(int port, int loopback_only)
{......PRINT_MSG("jtag_vpi server created.\n");PRINT_MSG("Listening on port %d\n", port);PRINT_MSG("Waiting for client connection...\n");return JTAG_SERVER_SUCCESS;
}
开始riscv-tests/debug之前需要进行如下设置:
- 设置OpenOCD使用配置文件,如下面的配置文件Riscv 合规测试和debug测试
- 设置target硬件的配置
import targets
import testlib
import os
import subprocessclass C920Hart(targets.Hart):xlen = 64ram = 0x80000000ram_size = 256 * 1024 * 1024bad_address = 0x0800080000instruction_hardware_breakpoint_count = 3link_script_path = "C920.lds"misa = 0x800000000094112freset_vectors = [0x800000000]class C920Sim(targets.Target):timeout_sec = 100000 #msserver_timeout_sec = 50000remotelogfile_enable = Trueopenocd_config_path = "C920.cfg"harts = [C920Hart()]support_memory_sampling = False # Needs SBAicount_limit = 1 #//count is hard-wired to 1clint_addr = 0xFF08000000 + 0x04000000def __init__(self, path, parsed):super().__init__(path, parsed) self.parsed = parsedif not self.parsed.test_prefix:original_dir = os.getcwd()os.chdir(os.path.expandvars("$PRJ_HOME/tb/riscv_dbg/remote_bitbang"))output_file = "build.log"with open(output_file, "w") as f:subprocess.run(['make', 'clean'], stdout=f, stderr=f)with open(output_file, "a") as f:subprocess.run(['make', 'CFLAGS_DBG="-DRISCV_DBG=1"'], stdout=f, stderr=f)os.chdir(original_dir)def create(self):if self.parsed.test_prefix:#sim_cmd = f'python3 $PICOSIM_DIR/yasaTop.py -notest_flist -t CpuRiscvDgbTest -tsmc -seed 1 -riscv_dbg -test_prefix {self.parsed.test_prefix} -v -so'sim_cmd = f'python3 $PICOSIM_DIR/yasaTop.py -notest_flist -t CpuRiscvDgbTest -tsmc -seed 2 -jtag_vpi -test_prefix {self.parsed.test_prefix} -v -w -so -sim_timeout 500000'else:sim_cmd = 'python3 $PICOSIM_DIR/yasaTop.py -notest_flist -t CpuRiscvDgbTest -tsmc -seed 1 -riscv_dbg -test_prefix riscv_dbg_openocd -v'# timeout includes compile time, so set it a large time then default value# firstly need goto tb/riscv_dbg/remote_bitbang, then execute ~make clean, ~make CFLAGS_DBG="-DRISCV_DBG=1"return testlib.VcsSim(sim_cmd=os.path.expandvars(sim_cmd), debug=False, timeout=1800)
- 跑一个case
\bsub -m picocsxx -Is ./gdbserver.py targets/T-head/C920Sim.py CheckMisa --test_prefix picocsxxx --sys_out