用途
本技能用于指导代理完成 OpenOCD 的配置与使用,覆盖 JTAG 和 SWD 目标,包括:向微控制器烧录固件、连接 GDB 进行裸机调试、设置硬件观察点,以及配置 J-Link 和 CMSIS-DAP 适配器。
触发场景
- 如何用 OpenOCD 将 GDB 连接到 MCU
- 如何使用 OpenOCD 烧录固件
- 如何为 OpenOCD 设置 J-Link
- JTAG 与 SWD 有什么区别
- 如何在 GDB 中设置硬件观察点
- OpenOCD 报错 “Error: unable to find JTAG device” 如何修复
JTAG 与 SWD 对比
| 特性 | JTAG | SWD(Serial Wire Debug) |
|---|---|---|
| 引脚 | 4+(TCK、TMS、TDI、TDO、TRST) | 2(SWCLK、SWDIO) |
| 多目标 | 支持(菊花链) | 不支持(单目标) |
| 速度 | 最高 30 MHz | 最高 10 MHz |
| 可用性 | 完整 JTAG:Cortex-A/R、RISC-V | SWD:仅 Cortex-M |
| 线缆成本 | 更复杂 | 更简单的 2 线 |
大多数 Cortex-M 微控制器同时支持两者。引脚数量受限时使用 SWD。
OpenOCD 配置
# openocd.cfg — CMSIS-DAP (ST-Link v2, DAPLink)
source [find interface/cmsis-dap.cfg]
source [find target/stm32f4x.cfg]
adapter speed 4000 # kHz
# For SWD explicitly
transport select swd
# J-Link adapter
source [find interface/jlink.cfg]
jlink serial 123456789 # optional: select by serial
source [find target/nrf52.cfg]
adapter speed 8000
# Run OpenOCD (keeps running, serves GDB on port 3333)
openocd -f openocd.cfg
# Common interface config files
ls $(openocd --help 2>&1 | grep "scripts" | head -1)/interface/
# cmsis-dap.cfg, jlink.cfg, ftdi/olimex-arm-usb-ocd.cfg, stlink.cfg ...
# Common target config files
ls $(openocd --help 2>&1 | grep "scripts" | head -1)/target/
# stm32f4x.cfg, nrf52.cfg, esp32.cfg, rp2040.cfg, at91sam4s.cfg ...
连接 GDB
# In terminal 1: start OpenOCD
openocd -f openocd.cfg
# In terminal 2: start GDB
arm-none-eabi-gdb firmware.elf
# GDB commands
(gdb) target extended-remote :3333 # connect to OpenOCD
(gdb) monitor reset halt # reset and halt target
(gdb) load # flash ELF to target
(gdb) monitor reset init # re-initialize after flash
(gdb) break main # set software breakpoint
(gdb) continue
# One-liner for quick debugging
arm-none-eabi-gdb -ex "target extended-remote :3333" \
-ex "monitor reset halt" \
-ex "load" \
-ex "break main" \
-ex "continue" \
firmware.elf
烧录固件
# Flash via OpenOCD telnet interface
telnet localhost 4444
# OpenOCD telnet commands
> reset halt
> program firmware.elf verify reset
> exit
# Or via GDB
(gdb) monitor flash write_image erase firmware.bin 0x08000000
(gdb) monitor reset run
# Flash only (no debug) — script mode
openocd -f openocd.cfg \
-c "program firmware.elf verify reset exit"
# For raw binary
openocd -f openocd.cfg \
-c "program firmware.bin 0x08000000 verify reset exit"
硬件断点与观察点
软件断点(break)会用陷阱指令修补指令内存——在没有调试寄存器的情况下,无法在 flash 原地执行(execute-in-place)中工作。应改用硬件断点:
# Hardware breakpoint (uses debug register, limited count: 4-8 on Cortex-M)
(gdb) hbreak function_name
(gdb) hbreak *0x08001234
# Hardware watchpoint — triggers on memory read/write
(gdb) watch global_variable # write watchpoint
(gdb) rwatch some_buffer # read watchpoint
(gdb) awatch sensor_value # read OR write watchpoint
# List breakpoints/watchpoints
(gdb) info breakpoints
# Cortex-M typically has: 4–8 hardware breakpoints, 2–4 watchpoints
OpenOCD 命令参考
# Via telnet (port 4444) or GDB monitor
monitor reset halt # reset and hold at reset vector
monitor reset init # reset and run init scripts
monitor reset run # reset and run freely
monitor halt # halt running target
monitor resume # resume execution
monitor mdw 0x20000000 # memory display word at address
monitor mww 0x40021000 0x1 # memory write word
monitor reg r0 # read register
monitor arm disassemble 0x08000000 16 # disassemble 16 instructions
# Flash operations
monitor flash list
monitor flash erase_sector 0 0 0 # erase sector 0
monitor flash write_bank 0 firmware.bin 0
常见错误
| 错误 | 原因 | 修复 |
|---|---|---|
| unable to find JTAG device | 接口、线缆或供电错误 | 检查 USB 连接;给目标供电;验证接口配置 |
| JTAG scan chain interrogation failed | 目标配置错误或 SWD 模式错误 | 将配置与具体 MCU 匹配;尝试 transport select swd |
| flash 'stm32f4x' is not supported | 目标错误 | 检查 MCU 型号;使用正确的 .cfg |
| Error: timed out while waiting for target halted | 目标在运行,未暂停 | monitor halt;检查 BOOT 引脚 |
| Cannot access memory at address | MMU、内存保护或地址错误 | 检查 MPU 配置;使用正确的 flash/RAM 地址 |
| Warn: target not examined yet | OpenOCD 未连接到目标 | 检查供电与连接 |
J-Link 配置
# openocd.cfg for J-Link
source [find interface/jlink.cfg]
jlink usb 0 # use first J-Link found
transport select swd # or jtag
adapter speed 4000
source [find target/stm32l4x.cfg]
J-Link GDB Server(OpenOCD 的替代方案):
# Segger's own GDB server
JLinkGDBServer -if SWD -device STM32L476RG -port 3333 &
arm-none-eabi-gdb -ex "target remote :3333" firmware.elf
相关技能
- 使用 skills/embedded/freertos 进行 FreeRTOS 感知的 OpenOCD 调试
- 使用 skills/embedded/zephyr 进行 Zephyr 的 west debug 集成
- 使用 skills/debuggers/gdb 进行 GDB 会话管理
- 使用 skills/embedded/linker-scripts 理解 flash 地址的内存映射