3. OpenOCD 命令行基础:启动、连接与常用命令
好,我们正式开始动手了。这一章我带你过一遍 OpenOCD 最基础的操作——怎么把它跑起来,怎么跟它说话,以及那些你每天都会敲的命令。别小看这一步,我见过太多人卡在启动阶段,折腾半天连不上目标板,最后发现是配置文件写错了一个字符。
3.1 启动 OpenOCD:两种典型姿势
启动 OpenOCD 其实就一条命令,但参数怎么给,取决于你的调试器和目标芯片。我个人习惯把配置拆成接口配置和目标配置两个文件,这样复用起来方便。
3.1.1 基本启动命令
openocd -f interface/jlink.cfg -f target/stm32f4x.cfg
这条命令干了三件事:加载 J-Link 调试器驱动、加载 STM32F4 目标芯片配置、启动 OpenOCD 后台服务。启动成功后你会看到类似这样的输出:
Info : Listening on port 3333 for gdb connections
Info : Listening on port 4444 for telnet connections
Info : Listening on port 6666 for tcl connections
看到这三个端口号,说明 OpenOCD 已经准备好了。3333 给 GDB,4444 给 Telnet,6666 给 TCL 脚本。嗯,这三个端口你得记住,后面天天用。
openocd.cfg 文件,把接口和目标配置都写进去,然后直接敲 openocd 不带参数。省事,也不容易搞错。
3.1.2 常见调试器配置对照
| 调试器 | 接口配置文件 | 备注 |
|---|---|---|
| J-Link | interface/jlink.cfg |
SEGGER 官方调试器,稳定 |
| ST-Link/V2 | interface/stlink-v2.cfg |
STM32 开发板自带,便宜 |
| FTDI/FT2232 | interface/ftdi/xxx.cfg |
需要自己接线,灵活 |
| CMSIS-DAP | interface/cmsis-dap.cfg |
ARM 标准,跨平台好 |
我曾经在一个项目里用 FT2232 自己做了个调试器,结果接线图看反了,SWD 的 SWCLK 和 SWDIO 接反,折腾了俩小时才发现。你想想看,这种低级错误其实很容易犯——启动 OpenOCD 之前,先拿万用表量一下信号线,能省很多时间。
3.2 连接 OpenOCD:Telnet 与 GDB
OpenOCD 启动后,它就在后台等着了。怎么跟它交互?两种主流方式:Telnet 和 GDB。我平时调试用 GDB,快速验证寄存器或内存用 Telnet。
3.2.1 Telnet 连接
打开一个新终端,输入:
telnet localhost 4444
连接成功后你会看到 OpenOCD 的命令提示符 >。这时候就可以敲命令了。比如:
> halt
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000134 msp: 0x20001000
> reset
> flash banks
#0 : stm32f4x.flash (STM32F4xx) at 0x08000000, size 0x100000, buswidth 0, chipwidth 0
Telnet 的好处是轻量、响应快。我经常用它来快速检查芯片状态——比如看看 PC 跑到哪了,或者读个寄存器值。但要注意,Telnet 本身是明文传输,不过咱们在本地调试,安全问题不大。
apt install telnet 就行。
3.2.2 GDB 连接
GDB 连接更常用,尤其是你要单步调试、设断点的时候。启动 ARM 交叉编译版的 GDB:
arm-none-eabi-gdb your_firmware.elf
然后在 GDB 内部连接 OpenOCD:
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) continue
这里 monitor 命令很关键——它可以把 GDB 的命令透传给 OpenOCD。比如 monitor reset halt 就是让 OpenOCD 去复位芯片并停在复位向量处。我刚开始用的时候老忘记加 monitor,结果命令直接报错,后来才反应过来。
3.3 常用命令概览
OpenOCD 的命令不少,但常用的就那么十几个。我把它们分成四类,你记牢这些就够了。
3.3.1 目标控制命令
| 命令 | 作用 | 示例 |
|---|---|---|
halt |
暂停目标 CPU | halt |
resume |
恢复运行 | resume |
reset |
复位目标 | reset halt |
step |
单步执行 | step 10 |
3.3.2 内存与寄存器命令
| 命令 | 作用 | 示例 |
|---|---|---|
mdw |
读内存(32位) | mdw 0x08000000 16 |
mww |
写内存(32位) | mww 0x20000000 0xdeadbeef |
reg |
显示/设置寄存器 | reg pc |
bp |
设置断点 | bp 0x08000100 4 hw |
3.3.3 Flash 操作命令
| 命令 | 作用 | 示例 |
|---|---|---|
flash banks |
列出 Flash 设备 | flash banks |
flash info |
查看 Flash 信息 | flash info 0 |
flash write_image |
烧录固件 | flash write_image erase firmware.hex |
flash erase_sector |
擦除扇区 | flash erase_sector 0 0 3 |
3.3.4 其他实用命令
targets:列出所有目标,多核芯片会显示多个poll:开启/关闭轮询模式,调试时建议开启reset_config:配置复位方式(srst/trst)adapter speed:设置 SWD/JTAG 时钟频率
adapter speed 设得太高——板子走线长,信号质量差,降到 1MHz 就稳了。如果你遇到连接不稳定,先把速度降到 1MHz 试试。
3.4 知识结构图:OpenOCD 命令行交互体系
下面这张图帮你理清 OpenOCD 的启动、连接和命令体系。你一看就明白各个部分是怎么串起来的。
3.5 实战小技巧:快速验证连接
每次连上新板子,我第一件事就是跑下面这几条命令,确认 OpenOCD 和目标板通信正常:
- 启动 OpenOCD,看有没有报错
- Telnet 连上去,敲
halt看能不能停住 CPU - 读 PC 寄存器:
reg pc,看看地址是不是在 Flash 范围内 - 读一段内存:
mdw 0x08000000 4,确认能读到数据 - 复位:
reset halt,看芯片能不能正常复位
这五步走完,基本可以确定硬件连接和 OpenOCD 配置都没问题。我每次换板子都这么干,从来没失手过。
halt 命令卡住或者超时,八成是 SWD 信号线有问题。先检查接线,再检查目标板供电,最后才怀疑 OpenOCD 配置。顺序别搞反了。