文档
OpenOCD 调试实战手册
本章目标
深入掌握 OpenOCD 的调试技巧:硬件断点、条件断点、RTOS 感知调试、Flash 操作。
1. OpenOCD 架构理解
GDB Client ──TCP:3333──> OpenOCD Server ──USB──> 调试探针 ──SWD/JTAG──> MCU
│
Telnet :4444 (控制台)
OpenOCD 的核心角色是 协议转换器:将 GDB Remote Serial Protocol 翻译为调试探针的底层命令。
2. 硬件断点 vs 软件断点
| 类型 | 实现 | 数量限制 | 适用 |
|---|---|---|---|
| 硬件断点 | 调试寄存器 (FPB) | 4-8 个 | Flash/ROM 中的代码 |
| 软件断点 | 替换指令为 BKPT | 不限 | RAM 中的代码 |
# 硬件断点(默认 Flash 中使用)
(gdb) hbreak main
(gdb) hbreak *0x08000420
# 软件断点
(gdb) break function_name
# 条件断点(硬件断点支持条件)
(gdb) break main.c:42 if count > 100
3. 内存与寄存器查看
# 查看寄存器
(gdb) info registers
(gdb) print/x $sp
(gdb) print/x $pc
# 内存 dump
(gdb) x/16xw 0x20000000 # 16 个 32-bit words(SRAM 起始)
(gdb) x/32xb 0x08000000 # 32 字节(Flash 起始 = 向量表)
# 内存写入
(gdb) set {int}0x20000010 = 0x12345678
# 对比 Flash 内容与固件
(gdb) monitor flash read_bank 0 /tmp/flash.bin 0 0x10000
4. RTOS 感知调试
# FreeRTOS 线程列表
(gdb) info threads
# 切换线程
(gdb) thread 3
(gdb) backtrace
# OpenOCD 需要加载 FreeRTOS 支持
openocd -f interface/stlink.cfg \
-f target/stm32f4x.cfg \
-c "rtos FreeRTOS"
5. 复杂调试场景
硬故障(HardFault)分析
# 发生 HardFault 后
(gdb) monitor reset halt
# 查看故障寄存器
(gdb) x/1xw 0xE000ED2C # CFSR (Configurable Fault Status Register)
(gdb) x/1xw 0xE000ED28 # HFSR (HardFault Status Register)
(gdb) x/1xw 0xE000ED34 # MMFAR / BFAR
# 从栈帧恢复调用现场
(gdb) x/8xw $sp # 查看压栈的寄存器
# R0, R1, R2, R3, R12, LR, PC, xPSR
外设寄存器实时监控
# Telnet 4444 控制台
> mdw 0x40021000 16 # 读 RCC 寄存器
> mdw 0x40020000 16 # 读 GPIOA 寄存器
> mww 0x40020014 0xFFFF # 设置 GPIOA ODR
6. 与 IDE 集成
// VSCode launch.json (Cortex-Debug 插件)
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"cwd": "${workspaceRoot}",
"executable": "./build/firmware.elf",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"svdFile": "./STM32F407.svd" // 外设寄存器视图
}
思考题
- 为什么 Flash 中的代码只能用硬件断点?
- HardFault 发生后如何从栈帧定位出错的代码行?
- RTOS 感知调试依赖什么机制获取线程列表?