尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用Claude Code Skill打造嵌入式AI管家:编译、烧录到波形分析

用Claude Code Skill打造嵌入式AI管家:编译、烧录到波形分析 1. 为什么说嵌入式开发终于等来了“AI 管家”干嵌入式这行的人都有个共同感受**这边的工具链太散了。**写代码用 VSCode编译靠 CMake 加交叉编译器烧录要敲 OpenOCD 命令查寄存器得翻 datasheet看波形又要切到逻辑分析仪的软件里。一天下来真正写代码的时间没多少全在工具之间来回切换、查资料、填参数。尤其是调试阶段CPU 跑到哪个寄存器、哪个外设没初始化对、波形时序差了几个微秒——这些问题靠肉眼盯屏幕找真的是在拿命换效率。Claude Code 本身的写代码能力大家已经见识过了但把它用在嵌入式上一开始我也只是让它帮忙生成点驱动的框架代码。真正让我觉得“有戏”的是 Claude Code 的 Skill 机制。Skill 说白了就是一套高度定制化的指令包和工具集合你把编译脚本、烧录流程、寄存器映射表、波形解析脚本都整理好Claude 按你设定的流程来调。它就不再是一个等问题的问答机器人而是一个能自己跑通“编译错误→拿日志→查代码→改完再编译”这条闭环的干活搭档。所以这篇文章我就把这段时间摸出来的经验完整梳理一遍。适合的人大概是这几类一是被 Keil、IAR 绑住手脚、想换成现代工作流又不确定怎么落地的 MCU 开发者二是已经在用 Claude Code 写业务代码、正准备往嵌入式方向延伸的 AI 编程重度用户三就是纯粹好奇“AI 能不能替我看时序图”的硬件工程师。我会把 Skill 怎么设计、怎么注册、各个功能模块怎么实现讲清楚尽量少讲套话多给能直接抄走的配置和脚本。2. Skill 的架构设计先想清楚 Claude 到底“会做”什么2.1 嵌入式 Skill 不能只给提示词不少人以为 Skill 就是写一段“你是一个嵌入式专家”的提示词这是个误区。Claude Code 的 Skill 机制分为两部分SKILL.md 指令文件和可执行的工具脚本。指令文件负责告诉模型“在什么场景下调用、遵循什么样的步骤”而工具脚本是真正干活的实体负责编译、烧录、抓寄存器值这类操作。我第一版只写了 SKILL.md让 Claude “根据交叉编译器执行编译”结果它自作聪明地调用了一个并不存在的编译器路径报错之后还一脸无辜。后来我把编译脚本写成 Python 文件让 SKILL.md 里面明确写“调用 tools/build.py参数为 board_type 和 target”情况才稳定下来。这个教训是Skill 的本质是把人类工程师的工作流固化成代码而不是靠模型临场发挥。模型的优势在判断日志、分析错误、规划修复方案而不是在一个陌生的嵌入式环境中摸索路径。2.2 分层结构指令、工具、数据源我现在用的嵌入式 Skill 目录大概长这样embedded_skill/ ├── SKILL.md ├── tools/ │ ├── build.py │ ├── flash.py │ ├── read_reg.py │ └── parse_wave.py ├── configs/ │ ├── stm32f407.json │ └── esp32c3.json └── docs/ └── register_map.mdSKILL.md 是入口描述技能的使用场景、边界和流程。tools 里面的脚本是能执行的动作configs 保存不同板子的编译参数和烧录接口docs 放一些参考备忘比如寄存器地址和位的含义、波形数据格式约定。这个分层的好处是职责清晰Claude 负责根据对话上下文决定调哪个工具、怎么解释工具输出但工具本身不依赖 Claude 的“智商”。即使某天没有模型参与你自己命令行也能跑这些脚本。这样等于把 AI 的可控性建立在了确定性代码之上。2.3 场景触发条件要尽量明确SKILL.md 里面我专门写了触发条件避免 Claude 在写算法题的时候也莫名其妙去加载嵌入式工具链。现在设置的触发场景有这么几类用户在对话里提到具体的芯片型号比如 STM32F407、ESP32-C3提到编译、烧录、寄存器、波形这些关键词或者直接将项目根目录指向一个带 CMakeLists/Makefile 的嵌入式工程。只有这些条件被满足时Skill 才会激活。这样一个设计思路核心其实是资源聚焦。嵌入式相关的工具链、数据文件、脚本如果全部常驻在上下文里会占用大量 token导致模型在普通代码任务上的表现也会变差。靠场景触发来按需加载能有效控制开销这也是 Skill 机制和普通自定义 system prompt 的一个重要区别。3. 搭建自己的嵌入式 Skill 环境3.1 准备工具链和基础依赖在写任何 Skill 代码之前先把开发环境本身彻底搞定。因为 Skill 只是帮你更高效地调用工具不能替代工具本身。我目前的工作环境是 Windows WSL2Windows 侧跑串口终端和图形化的逻辑分析仪客户端Linux 侧放交叉编译器和自动化脚本。必备的东西列一下Claude Code CLI这个直接 npm 安装就行装完claude命令能正常响应。交叉编译链ARM 系列用arm-none-eabi-工具链ESP32 用乐鑫官方的idf.py工具链。CMake 和 Ninja用来驱动构建系统Ninja 的增量编译速度比 Makefile 快很多。OpenOCD 或者 stlink-tools用于烧录。OpenOCD 兼容性好如果需要用 J-Link则装好 J-Link 驱动命令行工具是JLinkExe。Python 3.10 以上用来写各个工具脚本顺便处理波形文件。这些准备好之后先手动验证一遍命令能跑通再接入 Skill 层。不然你让 Claude 调一个本来就不好使的脚本它会陷入无意义的反复尝试很浪费时间。3.2 配置 SKILL.md让 Claude 明白自己的工作边界SKILL.md 就是给 Claude 看的一份“工作岗位说明书”。我自己的写法分四块第一块是技能描述一句话说明这个 Skill 服务于嵌入式 MCU 开发覆盖哪些阶段。第二块是触发条件就是前面说的场景关键词。第三块是工作流定义规定当用户提出需求时Claude 必须先分析需要哪些工具再按顺序执行最后汇总结果。比如用户说“编译一下”Claude 应该读取项目配置调用 build.py检查返回码如果失败就分析日志、定位文件、给出修改建议。第四块是安全护栏这条很重要。我明确写了涉及芯片寄存器的写入操作必须经过用户明确确认才可以执行烧录命令默认不添加擦除全片之类的危险操作如果脚本输出编码异常或者命令找不到不要假装成功必须如实反馈。这里贴一个精简版的 SKILL.md 开头部分大家可以参考它的结构--- name: embedded-assistant description: 嵌入式MCU项目开发助手负责编译、烧录、寄存器调试和波形分析。 --- # Embedded Assistant Skill ## 触发条件 - 用户提到具体芯片型号如 STM32、ESP32、GD32、NXP 系列 - 用户提到编译、烧录、寄存器、波形、linker、MAP 文件等关键词 - 当前工作目录存在 CMakeLists.txt、Makefile、*.ioc、platformio.ini 等嵌入式工程文件 ## 工作流程 1. 询问或确认目标板型、编译环境 2. 从 configs/ 下加载对应板型的配置文件 3. 根据用户意图调用 tools/ 下的功能脚本 4. 分析输出给出结论或修复建议3.3 注册 Skill 到 Claude CodeClaude Code 的 Skill 是通过目录约定来识别的。把embedded_skill/整个文件夹放到指定的 skills 目录下后在会话中用embedded-assistant就能加载。如果希望某些场景自动触发可以在项目级的 CLAUDE.md 中写上关联说明。先在一个空目录里做一个最小化实验让 Claude 读取 SKILL.md然后问它“如果用户说编译失败了你该怎么做”。正常的话它会按照工作流程描述先定位配置文件再看日志而不是直接给你乱写一段代码。这一步通过了说明 Skill 注册成功接下来往里面加功能模块才有意义。4. 四大核心功能实现从编译到波形4.1 编译模块最基础也最容易出错编译模块在整个 Skill 里的位置是“地基”。如果编译这一步不可靠后面不管查寄存器还是看波形都是空中楼阁。我的 build.py 主要逻辑是读取目标板子配置文件确定编译工具链路径和 CMake 参数调用 subprocess 启动构建捕获 stdout 和 stderr判断返回码如果失败把错误段落保留下来供 Claude 分析。配置文件的格式大致如下{ board: stm32f407, toolchain: arm-none-eabi-, cmake_options: [-DCMAKE_BUILD_TYPEDebug, -DCMAKE_TOOLCHAIN_FILEtoolchain.cmake], build_dir: build/stm32f407, output: build/stm32f407/firmware.elf }这里有个很关键的细节Claude 分析编译错误时最好把错误信息包含的具体文件路径和行号完整保留不要只给一个错误类型。因为嵌入式编译报错经常是连锁反应——一个头文件路径写错会带出几百行莫名其妙的类型错误。如果只把错误摘要给模型它会盯着后面那些衍生错误浪费时间。比如原来的代码里写错了寄存器地址偏移编译器报了 “undefined reference to xxx”如果不看 MAP 文件只从语法上找问题根本定位不了。所以我在 build.py 里做了个额外处理错误信息先按“文件路径”和“错误关键字”分组提取出每个文件的核心错误行再交给 Claude。这样模型拿到的信息密度高定位问题的速度会快很多。实测下来原本人工要看半天的编译错误交给 Skill 流程后往往几分钟内能指出是哪个源文件的哪个宏定义有问题。4.2 烧录模块让 AI 操作你的开发板烧录部分我保持了比较保守的策略。flash.py 会先显示将要执行的命令和操作说明并且支持--confirm参数来控制是否需要人工确认。在实际使用中我会让它默认开--confirm哪怕 Claude 已经觉得没问题了。烧录脚本里面做了一个“先查询后操作”的流程先查询当前连接的调试器或串口设备识别芯片型号再确定烧录方式。比如 STM32 常用 ST-Link走 OpenOCDESP32 常用 USB 转串口走 esptool。每次烧完我要求脚本自动执行一次校验读取确认 Flash 内容和构建产物一致。这里有一个我在实际中反复踩到的坑WSL2 对 USB 设备的转发支持并不总是顺畅。经常出现烧录器在 Windows 侧认到了但 WSL2 里面 lsusb 看不到设备。解决方案是把 Windows 侧的烧录工具做成一个代理WSL2 里的脚本通过 socket 或者简单 HTTP 调用 Windows 侧的命令行工具。这样既保留了 WSL2 的编译优势又能正常操作硬件。这个问题在社区里问的人很多建议大家提前规划好接线方式避免在 Skill 调试阶段被环境问题卡住。烧录完成之后“AI 管家”还能干一件事自动检查程序入口函数是否被正确放置。检查方式是用arm-none-eabi-objdump看反汇编入口地址或者直接读取 MAP 文件的入口符号如果发现入口偏移不对说明链接脚本有隐患。这个检查项也是我在实际项目中加进去的最初是因为一次 Bootloader 跳转失败查了两天才定位到链接脚本里 vector table 对齐没写对。4.3 寄存器查看模块把 800 页 datasheet 变成一问一答寄存器模块是 Skill 中最接近“管家”定位的功能。嵌入式开发里查寄存器太常见了常见到什么程度——“这个位是干嘛的来着”“为什么我改了配置没生效”“这个寄存器是只读的吗”这类问题在调试的时候几乎每隔十几分钟就会冒出来一次。以前大家的做法是翻 datasheet在几百页 PDF 里面搜关键词效率极低。我的实现思路分成两路一路是代码层面的寄存器定义查询另一路是运行时寄存器值读取。代码层面的查询核心是一个寄存器描述文件。我用表格形式把常用外设的关键寄存器整理好放到 docs/ 目录下面。比如 GPIO 的 MODER、OTYPER、OSPEEDR、PUPDR、IDR、ODRUART 的 BRR、SR、DR定时器的 CR1、CCMR1、CCR 等。每一条都写明偏移地址、复位值、每个位的含义、典型配置值。Claude 读这个文件之后可以解释一段代码在操作什么、配置结果会是什么。运行时的寄存器读取我写了一个 read_reg.py。早期版本是通过 OpenOCD 的mdw命令直接读内存地址这样做很直接但不区分外设总线。后来发现外设基址在不同系列芯片上差异很大于是改成先用配置文件获取总线基地址再算出绝对地址来读。现在还可以通过 gdb 的x/wx命令来做但 gdb 需要额外跑一个 gdbserver配置成本高了一些。read_reg.py 的一个额外功能是把寄存器的值解释成有意义的文本。比如读取一个 16 位的状态寄存器脚本会按每个标志位的掩码拆开标出哪个位是 1、表示什么状态。Claude 基于这个输出就能直接判断外设是否工作正常不需要用户再对着十六进制数心里默算。比如以太网 PHY 的寄存器分析靠这个脚本读几个关键寄存器基本能判断出 link 状态、协商速率和工作模式有没有异常。4.4 波形分析模块让 Claude 帮你看时序图波形分析这块是很多人觉得最像“黑科技”的部分其实原理并不复杂。逻辑分析仪导出的文件格式一般是 CSV 或者 VCDCSV 是一条条数据样本VCD 是带时间戳的信号电平跳变记录。我的 parse_wave.py 就是把这两种格式解析成结构化的时序描述再交给 Claude 去做高层推理。比如一个 I2C 的波形解析流程是这样的读取 CSV 文件识别 SCL 和 SDA 两路信号。根据 SCL 上升沿的位置截取 SDA 的电平状态组装成一串字节序列。判断起始条件SCL 高电平时 SDA 从高变低和停止条件SCL 高电平时 SDA 从低变高。把字节序列翻译成 I2C 地址、读写位、数据和 ACK/NACK 状态。输出完整的时序描述文本交给 Claude 进一步分析。Claude 拿到这段描述后能做的事情就多了。比如 I2C 地址不对它能指出设备的 7 位地址和 8 位地址之间的区别比如有 NACK它可以根据代码逻辑判断是设备没上电还是地址写错。这种能力对硬件调试帮助极大因为传统的逻辑分析仪软件只能给出“波形长这样”而我们需要的是“波形说明了什么”。用 CSV 做解析的一个大坑是采样率不足。如果你用低采样率的逻辑分析仪去抓高速 SPI很容易出现信号跳变没有被捕捉到的情况解析出来的总线数据完全是错的。我现在的处理方式是在文件头部记录采样率解析之前先检查信号最高频率和采样率之间的关系如果采样率低于信号频率的 8 倍就给出警告提示数据可能不可靠。这个小提示曾经帮我避免了一次很尴尬的误判代码逻辑没问题是逻辑分析仪采样率等级设置低了信号边沿被平滑掉了。5. 实操中遇到的几个典型问题和解决思路5.1 Claude 调用了错误的编译器或者路径这个错误出现的场景一般是切换了项目但配置文件没有同步更新。Skill 记住了上一个项目的工具链路径却在新的芯片平台上执行。我的解决办法有两个一是配置文件中加入 toolchain 的 MD5 校验或者版本检查二是让 build.py 检测到编译器不存在时主动输出一份“可用编译器列表”而不是直接报错。这样 Claude 就能根据提示自己切换工具链而不是反复尝试一个不存在的路径。5.2 寄存器查询结果与实际不符有段时间 read_reg.py 读出来的寄存器和 IDE 里看到的完全对不上排查下来发现是芯片在低功耗模式下部分外设时钟被关闭读寄存器会返回全 0 或伪随机值。现在脚本里加了一个前置检查先确认目标外设的时钟是否使能如果未使能不再无脑去读值而是提示用户“当前外设时钟关闭寄存器读取结果无意义”。这个细节看着小实际调试时非常能节省时间。5.3 波形文件太大导致解析超时逻辑分析仪抓一次几秒的数据CSV 文件可能到几百 MB。直接让 Python 一次性读入内存脚本直接卡死。我现在改用分块读取的方式只提取用户关注时间段的数据。同时允许用户在对话里指定采集通道和时间范围把数据量降下来。这个优化让波形解析从“不可用”变成了“日常可用的工具”也是我觉得最值得做的一个工程化改进。6. 这套方案到底有多大价值效率对比和心得从半个月的实际使用体验来看我统计的大致效率变化是常规编译错误定位时间从以前的 15 到 30 分钟降到现在的 3 分钟以内查寄存器配置以前要翻 datasheet现在直接问一句“这个寄存器的这个位是什么意思”就能得到带上下文的解答烧录流程因为加了自动校验基本能做到一次成功。最明显的感受是调试心态变了。以前遇到复杂 bug第一反应是“有点慌又要查半天”现在是“先让 Claude 跑一遍工具流程看看数据说是怎么回事”。不过也想提醒一句当前这个“AI 管家”距离全自动还远。它的判断能力仍然是概率性的尤其是在极端边界条件下比如 DDR 时序异常、电源纹波导致的偶发复位这类硬件深水区问题AI 也只能帮你缩小范围最终定论还是得靠你手里的示波器和经验。但作为嵌入式开发者的日常助手这个 Skill 的价值已经能明显感知到了。我目前把 compile 和 register 这两个模块用得很熟波形模块在 I2C、SPI、UART 这类低速总线上已经足够可靠。下一步计划是把 RTOS 的任务调度状态也纳入进来让 Claude 能通过读内核数据结构来回答“这个任务为什么没被调度到”这类问题。这个做完之后嵌入式调试中最后一个难啃的硬骨头——实时系统问题也就有了 AI 辅助的切入点了。最后再分享一个小技巧Skill 的配置目录建议放进 git 仓库里管理每次调整工具的阈值、更新寄存器描述文件都留下提交记录。Claude 在分析问题的时候你甚至可以问它“这个脚本最近改了什么”它能通过 git 历史帮你快速回溯变更。这个用法是我在整理波形解析脚本时偶然发现的目前已经成为我的日常操作之一强烈推荐给打算长期维护这套 Skill 的人。
返回列表