设备挂机异常后,用 pyOCD 与 Cortex-Debug 保留 MCU 现场

设备已经异常时,先保持供电。不要复位、重新烧录,也不要启动平时的 Launch 下载调试。下面这份配置会把 MCU 原地暂停,让 VS Code 显示它卡住时所在的代码、调用过程和变量。

Cortex-Debug 现场连接配置

先把下面配置加入 .vscode/launch.jsonMCU 现场检查name 字段创建的自定义名称,添加后才会出现在 VS Code 的“运行和调试”列表中。

{
  "name": "MCU 现场检查",
  "type": "cortex-debug",
  "request": "attach",
  "servertype": "pyocd",
  "targetId": "TARGET_ID",
  "executable": "${workspaceFolder}/build/firmware.elf",
  "serverArgs": [
    "-O",
    "connect_mode=halt"
  ],
  "overrideGDBServerStartedRegex": "GDB server listening on port"
}

targetIdexecutable 直接沿用已经可以正常调试的工程配置。原配置中已有 cmsisPacksvdFile,把对应行原样复制进来。

不要复制 Reset、Run to main、GDB load 或烧录任务。这些动作会改变需要检查的现场。

终端已经显示 GDB server listening on port,VS Code 仍报启动超时时,保留配置里的 overrideGDBServerStartedRegex。它让 Cortex-Debug 认出 pyOCD 已经启动,增加等待时间没有用。

设备异常后的四个动作

  1. 保持设备当前供电,不按复位键,不重新烧录固件。
  2. 连接调试器的 SWDIO、SWCLK 和 GND。SWD 是 Cortex-M 芯片常用的调试接口。
  3. 打开 VS Code,在“运行和调试”中选择已经添加的 MCU 现场检查
  4. 启动调试,看到源码停住后立即截图或记录,暂时不要按“继续运行”。

终端出现 GDB server listening on port 表示 pyOCD 已经开始监听。VS Code 随后应停在当前代码位置,不会重新运行到 main

ELF 与调用栈的对应关系

executable 必须指向设备当前固件同一次构建产生的 ELF 文件。ELF 在现场连接中只负责把地址翻译成函数、源码和变量,不负责下载固件。

调试器暂停后,按这个顺序记录:

  1. 查看当前源码行,确认 CPU 停在什么函数。
  2. 展开 Call Stack,记录程序经过哪些函数到达当前位置。
  3. 查看 Variables 和已有的 Watch,记录与异常状态直接相关的值。

本地 ELF 与设备固件不对应时,函数名、源码行和变量都可能显示错误。先保存信息,再决定是否单步或继续运行。

现场连接的失效边界

以下情况已经无法保留原始现场:

这套方法保留的是调试器连接那一刻的状态,无法回到更早的故障瞬间。正式挂机前,先在正常设备上启动一次 MCU 现场检查,确认芯片会原地暂停且没有重新进入启动流程,再把这项配置留在工程中。