4. 配置文件基础:OpenOCD 配置文件结构、接口配置、目标配置、板级配置
OpenOCD 的配置文件,说白了就是告诉调试器三件事:用什么硬件连、连什么芯片、板子上怎么接的。我刚开始接触 OpenOCD 时,总觉得配置文件又长又乱,后来拆开看才发现,其实就三个层次。
核心思想:OpenOCD 的配置采用分层设计——接口层(interface)→ 目标层(target)→ 板级层(board)。每一层只关心自己的事,互不干扰。
4.1 接口配置(interface)
接口配置,就是告诉 OpenOCD 你手里拿的是什么调试器。我个人习惯把接口配置单独写成一个 .cfg 文件,方便复用。
举个例子,我用 J-Link 调试 STM32 时,接口配置长这样:
# interface/jlink.cfg
interface jlink
transport select swd
adapter speed 4000
这里有三行,每行都有讲究:
- interface jlink:指定调试器类型。OpenOCD 支持的调试器很多,J-Link、ST-Link、FTDI、CMSIS-DAP 都有对应的驱动。
- transport select swd:选择传输协议。ARM 芯片常用 SWD(两线)或 JTAG(四线)。我建议能用 SWD 就用 SWD,省引脚,速度快。
- adapter speed 4000:设置 SWD 时钟频率,单位 kHz。4000 就是 4MHz。不是越高越好,线长了容易出错。
小技巧:调试高频芯片时,如果遇到连接不稳定,先把 adapter speed 降到 1000(1MHz)试试。我在调试某款国产 ARM 芯片时,默认 4MHz 死活连不上,降到 1MHz 就稳了。
其他常见调试器的接口配置:
| 调试器 | 接口配置示例 | 说明 |
|---|---|---|
| ST-Link | interface hla; hla_layout stlink; hla_device_desc "ST-Link/V2-1" |
ST-Link 使用 hla(High Level Adapter)驱动 |
| FTDI | interface ftdi; ftdi_vid_pid 0x0403 0x6010 |
需要指定 VID/PID,常见于自制调试器 |
| CMSIS-DAP | interface cmsis-dap; transport select swd |
很多开发板自带的调试器都用这个 |
4.2 目标配置(target)
目标配置,就是告诉 OpenOCD 你要烧录的芯片是什么内核、多少 Flash、多少 RAM。这部分我建议直接从 OpenOCD 的 target 目录里复制现成的,别自己手写。
以 STM32F407 为例,OpenOCD 自带的配置是这样的:
# target/stm32f4x.cfg
set CHIPNAME stm32f4x
set ENDIAN little
source [find target/armv7m.cfg]
# 工作区 RAM 地址和大小
set WORKAREASIZE 0x10000
# Flash 配置
flash bank bank1 stm32f2x 0x08000000 0x00100000 0 0 0
关键点:
- source [find target/armv7m.cfg]:先加载 ARM Cortex-M 内核的通用配置。Cortex-M0、M3、M4、M7 都走这个文件。
- WORKAREASIZE:工作区大小,就是芯片 RAM 里给 OpenOCD 用的临时空间。太小了下载大固件会报错。
- flash bank:定义 Flash 的起始地址、大小和驱动。stm32f2x 这个驱动兼容 STM32F2/F4 系列。
注意:不同系列的芯片,flash bank 的驱动名不一样。比如 STM32F1 用 stm32f1x,STM32F7 用 stm32f7x。用错了会报 "unknown flash driver" 错误。我曾经在 STM32F103 上误用了 stm32f2x,折腾了半小时才发现。
4.3 板级配置(board)
板级配置,就是把接口和目标组合起来,再加上板子特有的设置。比如复位方式、时钟配置、额外的初始化脚本等。
一个典型的板级配置:
# board/stm32f4discovery.cfg
source [find interface/stlink-v2-1.cfg]
source [find target/stm32f4x.cfg]
# 复位配置
reset_config srst_only srst_nogate
# 板级初始化
init
targets
puts "STM32F4 Discovery 已连接"
这里做了三件事:
- source 接口配置:加载 ST-Link 的接口文件。
- source 目标配置:加载 STM32F4 的目标文件。
- reset_config:设置复位方式。srst_only 表示只用 SRST 复位,srst_nogate 表示不通过 JTAG 门控复位。
经验之谈:板级配置里最常见的坑就是复位配置。有些板子需要 srst_nogate,有些需要 trst_and_srst。我的做法是:先试 srst_only srst_nogate,不行再换 trst_and_srst。如果还不行,八成是硬件复位电路有问题。
4.4 配置文件的加载顺序
OpenOCD 加载配置文件的顺序是固定的:先接口,再目标,最后板级。但实际使用时,你可以在命令行里指定任意顺序,OpenOCD 会自动解析依赖。
常用的加载方式有两种:
| 方式 | 命令示例 | 适用场景 |
|---|---|---|
| 直接指定板级文件 | openocd -f board/stm32f4discovery.cfg |
官方支持的开发板,最省事 |
| 手动组合接口+目标 | openocd -f interface/jlink.cfg -f target/stm32f4x.cfg |
自制板或非标准板,灵活度高 |
我个人更推荐第二种方式。为什么?因为很多自制板没有现成的 board 文件,自己写一个又容易漏东西。直接组合接口和目标,再在命令行里加几条自定义命令,反而更可控。
4.5 自定义配置的避坑指南
写配置文件时,有几个坑我踩过,分享给你:
- 路径问题:source 时用 [find xxx.cfg],OpenOCD 会在安装目录的 scripts 文件夹里找。如果你把配置文件放在当前目录,用
source ./my.cfg。 - 变量覆盖:target 文件里经常用 set 定义变量(比如 CHIPNAME),如果你在 board 文件里重新 set 了同名变量,后面的会覆盖前面的。
- transport 冲突:接口层选了 SWD,目标层又选 JTAG,OpenOCD 会报错。transport 只能选一次,建议放在接口层。
- 速度别贪快:adapter speed 设太高,下载到一半就断连。我一般从 2000 开始试,稳定了再往上加。
调试小技巧:如果 OpenOCD 启动时报错,先加 -d 参数开启调试日志。比如 openocd -d -f interface/jlink.cfg -f target/stm32f4x.cfg。日志里会告诉你哪一行配置出了问题。
4.6 一个完整的实战例子
最后,给你看一个我实际项目里用过的配置组合。当时调试的是一块基于 STM32F407 的自制板,调试器是 J-Link。
接口文件:my_jlink.cfg
interface jlink
transport select swd
adapter speed 2000
目标文件:my_stm32f4.cfg
set CHIPNAME my_stm32f4
source [find target/stm32f4x.cfg]
启动命令:
openocd -f my_jlink.cfg -f my_stm32f4.cfg
就这么简单。启动后 OpenOCD 会输出连接信息,看到 "target state: halted" 就说明成功了。
总结一下:配置文件的核心就是分层——接口管硬件、目标管芯片、板级管组合。写的时候别贪多,能用现成的就别自己造。记住这三点,OpenOCD 的配置就没什么难的了。