用 AI 开发 Zephyr-IoT 应用 在持续改进基于 AI 的嵌入式软件工作流的过程中本文将同样的 AI 智能体协作纪律应用到了 Zephyr 上。在本文的实验中乐鑫仍使用同一套来自 M5Stack 的 ESP DualKey 套件沿用相同的规格说明、集成规则、计划 → 执行 → 提交 → 测试流程、可复用模块、开发日志以及 Git 管理方式——但并未重新定义产品本身。引言在上一篇文章中乐鑫带着来自 M5Stack 的 ESP DualKey 走过了一段 Rust 固件开发之旅。目标是什么将乐鑫的统一配网Unified Provisioning功能从 ESP-IDF 移植到 BLE 和 SoftAP 上并构建出一个能够联网的产品。尽管项目按预期完成产出了预期的成果但真正重要的是这套工作流本身。本文正是围绕这套工作流展开这次应用到了 Zephyr 上。这里想阐述的重点并不是如何成为 Zephyr 专家。作为乐鑫内部 Zephyr 的产品经理——同时也偶尔提供技术支持——作者虽有一定经验积累但本文的核心目标并非 Zephyr 本身而是如何借助 AI 以不同的方式开展工作抛开表面的喧嚣。真正持久的收获在于如何与智能体协作——规格说明、边界、Git、证据——而不是纸面上哪种语言或哪种 RTOS 更胜一筹。如今写代码的速度很快难点转变为管理代码及其周边的一切架构设计、组织结构、测试验证以及知道何时该让模型停止敲代码。写代码这件事本身正在淡出但用代码的方式去思考问题依然至关重要。这一次ESP DualKey 仍然需要以和之前一样的方式与乐鑫 ESP BLE Provisioning应用通信。这次只是把实现迁移到了 Zephyr C并且在与智能体协作的方式上变得更加严格——更清晰的规格说明、更明确的边界、在 Git 管理和实测台验证方面更强的纪律性。若尚未阅读过 Rust 那篇文章建议先从那里读起再回到本文这样对产品脉络的理解会更加清晰。最后也是更重要的一点本文重点在于应用已经学到的经验这次不再堆砌大量原始日志内容。工具与目标Cursor 与产品定义这次实验并非从零开始。在智能体协作方面依然延续了此前熟悉的Cursor使用习惯——工作量较大时启用 Plan计划模式编码风格、项目边界、结构规范等约定也一并沿用。乐鑫仍然沿用了 Rust 项目中的产品规格说明并以Rust 代码树作为行为参照——按钮该做什么、配网体验该是什么样、实测台上完成意味着什么。ESP-IDF 和 Rust 阶段积累的成果被尽可能地复用。真正全新的部分是一个新操作系统的引入Zephyr。常规的 Zephyr 项目活动、任务、方法和流程这次全部结合 AI 来完成。由此便要谈到 Zephyr 本身……关于 ZephyrZephyr是 Zephyr 项目旗下的一款开源实时操作系统由 Linux 基金会The Linux Foundation负责管理。它远不止是一个内核而是一个庞大的树内目录包含驱动程序、协议栈和各类服务通过Kconfig和**设备树devicetree**进行配置并通过west元工具完成构建。它将 RTOS、板级支持、库文件与应用程序整合在一起。板卡和 SoC 的集成工作在上游完成产品固件和可复用模块通常存放在独立的代码仓库中而不是放在 OS 代码树内部。Zephyr 在乐鑫芯片上的支持乐鑫为 ESP32 系列 SoC 提供并支持 Zephyr。在乐鑫内部Zephyr 被视为一种可运行在乐鑫芯片平台上的 OS 发行版是一套成熟可靠的解决方案相关工作自 2020 年以来持续推进。Zephyr 的当前支持状态可在开发者门户的状态页面中查阅。为什么选择 Zephyr如前所述乐鑫已经支持 Zephyr。Zephyr 在乐鑫用户中的采用率一直保持稳步增长越来越多的开发者开始考虑采用乐鑫 Zephyr这一组合来推进项目。作为芯片厂商乐鑫始终致力于为用户提供优质的开发体验和完善的资源支持。然而也观察到部分客户反馈从零搭建新项目存在一定困难。这恰好是验证新方法的一个良好契机。此前已有类似设计的实践经验可供参考手机 App 和参考 C 代码定义了何为正确Zephyr 代码负责实现协议而不是重新定义协议。正因如此选择 Zephyr 来继续演进这套工作流程并非出于对固件开发本身认知的欠缺也不是因为 Zephyr 要在所有场景中取代 Rust——它们都是优秀的解决方案正如 ESP-IDF 一样出色。就 Zephyr 而言作者此前已完成安装与配置。Zephyr 的安装过程并不复杂相关文档也相当完善。理论上 AI 也能够完成这项安装工作不过这将是后续测试的内容。以产品定义为目标乐鑫沿用了docs/spec/product_spec.md并在 Zephyr 相关之处做了针对性调整——手势操作、LED 指示、配网流程的进入与退出包括重启策略、MQTT 和 HID以及明确划定的范围外内容。这并非一次全新的产品定义而是将同一份契约迁移到了新的技术栈上。在借助 AI 开展开发时那份文档正是目标所在正如前一篇文章中提到的那样以规格说明的形式呈现SSID 与 BLE 名称、超时时间设置、产品层面的取消逻辑以及实测台上完成具体意味着什么。当规格说明与代码出现分歧时需要有意识地修正其中一方——绝不能让两者同时各自漂移。依然是同一套 ESP DualKey 套件只是这次贴上了标识贴纸。设计原则已有的习惯这次实验并非重新开始基于常识总结出的一些整体性规则已经足以支撑起点。以下是经过补充和重新措辞后的内容一份书面规格说明胜过临场发挥的提示词。在协议相关的工作中参考代码ESP-IDF 示例、protocomm胜过纯文字描述。Git是实验出错时的撤销手段每个里程碑都值得一次提交。有边界的任务胜过实现整个子系统这类大而全的任务。追踪记录与实测台证据胜过仅凭源代码进行推断。架构设计与评估工作由开发者主导打字编码交给智能体完成。一旦交付出现问题责任由开发者本人承担。一旦方向明确编码工作应交由智能体完成。遇到卡壳时开发者与智能体共同调试。除此之外还积累了其他经验和改进之处。Rust 文章带来的启示主要是命名与体系化上述清单源自常识的沉淀撰写那篇文章时为其赋予了便于记忆的表述方式。此后又总结出一些经验这里值得原汁原味地保留下来Agent 模式只有在双方就下一步方向达成一致后才启用。当需要按顺序执行大量步骤时才使用Plan计划模式而不是依靠一场持续、重复的修复对话。每份计划都对应一次提交——细粒度的检查点确保当协作伙伴打字编码时二分查找 (bisect) 和回滚依然可行。关注结构与组织——即打扫房间——熵 (entropy) 不仅体现在低质量代码上也体现在重复的文档、散落的脚本以及放错位置的文件中。这篇文章中真正全新的内容而非仅仅是换个说法重复包括将熵明确定义为一种失败模式一张常见坑点清单虚构出的 API、协议漂移、混杂代码、过度重构、时序意外脚手架式的工作习惯生成器、编辑器规则、启动提示词、精选参考示例尽可能引入仿真与 CI 验证以及清理过程中误删调试日志的教训——当时双方都未将实验记录本视为值得保留的资产。Zephyr 这条线的实验建立在假定该契约依然有效的基础上评估者与编码者分工明确、规格说明先行、控制熵、以 Git 作为安全网。但一套更完整的流程正在逐渐成形下文将详细展开计划-编码-测试-提交循环。Zephyr 集成原则既然采用了 Zephyr它也自带一套需要遵循的规则。虽然本次设计聚焦于 Zephyr但这些规则完全可以被推广到任何操作系统上。具体如下尽可能充分使用 Zephyr——优先采用该 RTOS 及其原生支持的流程而非在应用层并行搭建迷你操作系统层。尽可能充分使用 OS 服务——网络管理、Wi-Fi 管理、BLE host、settings/NVS 模式、日志记录、工作队列只要子系统已经存在就应接入 Zephyr 子系统而非自行搭建临时垫片方案。尽可能充分使用 Zephyr 发行版——在自建私有副本之前优先利用树内模块和 Kconfig 可选的构建模块当功能缺失时向上游贡献代码而自行 forking 维护。尽可能无缝地融入 Zephyr 生态——west 工作区、树外模块布局、设备树、prj.conf、示例代码以及外观上与常规 Zephyr 集成方式一致的命名规范和文档风格。这四条原则是极为出色的提示词约束条件它们能够在模型凭空构想出一种外来项目形态之前先行明确好的标准。后文会展示这些原则是如何直接体现在代码仓库和构建产物中的而无需在每次使用时重新推导一遍。三个层次产品行为product_spec.md、Zephyr 集成原则上述清单以及新的代码仓库与构建布局详见后文。Zephyr 集成原则的新经验本次实验如果说上述原则相当于宪法即以往固件开发经验与 Rust 实验教训的沉淀那么接下来要讲述的就是 Zephyr 配网实验之后新增的修正案。这次实践揭示了更多层面的问题其中一些是全新发现另一些则是对已有认知的修正。经验的价值正在于此。这一次也保留了一份完整的开发日志。所有的经验积累都呈现出叠加效应能够携带更多的知识继续向前推进。代码提速判断仍需慎重模型敲代码的速度远超人类但这并不会减轻评估者的工作量反而加重了这一角色的负担。速度提升是实际的而真正的价值始终体现在批判性思考、架构设计、测试验证、调试排错和组织协调这些环节上始终得由人类亲自把关。快智能体慢开发者起草模块、执行重构、编写样板代码判断该架构是否应该存在提出 API 形态建议判断某个公开 API 是否稳定、精简快速阅读源代码判断追踪记录能证明芯片上实际发生了什么生成大规模代码差异判断该里程碑阶段是否允许提交如此大的差异这次实验进一步印证了这一点当配网出现异常行为时真正有效的做法依然是贴出日志、说明预期结果、询问哪个分支出了问题而不是持续生成代码直到编译通过为止。组织工作是开发者的职责Rust 那篇文章中提到的熵问题在这次实践中依然成立如果没有人主动强制维护结构用完即弃的脚本、重复的文档以及放错文件夹的顺手生成文件就会不断累积。规格说明与日志的区分、模块与应用程序的边界、.gitignore配置、子模块 (submodule) 版本锁定以及哪些内容该删除、哪些该提交——这些始终是开发者本人需要把关的职责范围。去重同样是这项工作的一部分当某个模块已有独立手册时就不应在产品代码仓库中重复导出相同的说明文字。这次实践中这一纪律得到了保持与 Rust 项目清理过程中日志丢失的教训形成鲜明对比。别再让 AI 拥有整棵代码树——拆分出独立组件此前曾经历过一个AI 在同一棵代码树中包揽一切的阶段。这次实践转向了可复用组件、验证用应用程序与精简产品三层结构——与具体技术栈无关并且明确考虑到了可复用性需求。混杂代码通用性修正方案Rust 那篇文章中已经点出了这一常见坑点——逻辑全部堆积在同一棵代码树中边界薄弱除非强制要求否则模型不会主动构建出清晰的层次结构。这次的应对方式从架构层面入手而非停留在语法层面一个正式的组件、一个正式的应用程序、一份独立于调试日志之外的规范化组件规格说明以及一个像对待独立软件库那样接受审查的公开 API。esp-provisioning 模块与 ESP DualKey 代码仓库正是这套思路在 Zephyr 上的具体呈现但这一经验并不局限于 Zephyr 本身。先验证后产品化在接入完整的产品应用之前先烧录并实测对应的示例程序或测试工具 (harness)。这与计划循环中的验证环节直接对应。在 Zephyr 上该测试工具正是esp_provisioning_shell。与智能体协作的有效策略以下策略并不局限于 Zephyr 场景源代码本身就是一份规格说明——与具体语言无关。为确保精确性应将智能体指向正在运行的代码树、模块 API 头文件以及 ESP-IDF 参考实现意图表达和代码审查则使用 Markdown 文档完成。组件与验证应用先行随后再进行产品集成。上游优先。若需要为上游项目添加或改进功能建议暂停手头工作先完成上游相关工作再回到主线继续推进。API 边界共享模块不应吸纳产品层面的业务策略。配网模块随着时间推移被持续裁剪正是因为其边界一直在被污染。产品归产品库归库无论该库当前是否已经存在。每次计划执行只对应一个里程碑一份计划、一次执行随后完成验证与提交再进入下一份计划。Git 与产物管理本次实践的观察频繁提交是硬性要求。子模块版本更新、API 裁剪、传输层修复都需要细粒度的提交记录否则git bisect便失去了应有的意义。这并非形式主义而是与打字速度极快、且缺乏自我约束的协作伙伴共事时的生存法则。AI 不负责处理上游 Git 操作。智能体可以准备差异对比 (diff) 和摘要说明但上游 Pull Request 的落地工作需由人类完成。某些关键环节——如同火车与飞机的运行——始终需要人类监督一旦失控后果可能相当严重。开发日志必须坚持保留。这次实践中journal.md被保留下来作为一份局部化的排障与防止重复走弯路记录。同时也发现它还能有效防止模型陷入重复推理。AI 本质上是一台统计机器经过一段时间后它可能会再次尝试此前已被证明无效的方案。这份日志有效阻止了这种情况的发生其效果远超预期且体现在诸多意想不到的方面。这一次日志被存放在模块代码仓库中。每份计划要做的第一件事就是更新日志。通常的做法是在制定计划阶段就明确要求——待办事项将上一轮循环中所有正面结果以及已尝试但未能解决问题的方案更新进日志。问题描述与对应的修复方案会被一并记录也就是说问题和修复方案会共同写入日志。很多情况下当 AI 撤销某项改动、查阅日志、找到一条直接相关或类似的记录后往往能在同一轮次中就完成修复。计划 → 执行 → 提交 → 测试核心齿轮这套节奏具有通用性——无论是 Rust、Zephyr还是其他任何技术栈都同样适用。Zephyr 在这里仅作为具体案例出现。图 2 - 提出的开发循环。Rust 那篇文章曾提及针对长序列任务需要进行计划但并未把计划执行完成之后该如何推进落实为具体的操作步骤。这次将其提升为独立的一个环节计划在开展非平凡的智能体工作之前先制定计划借助 Cursor 的 Plan 模式或撰写一份明确的计划文档。执行由智能体、开发者或双方协作完成计划的执行。提交在测试进入较为棘手的阶段之前先提交一个可回滚的检查点——此时改动依然容易撤回——因为在实测台验证过程中智能体或开发者本人都可能不受控制地想要再多修一处。测试在实测台上进行验证构建、烧录、冒烟测试场景对于组件而言需先跑通示例测试工具再接入完整产品。循环测试完成后基于上一阶段的结果重新启动计划环节而不是在一次失败的运行基础上不断堆叠没有边界的修复提示词。务必回到计划阶段——放任 AI 无节制地写代码、自行修复 Bug 的诱惑始终存在但应当加以抵制。一旦如此AI 生成的代码将变得难以维护、难以支撑。从流程角度看这本质上就是 PDCA计划-执行-检查-处理Plan-Do-Check-Act穿上了固件开发的外衣这一规律依然成立。在第一篇文章中曾提到与 AI 协作在技术层面上与管理初级开发者极为相似这次的实践进一步印证了这一 PDCA 理念。通过将整个开发过程以频繁提交的方式记录进 Git日后无论是审查方案还是加以控制都会变得相对容易。Git 依然是那张安全网提交粒度与产物管理习惯让 bisect 保持可靠而这套循环正是让契约真正落地的运行节奏——计划不是对话中的一种奢侈行为每一次执行都应以验证和提交收尾。在有人质疑这样做是否会导致 Git 历史变得杂乱之前需要说明的是提交记录随时可以被压缩squash并回顾其中的提交信息——也就是那些计划——审视各次提交之间真正保留下来的内容。这在可追溯性方面是一次显著提升虽然会带来一定程度的熵增但这种熵增是可控的。开发者曾一度放松了对提交之间所有 Cursor 计划的管控导致这些计划被 AI 用于生成提交信息甚至计划本身也被直接提交。再一次这对协作组合中负责批判性思考的一方即开发者本人未能尽到应尽的职责。避免重蹈覆辙本身就是学习的意义所在。Zephyr 特有经验本次在 ESP32 上的实验这次实践中同样积累了一些技巧并且发现了若干与 Zephyr 相关的经验这些经验完全可以被归纳、推广到所使用的任何基础软件平台上。使用的 Zephyr 集成模式具体如下模块布局遵循最佳实践。这并非全新理念但始终值得反复强调。优先尝试示例应用。这是一项能大幅节省时间与精力的明智决定。逐个单独验证各个组件能够节省大量后续排查成本。产品应用需保持条理清晰。业务逻辑应与基础组件支持能力相分离。不要触碰上游代码。AI 存在一个较为棘手的倾向一旦发现方便之处就想去修复问题或添加追踪代码这其中包括对 Zephyr 主干源码的大量修改。它无法区分代码的性质在其视角中代码就是代码。针对这一点作者设定了一条硬性规则。除非确实需要触碰上游内容。这正是妙处所在。当 AI 确信新增 Zephyr 代码确有必要时它会先征求许可再进行修改。此时会采取更为传统的方式逐行审查相关代码。当改动可能影响到整个上游项目时开发者会变得格外谨慎。ESP DualKey / esp-provisioning 成果简述公开代码仓库zephyr/modules/esp-provisioning —— 树外模块及 shell 示例。zephyr/ —— 消费该模块的产品固件。在实测台上shell 示例通过 BLE 和 SoftAP 传输方式与乐鑫配网 App 完成联调集成后的应用遵循同一份产品规格说明。模块 API 经过持续裁剪以保持其应有的软件库形态。结论Rust 那篇文章中提出的结对编程分工方式依然成立模型负责编码开发者负责评估——依据规格说明、参考代码树、构建输出、UART 追踪记录以及实测台验证结果进行把关。代码是廉价的判断力不是。随着实践的持续推进真正发生变化的是一整套围绕 AI 驱动开发的流程正在逐步沉淀成型而不再将每一次对话都当作一次性行为处理。规格说明、规则体系、开发日志、可复用模块、先验证后产品化的顺序、提交粒度以及计划 → 执行 → 提交 → 测试这一循环都不是追赶潮流的附加环节——它们才是真正实现生产力提升、且不必为无法追溯的回归问题付出代价的关键所在。这些经验是层层累积而成的。Rust 那一轮实践带来了协作契约、熵的控制方法以及关于混杂代码树和丢失日志的警示。Zephyr 这一轮则新增了平台化的组件设计、更清晰的 API 边界、实测台上先验证后产品化的做法以及一条由开发者主导的上游 Git 协作路径。这一切都没有取代此前已经建立起的纪律。PDCA依然贯穿始终只是换上了 Cursor配上了一位打字速度更快的协作伙伴。Git 作为撤销手段、有边界的任务划分、UART 作为事实依据——这些原则同样一以贯之。真正的挑战并不在于每次切换技术栈都要重新发明一套全新的教条而在于充分复用已经掌握的经验将产品规格说明沿用下去让智能体参照既有源码与参考实现把规则一次性明确写下来并保留好下一次协作时可供读取的产物。若每次都从零开始只会重蹈覆辙——丢失的日志、臃肿的代码树以及那种应该能行却缺乏实际依据的侥幸心理。因此接下来的工作既是编码更是一种持续的梳理与沉淀坚持原则、用项目标准训练智能体让其在敲代码环节全面提速同时开发者始终守住评估者、策略制定者以及为整个项目指明方向的舰长与领航员这一角色。这正是速度真正能够转化为价值的地方。相关链接用 AI 开发基于 Rust 的 IoT 设备2026 年 4 月dualkey-provisioning — rust/Rust 固件zephyr/modules/esp-provisioningdualkey-provisioning — zephyr/ESP-IDF 统一配网 API