2. 使用OpenOCD连接RISC-V SoC的JTAG调试
任务目标
在本案例中,你将启动QEMU内置的RISC-V virt机器,在其上运行一个简单的RISC-V汇编程序,并通过GDB远程连接进行调试。完成本案例后,你将掌握QEMU作为RISC-V处理器模拟器的基本使用方法,以及GDB远程调试的完整流程。
环境准备
需要安装以下工具(以Ubuntu/Debian为例):
sudo apt-get install qemu-system-misc gdb-multiarch binutils-riscv64-linux-gnu
验证安装:
qemu-system-riscv64 --version
riscv64-linux-gnu-as --version
gdb-multiarch --version
实现步骤
1. 编写RISC-V汇编程序
创建一个文件 hello.s,内容如下:
.section .text
.globl _start
_start:
li t0, 0x10000000 # UART基地址(virt机器)
li t1, 0x48 # 'H'
sb t1, 0(t0)
li t1, 0x65 # 'e'
sb t1, 0(t0)
li t1, 0x6C # 'l'
sb t1, 0(t0)
sb t1, 0(t0) # 第二个'l'
li t1, 0x6F # 'o'
sb t1, 0(t0)
li t1, 0x0A # '\n'
sb t1, 0(t0)
# 死循环,便于调试观察
loop:
j loop
2. 编译链接
riscv64-linux-gnu-as -o hello.o hello.s
riscv64-linux-gnu-ld -o hello.elf -Ttext=0x80000000 hello.o
riscv64-linux-gnu-objcopy -O binary hello.elf hello.bin
说明:virt机器默认加载地址为0x80000000,链接脚本指定代码段起始地址。
3. 启动QEMU并运行程序
qemu-system-riscv64 -machine virt -nographic -bios none -kernel hello.bin
预期输出:终端显示 Hello 后程序进入死循环。按 Ctrl+A 然后按 X 退出QEMU。
4. 连接GDB进行远程调试
首先以调试模式启动QEMU(新终端):
qemu-system-riscv64 -machine virt -nographic -bios none -kernel hello.bin -s -S
参数说明:-s 在端口1234开启GDB服务,-S 启动时暂停CPU等待调试器连接。
然后在另一个终端启动GDB:
gdb-multiarch hello.elf
(gdb) target remote :1234
(gdb) continue
GDB连接后,程序开始执行,QEMU终端输出 Hello。此时可在GDB中按 Ctrl+C 中断程序,使用 info registers 查看寄存器状态,或使用 break *0x80000000 设置断点后重新运行。
验证方法
- 运行验证:QEMU终端正确输出
Hello,说明程序在模拟的RISC-V处理器上正常执行。 - 调试验证:GDB成功连接后,执行
continue能看到程序运行;中断后info registers能显示RISC-V寄存器内容(如pc、t0、t1),且pc指向死循环地址。 - 断点验证:在
0x80000000设置断点后重启程序,GDB应在第一条指令处暂停,单步执行stepi可逐条观察指令执行。
常见问题
- GDB连接失败:确认QEMU以
-s -S参数启动,且端口1234未被占用。 - 程序无输出:检查UART地址是否为
0x10000000(virt机器标准地址),以及链接地址是否正确。 - 架构不匹配:使用
gdb-multiarch而非默认gdb,并确保加载的是ELF文件(hello.elf)而非二进制文件。
本案例通过最小可复现示例,完成了QEMU模拟RISC-V处理器、运行程序及GDB远程调试的完整闭环。后续案例将在此基础上扩展更多调试技巧。