OpenOCD 进阶:Flash 编程与批量烧录脚本
目标
掌握 OpenOCD 的 Flash 分区操作、选项字节编程、多设备并行烧录和自动化脚本。
一、Flash 分区擦写
读取 Flash 内容
# read_flash.tcl
set FLASH_START 0x08000000
set FLASH_SIZE 0x00100000 ; # 1MB (STM32F407)
halt
flash read_bank 0 flash_dump.bin 0 $FLASH_SIZE
puts "Flash 已导出到 flash_dump.bin ($FLASH_SIZE bytes)"
resume
exit
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -f read_flash.tcl
解锁/锁定 Flash
# unlock.tcl
halt
stm32f4x unlock 0 ; # 解锁 bank 0
puts "Flash 解锁成功"
resume
exit
选项字节编程(读写保护)
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg \
-c "init" \
-c "halt" \
-c "stm32f4x lock 0" \
-c "reset run" \
-c "exit"
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg \
-c "init" \
-c "halt" \
-c "stm32f4x options_read 0" \
-c "exit"
二、批量烧录自动化脚本
INTERFACE="interface/stlink.cfg"
TARGET="target/stm32f4x.cfg"
FIRMWARE="build/firmware.hex"
SERIAL_FILE="devices.txt"
LOG_DIR="logs/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$LOG_DIR"
flash_device() {
local serial=$1
local log="$LOG_DIR/${serial}.log"
echo "────────────────────────────"
echo "烧录设备: $serial"
echo "────────────────────────────"
openocd \
-f "$INTERFACE" \
-c "hla_serial $serial" \
-f "$TARGET" \
-c "init" \
-c "halt" \
-c "flash write_image erase $FIRMWARE" \
-c "verify_image $FIRMWARE" \
-c "reset run" \
-c "exit" \
&
if [ $? -eq 0 ]
echo "✅ $serial — 成功"
else
echo "❌ $serial — 失败!查看日志: $log"
return 1
fi
}
TOTAL=0
SUCCESS=0
while IFS= read -r serial || [ -n "$serial" ]
[ -z "$serial" ] &
TOTAL=$((TOTAL + 1))
if flash_device "$serial"
SUCCESS=$((SUCCESS + 1))
fi
done <
echo ""
echo "===================================="
echo "烧录完成: $SUCCESS / $TOTAL"
echo "日志目录: $LOG_DIR"
echo "===================================="
三、结合 CMake 构建后自动烧录
# CMakeLists.txt 末尾添加烧录目标
add_custom_target(flash
COMMAND openocd
-f ${OPENOCD_SCRIPTS}/interface/stlink.cfg
-f ${OPENOCD_SCRIPTS}/target/stm32f4x.cfg
-c "program $<TARGET_FILE:${PROJECT_NAME}> verify reset exit"
DEPENDS ${PROJECT_NAME}
COMMENT "Flashing firmware..."
)
# 使用
# cmake --build . --target flash
四、多核调试(CM4 + CM0 异构系统)
openocd -f interface/stlink.cfg -f target/stm32h7x_dual_bank.cfg
arm-none-eabi-gdb cm7_firmware.elf
(gdb) target extended-remote localhost:3333
arm-none-eabi-gdb cm4_firmware.elf
(gdb) target extended-remote localhost:3334
五、实用 TCL 函数库
# utils.tcl — 可复用的 OpenOCD 辅助函数
proc wait_halt {timeout_ms} {
set start [clock milliseconds]
while {[expr {[clock milliseconds] - $start}] < $timeout_ms} {
if {[capture "halted"] == ""} {
sleep 10
} else {
return 1
}
}
error "等待暂停超时"
}
proc dump_regs {} {
set regs {r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc xPSR}
foreach r $regs {
puts [format "%-6s: 0x%08X" $r [reg $r]]
}
}
proc flash_erase_all {} {
flash erase_sector 0 0 last
puts "Flash 已全部擦除"
}
在启动时加载:
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -f utils.tcl
关键点
verify_image 烧录后自动校验,确保数据完整性
hla_serial 用于多 ST-Link 并行烧录时区分设备
- 选项字节操作需谨慎:错误的写保护设置可能导致芯片"变砖"
- TCL 脚本支持条件、循环,可实现复杂自动化流程
OpenOCD:命令行烧录与 GDB 调试 STM32
目标
使用 OpenOCD + arm-none-eabi-gdb 通过 ST-Link 对 STM32F4 进行命令行烧录和源码级调试。
硬件
- STM32 Nucleo-F407ZG 开发板(内置 ST-Link/v2-1)
- 或任意 STM32 + ST-Link 连接
一、烧录固件
1. 启动 OpenOCD Server
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
成功输出:
Info : STLINK V2J37M26 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.249107
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
2. 通过 Telnet 烧录
新开终端:
telnet localhost 4444
>
>
>
>
3. 一行命令烧录(无需 Telnet)
openocd -f interface/stlink.cfg \
-f target/stm32f4x.cfg \
-c "program firmware.elf verify reset exit"
| 参数 |
含义 |
program |
烧录命令 |
verify |
烧录后校验 |
reset |
烧录后复位 |
exit |
完成后退出 OpenOCD |
二、GDB 源码调试
1. 启动 OpenOCD(后台)
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg &
2. 启动 GDB 连接
arm-none-eabi-gdb firmware.elf
(gdb) target extended-remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) break main
(gdb) continue
(gdb) step
(gdb) print variable_name
(gdb) info registers
(gdb) x/10xw 0x20000000
(gdb) monitor reset run
(gdb) quit
3. 一键调试脚本
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg &
OOCD_PID=$!
sleep 1
arm-none-eabi-gdb -ex "target extended-remote localhost:3333" \
-ex "monitor reset halt" \
-ex "load" \
-ex "break main" \
-ex "continue" \
"$@"
kill $OOCD_PID 2>
常见 GDB 命令速查
| 命令 |
作用 |
monitor reset halt |
复位 MCU 并暂停 |
monitor flash write_image erase file.bin 0x08000000 |
烧录 .bin |
break function_name |
函数断点 |
break *0x08001234 |
地址断点 |
watch variable |
变量修改时中断 |
backtrace |
调用栈 |
layout src |
源码窗口 |
Ctrl+X A |
退出 TUI 模式 |
关键点
localhost:3333 = GDB Server,:4444 = Telnet 控制台
- ST-Link/v2 最大 SWD 频率约 4MHz,可用
-c "adapter speed 4000" 设置
- 如果
load 失败,先 monitor reset init 再试