2. JTAG基础
说实话,很多工程师拿到一块新板子,第一件事就是急着点灯、跑系统。但我个人的经验是——先把调试工具链跑通,后面能省下大把时间。你想想看,如果连GDB都连不上目标,出了Bug你只能靠猜,那多痛苦。
这一节,我们就来把OpenOCD、GDB、调试脚本、硬件连接这四样东西,一个一个搞定。
1. OpenOCD配置——让调试器听懂你的话
OpenOCD(Open On-Chip Debugger)是个好东西。它把上位机的GDB命令,翻译成JTAG/SWD时序,发给目标芯片。说白了,它就是个翻译官。
配置OpenOCD,核心就两件事:
- 接口配置:告诉它你用的是什么调试器(J-Link、ST-Link、CMSIS-DAP等)
- 目标配置:告诉它你要调试什么芯片(STM32F4、i.MX RT、RISC-V等)
我习惯把配置拆成两个文件,这样复用性高。比如:
# interface.cfg —— 调试器配置
source [find interface/jlink.cfg]
adapter speed 1000
transport select jtag
# target.cfg —— 目标芯片配置
source [find target/stm32f4x.cfg]
reset_config srst_only srst_nogate
然后启动OpenOCD:
openocd -f interface.cfg -f target.cfg
嗯,这里要注意:adapter speed别设太高。我遇到过一上来设10MHz,结果线缆太长信号反射,连都连不上。一般1000kHz起步,稳定了再往上加。
jlink serial <你的序列号>,避免同时插多个J-Link时连错设备。我吃过这个亏,调试了一下午发现连的是隔壁工位的板子……
2. GDB连接目标——打通上位机到芯片的通道
OpenOCD跑起来后,默认在本地3333端口开了一个GDB服务。这时候,GDB就可以连上去了。
连接命令很简单:
arm-none-eabi-gdb your_firmware.elf
(gdb) target remote localhost:3333
连上之后,我习惯先做几件事验证:
monitor reset halt—— 复位并暂停CPUinfo registers—— 看看寄存器值是不是预期的复位值load—— 把固件下载到Flash
如果info registers出来全是0xFFFFFFFF或者0x00000000,那八成是硬件连接有问题。别急着怀疑OpenOCD配置,先拿万用表量量JTAG/SWD的引脚电平。
reset halt 的瞬间松手。我管这叫「盲连大法」。
3. 调试脚本编写——把重复劳动自动化
每次调试都敲一遍target remote、monitor reset halt、load,你不烦吗?反正我烦了。所以,写个GDB脚本吧。
一个典型的调试脚本长这样:
# debug.gdb
target remote localhost:3333
monitor reset halt
monitor flash write_image erase your_firmware.elf
load
break main
continue
启动时直接:
arm-none-eabi-gdb -x debug.gdb your_firmware.elf
一键连上、下载、停在main函数入口。省心。
我个人还喜欢在脚本里加一些「调试辅助函数」。比如:
define dump_stack
info registers sp
x/32wx $sp
end
document dump_stack
打印当前栈顶的32个字
end
这样在调试现场,敲个dump_stack就能看栈回溯,不用每次都敲一长串命令。
4. 硬件连接验证——别让物理层坑了你
软件配得再好,硬件没连对,一切都是白搭。我见过太多人花一整天调OpenOCD,最后发现是杜邦线松了。
JTAG最少需要4根线:
| 信号 | 说明 | 常见坑点 |
|---|---|---|
| TMS | 模式选择 | 上拉电阻没接,浮空导致状态机跑飞 |
| TCK | 时钟 | 线太长(>20cm)信号反射,降速可解 |
| TDI | 数据输入 | 与TDO接反,数据流不通 |
| TDO | 数据输出 | 同上,接反了OpenOCD会报invalid IDCODE |
我的验证流程是这样的:
- 目测:检查排线有没有插反、插歪、插错孔位
- 万用表测通断:调试器端的TMS是不是真的连到了芯片的TMS引脚
- 测电平:TCK上有没有时钟?TMS在复位后是不是高电平?
- 跑OpenOCD:看能不能读到IDCODE
如果OpenOCD报JTAG scan chain interrogation failed,别慌。先检查transport select是不是选对了——JTAG和SWD是两种协议,别混用。
transport select swd。嗯,有时候问题就这么简单,但你就是想不到。
知识结构总览
下面这张图,把整个工具链的搭建流程串起来了。你可以把它当作一张「调试工具链搭建检查清单」来用。
这张图从左到右、从上到下,就是完整的搭建顺序。我个人建议你按这个顺序来,别跳步。硬件没验证就配OpenOCD,出了问题你都不知道是硬件还是软件的问题。