PAYATHON 2026

OpenOCD Raspberry pi Bit Bang SWD 无法连接 DP 并读取 IDR

排障赵师傅

结论

USB device firmware 通常不会直接导致 SW-DP 消失。STM32F407 的 USB FS 使用 PA11/PA12,SWD 使用 PA13/PA14。OpenOCD 读取调试端口的 DPIDR 时,Flash 中的应用代码还没有执行。

ST-Link 可以正常连接,但 mass erase 后 Raspberry Pi GPIO Bit Bang 仍然读不到 DP,问题更可能出在 Raspberry Pi 端,包括 SWD 时序、GPIO 方向切换、复位控制和信号完整性。Wrong Parity Error 也符合这类故障的特征:OpenOCD 收到了响应,但采样的数据位或校验位有误。

有一种情况需要单独考虑。如果程序启动后立即重配置 PA13/PA14、进入低功耗模式或关闭调试功能,普通 attach 可能失败,通常可以通过 connect-under-reset 连接。整片擦除后如果故障依旧,应先检查 Bit Bang 接口。

ST-Link 内部有专用调试硬件,可以可靠处理 SWDIO 双向切换、turnaround 周期、复位时序和信号采样。Raspberry Pi GPIO Bit Bang 依靠软件控制 GPIO,更容易受以下问题影响:

  • SWCLK 频率过高,目标端或 Raspberry Pi 无法稳定采样。
  • SWDIO 在读写切换时未及时释放,导致主机和目标同时驱动总线。
  • OpenOCD、Linux 内核或 Raspberry Pi 型号变化后,原来的 GPIO 时序参数不再适用。
  • reset_config 与实际的 NRST 接线不匹配。
  • SWDIO、SWCLK 没有合适的上拉或下拉,空闲电平不稳定。
  • 线缆过长、接地不良、供电噪声,或者接入 USB 后地电位发生变化。
  • Raspberry Pi GPIO 电平超出允许范围。GPIO 只能使用 3.3 V 逻辑,不能承受 5 V。
  • SWDIO 引脚编号、GPIO 模式或 peripheral base 配置不适用于当前 Raspberry Pi 型号。
  • 后台进程、内核驱动或 GPIO overlay 占用了相同的 GPIO。

mass erase 只能清除 MCU Flash,无法解决这些接口层问题。

先降低 SWD 时钟

排查 Bit Bang SWD 时,先降低 adapter speed。可用范围取决于 OpenOCD 版本和 Raspberry Pi GPIO driver,配置值不一定等于实际的 SWCLK 频率。

先从较低的值开始测试:

transport select swd
adapter speed 50

如果仍然失败,再继续降低:

adapter speed 10

启动命令可以参考下面的示例,其中接口配置文件需要替换为当前实际使用的文件:

openocd \
  -d3 \
  -f interface/raspberrypi-native.cfg \
  -c "transport select swd" \
  -c "adapter speed 50" \
  -f target/stm32f4x.cfg

部分 OpenOCD 版本已经修改了 Raspberry Pi GPIO driver 的名称和参数。如果配置文件来自较早的安装版本,应与当前版本附带的 interface/ 配置核对,重点检查 GPIO 编号、Raspberry Pi 型号和速度校准参数。

使用 connect-under-reset

如果 USB 固件启动后修改了 SWD 引脚、时钟或低功耗状态,应在 MCU 执行用户代码前保持 NRST 有效。

这种方式要求 Raspberry Pi 已经连接 STM32 的 NRST:

reset_config srst_only srst_nogate connect_assert_srst

然后尝试运行:

openocd \
  -d3 \
  -f interface/raspberrypi-native.cfg \
  -c "transport select swd" \
  -c "adapter speed 50" \
  -c "reset_config srst_only srst_nogate connect_assert_srst" \
  -f target/stm32f4x.cfg \
  -c "init; reset halt"

没有连接 NRST 时,无法使用依赖硬件复位的连接方式。可以手动拉低 NRST,启动 OpenOCD 后再释放 NRST,以此判断用户程序是否抢占了 SWD 引脚。

整片擦除后,MCU 中已经没有可执行的用户程序。此时如果 Raspberry Pi 仍然读不到 DP,而 ST-Link 可以正常连接,基本可以排除 USB firmware。

检查 SWDIO 双向切换

SWDIO 是双向信号。主机发出请求后,要在 turnaround 周期释放 SWDIO,再由目标返回 ACK 和数据。如果 GPIO Bit Bang driver 释放过晚、读取过早或 GPIO 方向配置错误,可能出现以下报错或现象:

  • Error connecting DP
  • cannot read IDR
  • Wrong ACK
  • Wrong Parity Error
  • 读取结果全为 0 或全为 1

Wrong Parity Error 表示收到的 32 位数据与 parity bit 不匹配,与 STM32 Flash 内容是否损坏无关。常见原因包括信号边沿不干净、采样时刻错误,以及 turnaround 期间的总线争用。

如果手边有逻辑分析仪或示波器,可以同时观察 SWCLK、SWDIO 和 NRST,检查以下内容:

  1. SWD line reset 是否发送了至少 50 个 SWCLK 周期的高电平。
  2. JTAG-to-SWD sequence 是否完整。
  3. 请求包发送后,Raspberry Pi 是否及时释放 SWDIO。
  4. 目标返回的 ACK 是否为 001,也就是 SWD 协议定义的 OK。
  5. 数据阶段是否有毛刺、缓慢边沿或两个器件同时驱动造成的中间电平。

不要只根据普通逻辑分析仪的协议解码结果下结论。采样率不够时,分析仪本身也可能漏掉毛刺。

重新检查硬件连接

导线没有断路,不代表信号质量一定正常。可以按照下面的最小连接重新测试:

Raspberry Pi        STM32F407
------------        ---------
GND             ->  GND
GPIO for SWCLK  ->  PA14 / SWCLK
GPIO for SWDIO  <-> PA13 / SWDIO
GPIO for NRST   ->  NRST        (推荐)
3.3 V sense     ->  VDD         (仅在接口设计需要时)

同时检查以下事项:

  • Raspberry Pi 和目标板必须共地。
  • SWDIO、SWCLK 导线应尽量短,避免使用接触不良的杜邦线。
  • 不要将 Raspberry Pi GPIO 直接接到 5 V 信号。
  • 确认 Raspberry Pi 和 STM32 没有同时向对方供电。
  • 检查接入 USB 数据线后,是否形成了第二条地线或供电回路。
  • 测量目标板的 3.3 V,确认连接 USB 后没有明显的电压跌落或纹波。
  • 确认没有外设占用 PA13/PA14,外部电路也没有强拉这两个引脚。

可以尝试给 SWDIO 增加弱上拉,但阻值需要结合现有板级电路确定。电阻过小会强拉 SWDIO,增加目标返回数据时的负载。

核对 Raspberry Pi GPIO 配置

先确认配置文件使用的是 BCM GPIO 编号还是物理排针编号。两者混用时,可能偶尔能收到响应,但数据并不可靠。

旧式配置可能包含类似内容:

adapter driver bcm2835gpio
bcm2835gpio swd_nums <SWCLK_GPIO> <SWDIO_GPIO>

占位符需要替换为实际的 BCM GPIO 编号:

bcm2835gpio swd_nums 25 24

这里的 25 和 24 只是语法示例,不表示当前接线应该使用这两个 GPIO。不同 OpenOCD 版本对 Raspberry Pi GPIO driver、参数名称和 Raspberry Pi SoC 地址的处理可能不同,应以本机安装版本附带的配置文件为准。

还要检查 GPIO 是否被其他功能占用:

gpioinfo

如果系统没有安装提供 gpioinfo 的工具,可以检查设备树 overlay,以及 SPI、I2C、UART、PWM 和其他 GPIO 服务是否占用了相同引脚。

获取有效的 OpenOCD 调试日志

以较高的日志级别运行 OpenOCD:

openocd \
  -d3 \
  -f interface/raspberrypi-native.cfg \
  -c "transport select swd" \
  -c "adapter speed 50" \
  -f target/stm32f4x.cfg

排查时记录以下信息:

  • OpenOCD 的完整版本号和构建来源。
  • Raspberry Pi 型号及操作系统版本。
  • 当前使用的 interface 配置文件。
  • SWCLK、SWDIO、NRST 对应的 BCM GPIO 编号。
  • adapter speed。
  • 接入 USB 前后的完整日志差异。
  • ST-Link 成功连接时是否使用了 under-reset 模式。

如果近期升级过 OpenOCD、操作系统或 Raspberry Pi 硬件,需要检查接口 driver 是否发生变化。即使应用固件也在同一时间修改过,时间上的先后关系仍不足以证明 USB firmware 是故障原因。

建议的排查顺序

  1. 用 ST-Link 确认 MCU、SWD 引脚和 option bytes 正常。
  2. 执行 mass erase,然后断电重启目标板。
  3. 暂时断开 USB,只保留电源、GND、SWCLK、SWDIO 和 NRST。
  4. 将 adapter speed 降到 50 或更低。
  5. 使用 connect-under-reset。
  6. 核对 BCM GPIO 编号和当前 OpenOCD 接口配置。
  7. 换用短线,并测量 SWCLK、SWDIO 和 3.3 V。
  8. 用示波器检查 SWDIO turnaround 和数据采样。
  9. 如果仍然失败,用相同接线测试另一块 STM32 板,或者用当前目标板测试另一台 Raspberry Pi,以区分目标板故障和主机接口故障。

从这些现象看,Wrong Parity Error 的诊断价值高于 USB 软件的影响。这个错误说明链路已经部分连通,但 Raspberry Pi Bit Bang 接口没有稳定接收到正确的 SWD 数据。应先降低速度,再检查 SWDIO 方向切换和复位时序,通常比反复擦除 Flash 更有效。

备注:内容仅供参考。