本帖最后由 创天蓝 于 2026-7-28 14:05 编辑
用 pyOCD 与 Cortex-Debug 在挂机异常后连接 MCU 查看现场几十台产品需要长期挂机,异常可能数小时或数天后出现。每台一直挂调试器不现实,启动调试还可能复位目标。设备平时独立运行,出现停转、卡死或状态异常后,再通过 SWD 暂停 MCU 查看现场。
Reset 与现场边界常规 Launch 调试会让程序从复位入口重新开始: - Reset -> Reset_Handler -> SystemInit -> main
复制代码现场连接需要保留当前执行位置: - 异常位置 -> SWD 连接 -> Debug Halt -> 读取 CPU 状态
复制代码一旦执行 Reset,PC、SP、调用栈和外设状态都会发生变化,故障现场也随之改变。
目标中的固件与本地 ELF 必须来自同一次构建。executable 只用于加载 ELF 符号,把地址映射到函数、源码和变量;现场调试不要执行 GDB 的 load 命令。load 会进入 Flash 编程流程,可能执行擦除、写入或复位,直接改变现场。ELF 与设备固件不一致时,调用栈和变量显示可能失真。
这套方法保存的是“调试器暂停 MCU 那一刻”的状态。若看门狗已经复位设备,或程序继续运行并覆盖了故障栈,原始现场无法靠延迟连接恢复。
Cortex-Debug Attach 配置Cortex-Debug 应使用 request: "attach"。它跳过 Launch 模式默认的下载和启动流程,不会主动把设备重新运行到 main。自定义 GDB 命令、启动脚本和 GDB Server 仍可能触发 Reset,使用前需要逐项检查。 - {
- "name": "MCU Attach (pyOCD)",
- "type": "cortex-debug",
- "request": "attach",
- "cwd": "${workspaceFolder}",
- "servertype": "pyocd",
- "targetId": "TARGET_ID",
- "executable": "./build/firmware.elf",
- "cmsisPack": "./pack/Vendor.Device.pack",
- "svdFile": "./svd/device.svd",
- "serverArgs": [
- "-O",
- "connect_mode=attach"
- ],
- "overrideGDBServerStartedRegex": "GDB server listening on port"
- }
复制代码当前版本的 Cortex-Debug 无法识别新版 pyOCD 的启动输出,需要用 overrideGDBServerStartedRegex 指定成功日志。否则 pyOCD 已监听端口,Cortex-Debug 仍可能停在等待启动。
异常出现后,在 VS Code 中启动这项配置。connect_mode=attach 只控制 pyOCD 初始化阶段,此时 pyOCD 不主动暂停 CPU。
本机 pyOCD 0.44.1 会在 GDB 接入时调用 halt(),所以此版本冻结点位于 GDB 连接阶段;其他版本请以启动日志为准。
Attach 与 Halt 的冻结时机状态仍在快速变化时,等待 GDB 完成连接可能太晚。把连接模式改成 halt,pyOCD 会在 GDB Server 初始化期间暂停内核。 - "serverArgs": [
- "-O",
- "connect_mode=halt"
- ],
- "overrideGDBServerStartedRegex": "GDB server listening on port"
复制代码暂停由 Cortex-M 调试硬件完成,CPU 无需运行到某个暂停函数。概念链路如下: - SWD -> DAP -> DHCSR.C_HALT -> CPU 停止
复制代码两种模式都配合 Cortex-Debug 的 request: "attach" 使用:
| pyOCD 模式 | 暂停时机 | 使用场景 | | attach | GDB 客户端接入时 | 状态稳定 | | halt | pyOCD 连接目标时 | 状态变化快 |
独立 GDB Server 提前冻结需要先冻结、后打开 VS Code 时,可以运行一次性脚本。它用 halt 启动 pyOCD GDB Server,冻结 MCU 后等待 GDB 接入。 - @echo off
- pyocd gdbserver --pack .\pack\Vendor.Device.pack -t TARGET_ID -O connect_mode=halt
- pause
复制代码VS Code 使用外部 GDB Server,并继续采用 request: "attach": - {
- "name": "MCU External Attach",
- "type": "cortex-debug",
- "request": "attach",
- "servertype": "external",
- "gdbTarget": "localhost:3333",
- "executable": "./build/firmware.elf",
- "svdFile": "./svd/device.svd"
- }
复制代码脚本只启动一次。参数错误或 GDB Server 退出后,pause 会保留错误信息,避免快速重复启动 pyOCD。
几十台设备可以继续独立挂机,调试探针只接到发生异常的设备上。halt 负责尽早冻结,Cortex-Debug 负责把寄存器、源码和变量组织成可读现场。
build 28 July 2026 14:03 (UTC+8)
|