一键导入
stm32-debug
STM32 debugging via serial log and ST-Link. Invoke when user encounters bugs, crashes, or unexpected behavior on STM32 and needs root cause analysis.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
STM32 debugging via serial log and ST-Link. Invoke when user encounters bugs, crashes, or unexpected behavior on STM32 and needs root cause analysis.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Initialize a ZMK keyboard firmware project. Invoke when user wants to create a new ZMK-based wireless/wired keyboard project, add a custom shield, or set up ZMK development environment.
Initialize a new nRF528xx development project. 自动侦测芯片型号,与用户交互确认硬件资源(GPIO/SPI/I2C/UART),选择编程语言,搭建 CMake 项目框架,完成编译烧录验证。Call after nrf-connect-sdk-setup is complete and the user wants to start a new project.
SOP for setting up nRF Connect SDK (Zephyr-based) development environment on macOS and Linux. 先检测已安装组件,仅安装缺失项。Installs and configures all required tools for Nordic nRF52/nRF53/nRF91 development.
nRF528xx 系列单片机开发入口 skill。自动索引子 skill 完成环境部署、项目初始化、调试排错全流程。当用户进行 nRF52/nRF52840/nRF52832 等芯片开发时调用。
STM32 系列单片机开发入口 skill。自动索引子 skill 完成环境部署、项目初始化、调试排错全流程。当用户进行 STM32 开发时调用。
STM32 开发环境安装。跨平台(Windows/macOS/Linux)支持,兼容 CubeIDE(路径A)和纯 CLI(路径B)两种方式。检测已有安装,仅安装缺失组件。Call first before any STM32 development.
| name | stm32-debug |
| description | STM32 debugging via serial log and ST-Link. Invoke when user encounters bugs, crashes, or unexpected behavior on STM32 and needs root cause analysis. |
跨平台支持:Windows / macOS / Linux。 调试手段:串口日志(首选) + ST-Link 寄存器/堆栈(备选/联用)。
环境准备 → 问题理解 → 代码研读 → [串口日志方式 | ST-Link 方式 | 二者联用] → 根因分析 → 报告输出 → 等待用户决策
AI 首次执行本 Skill 时,必须先检查 stm32-dev-setup skill 是否已存在。
AI 自行判断 stm32-dev-setup skill 是否已安装:
1. 在 skill 目录中搜索 stm32-dev-setup 相关文件
2. 如未找到,则从仓库获取
获取方式:
git clone https://github.com/kukucaiCndy/embedded_ai_skills.git /tmp/embedded_ai_skills
cp -r /tmp/embedded_ai_skills/stm32/stm32-dev-setup/* <当前环境的 skill 目录>/stm32-dev/
stm32-dev-setup skill 提供完整的工具链安装、工程编译、烧录流程。本 Skill 的编译/烧录步骤均复用 stm32-dev 的能力。
# 探测 ST-Link 并读取芯片信息
export PATH="/mingw64/bin:$PATH"
st-info --probe
| 结果 | 动作 |
|---|---|
Found 1 stlink programmers + 芯片信息 | ✅ 继续 |
Couldn't find any ST-Link | ❌ 告知用户检查连接 |
验证 ST-Link 可读写芯片:
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c "init" -c "halt" -c "reg" -c "resume" -c "shutdown" 2>&1
如能正常输出
r0~r15、pc、msp、psp、xPSR等寄存器,说明 ST-Link 调试通道正常。
本工具为安装包形式,需安装后才能使用。 工具配套 GUI 和 CLI 两种模式,使用前需先启动 GUI。
下载地址: https://github.com/kukucaiCndy/EmberinterTool/releases
| 步骤 | 操作 |
|---|---|
| 1. 下载安装包 | 从 Releases 页面下载最新安装包(.exe / .dmg / .deb) |
| 2. 运行安装程序 | 按安装向导完成安装,记下安装目录 |
| 3. 启动 GUI | 安装完成后先启动 GUI,确认工具正常运行 |
| 4. CLI 可用 | GUI 启动后,CLI 命令行接口才可用于脚本/自动化场景 |
AI 在使用串口工具前,必须先加载工具对应的 skill,掌握其命令行参数。
Skill 获取来源(按优先级):
1. 本地优先:从工具安装目录获取
常见路径:
Windows: C/D/E/F:\Program Files (x86)\EmberInterDebugTool\skill\
或自定义安装路径下的 skill\ 子目录
2. 线上备用:从 GitHub 仓库获取
https://github.com/kukucaiCndy/embedded_ai_skills/tree/master/tools/emberinter
AI 加载流程:
1. 先检查工具安装目录下的 skill\ 子目录是否存在
2. 如果存在,加载本地 skill 文件
3. 如果不存在,从 GitHub 仓库获取:
git clone https://github.com/kukucaiCndy/embedded_ai_skills.git /tmp/embedded_ai_skills
# skill 内容位于 /tmp/embedded_ai_skills/tools/emberinter/
4. 加载 skill 后,按照 skill 中的说明学习 CLI 参数
⚠️ 不要假设参数名。 必须通过 skill 中的说明确认后再使用。
AI 必须先理解问题全貌,再动手。核心理念:先诊断,后开药。
AI 向用户询问:
1. "请描述你遇到的问题现象(crash、输出异常、外设不工作等)?"
2. "问题是否稳定复现?还是偶发?"
3. "最近做了哪些代码修改?"
4. "设备当前状态:串口是否接入?硬件连接是否正常?"
AI 先阅读所有相关代码,建立完整调用链理解,再决定如何插入日志。
code/src/main.c 及主循环SysTick_Handler、各外设 ISRHAL_UART_MspInit、HAL_GPIO_EXTI_Callback 等SystemClock_Config、各 MX_xxx_InitAI 根据问题类型选择调试方案:
┌──────────────────────────────────────────────────────────────┐
│ 方案 A:串口日志调试(首选) │
│ 适用:设备能正常运行,串口可用 │
│ 优势:不暂停 CPU,适合时序敏感问题 │
│ │
│ 方案 B:ST-Link 调试 │
│ 适用:设备崩溃/死机/串口不可用 │
│ 优势:可读取崩溃瞬间的 CPU 状态 │
│ │
│ 方案 C:二者联用 │
│ 适用:复杂问题,需要日志 + 寄存器快照 │
│ 优势:双重证据交叉验证 │
└──────────────────────────────────────────────────────────────┘
AI 向用户报告选择的方案及理由,获得确认后继续。
使用前确保已按 2.3 节安装 EmberInterDebugTool 并启动 GUI。
AI 询问用户:
"请确认串口信息:COM 口号?(如 COM3)波特率?(如 115200)"
启动监听:
AI 按照 2.4 节加载的 skill 中的说明,使用 CLI 启动串口监听并保存日志。
⚠️ 实际参数名以 skill 中的说明为准。 上述流程为示例,AI 需先执行 2.4 节的加载流程后再组装命令。
AI 根据代码研读结果,在关键位置添加日志。日志格式要求:
printf("[DEBUG] [标签] 变量名 = 值\r\n");
// 例如:
printf("[DEBUG] [UART_TX] tx_count = %lu, tx_state = %d\r\n", tx_count, huart1.gState);
日志插入原则:
| 位置 | 日志内容 |
|---|---|
| 函数入口 | 函数名 + 关键参数值 |
| 函数出口 | 返回值 |
| 状态变化 | 旧值 → 新值 |
| 错误分支 | 错误码 + 上下文变量 |
| ISR 入口 | ISR 名 + 关键外设状态寄存器 |
| 关键循环 | 循环计数 + 关键变量 |
⚠️ 日志必须短小精悍。 在 ISR 中尤其不能打印过多字符,会影响时序。
# 记录烧录时间戳
echo "FLASH TIMESTAMP: $(date -Iseconds)" >> /tmp/serial_debug.log
# 编译 + 转换 + 烧录
export PATH="/mingw64/bin:$PATH"
cmake --build build
arm-none-eabi-objcopy -O binary build/${PROJECT_NAME}.elf build/${PROJECT_NAME}.bin
st-flash --reset write build/${PROJECT_NAME}.bin 0x08000000
复位设备后,串口工具持续监听。AI 分析烧录时间戳之后的日志:
当以下情况时使用 ST-Link 调试:
- 设备启动后立即 crash,串口无输出
- 设备运行一段时间后死机,串口停止输出
- HardFault 等内核异常
- 需要检查外设寄存器状态
export PATH="/mingw64/bin:$PATH"
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c "init" -c "halt" -c "reg" -c "resume" -c "shutdown" 2>&1
根据 PC、LR、MSP 重建调用链:
# 将 PC/LR 地址反汇编,定位到具体函数
arm-none-eabi-objdump -d build/${PROJECT_NAME}.elf | grep -A5 "<PC_VALUE>"
# 查看符号表确认函数名
arm-none-eabi-nm build/${PROJECT_NAME}.elf | sort | grep <ADDRESS>
# 从 MSP 处 dump 栈内容
st-flash read /tmp/stack_dump.bin <MSP_ADDRESS> 1024
xxd /tmp/stack_dump.bin
# 读取 GPIO 寄存器
st-flash read /tmp/gpioc_regs.bin 0x40011000 16
xxd /tmp/gpioc_regs.bin
# 读取 RCC 寄存器
st-flash read /tmp/rcc_regs.bin 0x40021000 64
xxd /tmp/rcc_regs.bin
# 读取 NVIC 寄存器
st-flash read /tmp/nvic_regs.bin 0xE000E100 256
xxd /tmp/nvic_regs.bin
外设寄存器基址参考芯片参考手册。常见 F103 寄存器:
RCC: 0x40021000 GPIOA: 0x40010800 GPIOB: 0x40010C00 GPIOC: 0x40011000 USART1:0x40013800 NVIC: 0xE000E100 SCB: 0xE000ED00
PC 所在函数作为出发点LR 确认调用来源串口日志发现问题 → ST-Link 暂停确认状态 → 交叉验证
具体步骤:
1. 先通过串口日志观察异常出现的时间点和模式
2. 在异常出现前后通过 ST-Link halt 获取 CPU 快照
3. 对比日志记录值和寄存器/内存实际值
4. 双源交叉验证,排除单源误导
AI 必须深入分析,不能停留在表象。
⚠️ crash 点 ≠ 根因
crash 发生在核心库/内核/驱动(如 HAL_Delay、SysTick_Handler、HardFault_Handler),
这往往是问题的最终表现,而不是根因。
真正的根因通常在用户代码侧:
- 对核心库的调用参数不正确
- 调用时序错误(如外设未初始化即使用)
- 配置遗漏(如缺少 __HAL_RCC_xxx_CLK_ENABLE)
- 缓冲区溢出(栈/堆越界破坏关键数据)
- 中断嵌套/优先级问题
- 超时设置不合理
| 检查项 | 排查方法 |
|---|---|
| 外设时钟是否使能 | 查 HAL_MspInit / MX_xxx_Init 中 __HAL_RCC_xxx_CLK_ENABLE() |
| GPIO 引脚配置是否正确 | 查 Mode、Pull、Alternate 配置 |
| hal_conf.h 模块是否启用 | 查对应 #define HAL_xxx_MODULE_ENABLED 是否去注释 |
| CMakeLists 是否链接 HAL 模块 | 查 target_link_libraries 中 HAL::STM32::{F}::xxx |
| ISR 是否存在 / 命名正确 | 查 ISR 函数名匹配启动文件中的向量表名 |
| SysTick 是否正确配置 | SysTick_Handler 中调用 HAL_IncTick() |
| 缓冲区大小是否足够 | snprintf / HAL_UART_Transmit 的 buffer 大小 |
| 栈是否溢出 | 检查 MSP 是否接近 SRAM 底部 |
| DMA 是否启用(UART/SPI 依赖) | hal_conf.h 启用 + CMakeLists 链接 |
| 外设初始化在 SystemClock_Config 之后 | 确保 MX_xxx_Init 在 SystemClock_Config() 之后调用 |
## 问题分析报告
### 1. 问题现象
- [用户描述的原始问题]
### 2. 调试方案
- 采用方案:[A / B / C]
- 理由:[说明为什么选择该方案]
### 3. 代码研读
- 相关文件:[列出文件路径]
- 关键函数调用链:[从 main → 问题点列出]
### 4. 调试数据
#### 串口日志(方案 A)
[粘贴关键日志片段并标注行号]
[标注异常数据点]
#### 寄存器快照(方案 B)
| 寄存器 | 值 | 解析 |
|--------|-----|------|
| PC | 0x... | 当前停在 xxx 函数 |
| LR | 0x... | 由 xxx 调用 |
| MSP | 0x... | 栈使用量约 N KB |
### 5. 根因分析
- **直接原因**:[导致 crash/异常的代码行或条件]
- **根本原因**:[为什么出现了这个直接原因]
- **证据链**:[日志数据 + 寄存器 + 源码 → 结论]
### 6. 解决方案
- 方案 1: [修改 xxx,因为 yyy]
- 方案 2: [备选方案]
- 推荐:[方案 X,理由]
请确认是否按推荐方案执行修改?
AI 输出报告后,等待用户指示:
- "按方案 X 修改代码" → AI 执行修改、编译、烧录、验证
- "补充 xxx 信息" → AI 按照用户要求补充调试
- "自己手动修改" → AI 结束调试,由用户操作
- "不是这个问题" → AI 重新分析
# 设备探测
st-info --probe
# 读取内存(Flash/SRAM/外设寄存器)
st-flash read <output.bin> <address> <size>
# CPU 寄存器 dump(需 halt)
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c "init" -c "halt" -c "reg" -c "resume" -c "shutdown"
# 完整 SRAM dump
openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c "init" -c "dump_image <output.bin> 0x20000000 <size>" -c "shutdown"
使用 EmberInterDebugTool(按 2.3/2.4 节安装并加载 skill),根据 skill 中的说明使用 CLI 启动监听。
export PATH="/mingw64/bin:$PATH"
# 符号表查看
arm-none-eabi-nm build/<project>.elf | sort
# 反汇编指定地址
arm-none-eabi-objdump -d build/<project>.elf | grep -A10 "<address>"
# 反汇编全部
arm-none-eabi-objdump -d build/<project>.elf > disasm.txt
xxd <file> # 标准格式
xxd <file> | head -20 # 只看前 20 行