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 本身是明文传输,不过咱们在本地调试,安全问题不大。

注意:有些系统默认没装 Telnet 客户端。Windows 10/11 需要去「启用或关闭 Windows 功能」里勾上 Telnet 客户端。Linux 直接 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 的启动、连接和命令体系。你一看就明白各个部分是怎么串起来的。

OpenOCD 命令行交互体系 OpenOCD 命令行交互体系 启动 OpenOCD 后台服务:Telnet (4444) | GDB (3333) | TCL (6666) Telnet 连接:telnet localhost 4444 GDB 连接:target remote :3333 目标控制 内存/寄存器 Flash 操作 其他实用 halt / resume reset / step mdw / mww reg / bp flash banks / info write_image / erase targets / poll adapter speed 启动 → 连接 → 交互,三步走通 OpenOCD

3.5 实战小技巧:快速验证连接

每次连上新板子,我第一件事就是跑下面这几条命令,确认 OpenOCD 和目标板通信正常:

  1. 启动 OpenOCD,看有没有报错
  2. Telnet 连上去,敲 halt 看能不能停住 CPU
  3. 读 PC 寄存器:reg pc,看看地址是不是在 Flash 范围内
  4. 读一段内存:mdw 0x08000000 4,确认能读到数据
  5. 复位:reset halt,看芯片能不能正常复位

这五步走完,基本可以确定硬件连接和 OpenOCD 配置都没问题。我每次换板子都这么干,从来没失手过。

我的经验:如果你发现 halt 命令卡住或者超时,八成是 SWD 信号线有问题。先检查接线,再检查目标板供电,最后才怀疑 OpenOCD 配置。顺序别搞反了。