设备挂机异常后,用 pyOCD 与 Cortex-Debug 保留 MCU 现场
设备已经异常时,先保持供电。不要复位、重新烧录,也不要启动平时的 Launch 下载调试。下面这份配置会把 MCU 原地暂停,让 VS Code 显示它卡住时所在的代码、调用过程和变量。
Cortex-Debug 现场连接配置
先把下面配置加入 .vscode/launch.json。MCU 现场检查 是 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"
}targetId 和 executable 直接沿用已经可以正常调试的工程配置。原配置中已有 cmsisPack 或 svdFile,把对应行原样复制进来。
name创建稍后要选择的自定义调试入口。request: "attach"连接现有程序,不执行 Launch 下载流程。connect_mode=halt让 pyOCD 连接目标时暂停 MCU,减少现场继续变化。
不要复制 Reset、Run to main、GDB load 或烧录任务。这些动作会改变需要检查的现场。
终端已经显示 GDB server listening on port,VS Code 仍报启动超时时,保留配置里的 overrideGDBServerStartedRegex。它让 Cortex-Debug 认出 pyOCD 已经启动,增加等待时间没有用。
设备异常后的四个动作
- 保持设备当前供电,不按复位键,不重新烧录固件。
- 连接调试器的 SWDIO、SWCLK 和 GND。SWD 是 Cortex-M 芯片常用的调试接口。
- 打开 VS Code,在“运行和调试”中选择已经添加的
MCU 现场检查。 - 启动调试,看到源码停住后立即截图或记录,暂时不要按“继续运行”。
终端出现 GDB server listening on port 表示 pyOCD 已经开始监听。VS Code 随后应停在当前代码位置,不会重新运行到 main。
ELF 与调用栈的对应关系
executable 必须指向设备当前固件同一次构建产生的 ELF 文件。ELF 在现场连接中只负责把地址翻译成函数、源码和变量,不负责下载固件。
调试器暂停后,按这个顺序记录:
- 查看当前源码行,确认 CPU 停在什么函数。
- 展开
Call Stack,记录程序经过哪些函数到达当前位置。 - 查看
Variables和已有的Watch,记录与异常状态直接相关的值。
本地 ELF 与设备固件不对应时,函数名、源码行和变量都可能显示错误。先保存信息,再决定是否单步或继续运行。
现场连接的失效边界
以下情况已经无法保留原始现场:
- 设备被断电、复位或重新烧录。
- 看门狗在连接调试器前已经复位 MCU。
- 程序继续运行并覆盖了故障时的栈和变量。
这套方法保留的是调试器连接那一刻的状态,无法回到更早的故障瞬间。正式挂机前,先在正常设备上启动一次 MCU 现场检查,确认芯片会原地暂停且没有重新进入启动流程,再把这项配置留在工程中。