亚马逊AWS官方博客
AI 辅助嵌入式全流程开发:使用 Kiro 逐步构建智能温湿度监控系统
摘要:本文介绍如何使用 AI 编码工具 Kiro 辅助嵌入式系统的全流程开发。通过一个智能温湿度监控系统的实际案例,展示从需求分析、代码生成到调试部署的完整开发过程,帮助开发者了解如何借助 AI 提升嵌入式开发效率。
目录
一、前言
嵌入式开发一直是软件工程中最“手工”的领域之一:工程师的大量时间并非花在创造性的架构设计上,而是消耗在翻手册、对寄存器、调参数这类机械劳动中。一个完整的嵌入式项目涉及时钟树配置、GPIO 复用、DMA 传输、RTOS 移植、GUI 渲染——每一层都有自己的“Datasheet 陷阱”。
举一个典型场景:要在 STM32H743 上驱动一颗 SDRAM,首先要在数千页的参考手册中找到 FMC 章节,再打开 SDRAM 的 Datasheet 核对时序参数。以 120 MHz 的 SDCLK 为例,72 ns 的 tXSR 需要向上取整为 9 个时钟周期;STM32H7 HAL 接口接收实际周期数,底层再将其转换为寄存器编码。时序单位、时钟来源或刷新公式中的任一环节处理不当,都可能导致 SDRAM 自检偶尔通过而显示仍然异常。
能否让 AI 辅助完成“查手册、整理参数和生成模板代码”等重复工作,让工程师把更多精力放在架构决策、参数复核和异常判断上?Kiro 提供了一套可行的人机协作方式。它的重点不是“一键生成代码”,而是通过三个机制组织开发过程:
- Spec 驱动——以“需求 → 设计 → 任务”的结构化流程逐层拆解,而不是一次性 prompt;
- Steering 约束——硬件参数与编码规范一次配置、全程生效;
- Skills 沉淀——把踩过的坑固化为可复用的团队资产,下次不再重复踩坑。
本文将分 9 个步骤介绍:如何使用 Kiro 辅助在 STM32H743IIT6(Cortex-M7,最高主频 480MHz)上逐步构建一个带 800×480 LCD 曲线显示的温湿度监控系统。流程覆盖硬件连接信息整理、需求与设计拆解、代码实现、编译、烧录和调试。
[图1 系统实机运行效果:800×480 LCD 实时温湿度曲线] |
二、前置准备
2.1 硬件清单
| 器件 | 型号 | 用途 |
| 开发板 | STM32H743IIT6(176 引脚 LQFP) | 主控 MCU,最高主频 480MHz Cortex-M7 |
| 温湿度传感器 | DHT20(I2C,7 位地址 0x38) | 数据采集 |
| 显示屏 | 800×480 RGB LCD(LTDC 接口) | 曲线显示 |
| 外部内存 | W9825G6KH-6I(32MB SDRAM) | 帧缓冲 + LVGL Draw Buffer |
| 调试器 | DAPLink(CMSIS-DAP) | SWD 烧录 |
2.2 软件环境
| 工具 | 版本 | 用途 |
| Kiro | kiro-ide-0.11.131-stable | AI 开发环境 |
| arm-none-eabi-gcc | 12.x+ | 交叉编译器 |
| pyOCD | 0.42+ | CMSIS-DAP 烧录 |
| 串口终端 | screen / minicom | 115200 8N1 日志 |
[图2 STM32H743 开发板、DHT20 传感器与 RGB LCD 连接实物] |
三、步骤 1:构建 Datasheet 知识库
嵌入式开发离不开查手册:SDRAM 的时序参数、DHT20 的 I2C 协议、LTDC 的像素时钟范围等信息散落在大量 PDF 中。通过 MCP 连接 Amazon Bedrock Knowledge Bases,可以让 Kiro 基于检索到的手册内容回答问题,减少仅凭模型记忆作答的风险。检索结果仍需工程师对照原始 Datasheet 复核。系统架构如下:
[图3 Datasheet 知识库系统架构] |
3.1 Datasheet 文档管理全流程
3.1.1 阶段一:上传
- 用户通过 Kiro 的 DataSheet MCP 工具上传文档(PDF、Word、技术规格书等);
- MCP 将文档写入 Amazon S3 Draft Bucket(草稿桶),并附带元数据(上传者、时间、文档类型、版本号);
- 此时文档状态为“待审批”,不对外可见。
3.1.2 阶段二:事件驱动审批
- 在 Draft Bucket 已启用向 Amazon EventBridge 投递事件后,PutObject 事件会发送至 EventBridge;该配置启用后通常需要数分钟生效;
- EventBridge 规则匹配后触发 AWS Step Functions 审批工作流;
- Step Functions 执行以下步骤:
- 通过 Amazon SNS 向审批人发送通知;如需投递到协作软件,还需配置相应的订阅端点或集成服务;
- 通过回调任务令牌等方式等待审批结果,并设置超时时间;
- 审批通过:将文档从 Draft Bucket 复制到 Production Bucket,确认复制成功后再删除草稿副本,状态标记为“已发布”;
- 审批拒绝:通过 SNS 将修改意见通知作者,文档保留在 Draft Bucket,状态改为“需修改”;
- 超时未审批:按工作流配置升级通知或结束审批。
3.1.3 阶段三:自动入库 Knowledge Base
- 文档落入 S3 Production Bucket 后,在该 Bucket 同样启用 EventBridge 事件投递的前提下,S3 事件再次触发 EventBridge;
- EventBridge 触发 AWS Lambda 函数;
- Lambda 执行:
- 按文档类型选择 Amazon Textract、Bedrock Knowledge Bases 支持的解析器或自定义解析流程;
- 对提取的文本进行清洗与分块(chunking);
- 通过与所选 Knowledge Base 数据源相匹配的摄取流程完成向量化和索引更新;
- 将处理状态(成功、失败和重试次数)记录到 Amazon DynamoDB。
- 入库并完成同步后,用户即可通过 Bedrock Knowledge Bases 的检索增强生成能力对 Datasheet 进行自然语言问答。
3.2 Kiro 查询知识库
[图4 Kiro 查询知识库流程] |
3.3 示例:SDRAM 初始化
下面以 SDRAM 初始化为例。Kiro 通过 DataSheet MCP 查询 STM32H743 FMC 控制器与 W9825G6KH-6I 的时序参数,并结合项目实际硬件配置推导出 FMC 寄存器值:
[图5 Kiro 调用 DataSheet MCP 查询 SDRAM 时序参数] |
完整的 SDRAM 初始化代码如下:
/**
* bsp_sdram.c — W9825G6KH-6I (32MB, 16-bit) via STM32H743 FMC
*
* 时序参数来源:
* - STM32H743 RM0433 Chapter 22 (FMC SDRAM controller)
* - W9825G6KH-6I Datasheet (speed grade -6I)
* - FMC_SDCLK = HCLK / 2 = 240MHz / 2 = 120MHz → 8.3ns per cycle
*/
#include "bsp_sdram.h"
SDRAM_HandleTypeDef hsdram;
/* ---- MPU 配置:Write-Through, Cacheable ---- */
static void SDRAM_MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
HAL_MPU_Disable();
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0xC0000000; /* SDRAM Bank 1 */
MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; /* B=0 */
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; /* C=1 */
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; /* TEX=0 → Write-Through */
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
/* ---- SDRAM 初始化命令序列(按 W9825G6KH 规格) ---- */
static void SDRAM_InitSequence(void)
{
FMC_SDRAM_CommandTypeDef Command = {0};
/* Step 1: Clock Enable */
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram, &Command, 0xFFFF);
/* Step 2: 等待时钟稳定 ≥100µs */
HAL_Delay(1);
/* Step 3: Precharge All */
Command.CommandMode = FMC_SDRAM_CMD_PALL;
HAL_SDRAM_SendCommand(&hsdram, &Command, 0xFFFF);
/* Step 4: Auto Refresh ×8 */
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.AutoRefreshNumber = 8;
HAL_SDRAM_SendCommand(&hsdram, &Command, 0xFFFF);
/* Step 5: Load Mode Register
* Burst Length = 1
* Burst Type = Sequential
* CAS Latency = 3 (匹配 FMC CASLatency 配置)
* Operating Mode = Standard
* Write Burst = Single
*/
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition =
(0x0000 << 0) | /* Burst Length = 1 */
(0x0000 << 3) | /* Burst Type = Sequential */
(0x0003 << 4) | /* CAS Latency = 3 */
(0x0000 << 7) | /* Operating Mode = Standard */
(0x0001 << 9); /* Write Burst = Single */
HAL_SDRAM_SendCommand(&hsdram, &Command, 0xFFFF);
}
/* ---- 主初始化函数 ---- */
uint8_t BSP_SDRAM_Init(void)
{
FMC_SDRAM_TimingTypeDef SDRAM_Timing = {0};
/* 1. MPU 配置 */
SDRAM_MPU_Config();
/* 2. FMC 控制器参数 — W9825G6KH: 13-bit row, 9-bit column, 16-bit data, 4 banks */
hsdram.Instance = FMC_SDRAM_DEVICE;
hsdram.Init.SDBank = FMC_SDRAM_BANK1;
hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9; /* 512 columns */
hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13; /* 8192 rows */
hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16; /* 16-bit */
hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; /* 4 banks */
hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; /* SDCLK = HCLK/2 = 120MHz */
hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
/* 3. 时序参数 — 来自 W9825G6KH-6I Datasheet + Kiro Datasheet MCP 查询 */
SDRAM_Timing.LoadToActiveDelay = 2; /* tMRD = 2 cycles */
SDRAM_Timing.ExitSelfRefreshDelay = 7; /* tXSR = 72ns → 9 cycles → reg=7 */
SDRAM_Timing.SelfRefreshTime = 4; /* tRAS = 42ns → 6 cycles → reg=4 */
SDRAM_Timing.RowCycleDelay = 7; /* tRC = 60ns → 8 cycles → reg=7 */
SDRAM_Timing.WriteRecoveryTime = 2; /* tWR = 2 cycles */
SDRAM_Timing.RPDelay = 2; /* tRP = 15ns → 2 cycles */
SDRAM_Timing.RCDDelay = 2; /* tRCD = 15ns → 2 cycles */
/* 4. 初始化 FMC */
if (HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
return 1;
/* 5. 执行 SDRAM 初始化命令序列 */
SDRAM_InitSequence();
/* 6. 设置刷新率
* W9825G6KH: 8192 rows, 64ms refresh period
* Refresh Rate = (64ms / 8192) × 120MHz - 20 = 917
*/
if (HAL_SDRAM_ProgramRefreshRate(&hsdram, 917) != HAL_OK)
return 2;
return 0;
}
该示例中的 FMC 时序字段仍需按实际 FMC 时钟重新计算,并注意 STM32H7 HAL 参数传入的是实际周期数,而不是已经减 1 的寄存器编码值。
四、步骤 2:导入原理图——AI 辅助整理硬件连接
硬件原理图是电子元器件之间电气连接关系的完整描述。一张典型的 STM32H743 开发板原理图包含上百个元器件、数百条网络连接,如何让 AI 准确理解这些硬件信息?有两种可行的方案:
方案一:多模态视觉识别(PDF/图片)。直接将原理图 PDF 或截图交给 AI,利用多模态能力识别元器件和连接关系。这种方式对简单电路(几十个引脚的 MCU)效果尚可,但面对 STM32H743 这样 176 引脚的 MCU,加上 SDRAM 的 40 余根数据/地址线、LTDC 的 24 根 RGB 信号线,识别准确率明显下降——漏识别一个引脚复用关系,就可能导致后续驱动代码配错 GPIO。此外,不同模型的识别能力参差不齐,结果不够稳定。
方案二:网表文本解析(本文采用)。网表(Netlist)是从 EDA 工具(Altium Designer、KiCad、立创 EDA 等)导出的结构化文本,记录元器件、封装和网络连接关系。相比直接识别原理图图片,网表更便于检索、版本管理和程序化处理,但它不一定包含全部设计意图、电气约束或版图信息,AI 的解析结果也仍可能出现遗漏或误判。
具体做法:通过 Kiro 的 filesystem MCP 读取网表文件,由 AI 辅助整理 MCU 参数、外设清单和引脚映射表,并标记潜在冲突供工程师复核。两种方案的对比如下:
| 维度 | 多模态视觉识别 | 网表文本解析 |
| 输入格式 | PDF/图片 | .net 等结构化文本 |
| 可靠性 | 受图片清晰度、版面和模型能力影响 | 连接关系更易追溯,但解析结果仍需校验 |
| 适用范围 | 适合快速理解局部或较简单电路 | 更适合连接密集、需要批量核对的设计 |
| 可复现性 | 受模型和图片质量影响较大 | 输入可固定,输出仍可能受模型版本与提示影响 |
| 版本管理 | 图片不便直接 diff | 文本文件便于 Git 管理和差异比较 |
⚠️ 重要提示:
无论采用哪种方案,AI 输出的硬件描述都必须经过人工检查确认。尤其是引脚复用关系和 I2C/SPI 总线上的设备地址,它们是后续驱动代码正确性的基础。确认无误后再锁定硬件配置,进入下一步。
4.1 Kiro 输出:外设清单
| 外设 | 芯片型号 | 接口 | 关键引脚 |
| SDRAM | W9825G6KH-6I | FMC | A0-A12、BA0-BA1、D0-D15 |
| USB 转串口 | CH340X | USART1 | PA9(TX)、PA10(RX) |
| 温湿度传感器 | DHT20 | I2C | PH4(SCL)、PH5(SDA) |
| RGB LCD | TFT 40P | LTDC | R0-R7、G0-G7、B0-B7、HSYNC、VSYNC、DE、PCLK |
| LED | 红、绿 | GPIO | PB1(红)、PB0(绿) |
五、步骤 3:生成 Steering 约束文档
嵌入式开发有一个独特的挑战:同样的硬件,不同工程师写出的代码可能天差地别。同样是驱动一颗 SDRAM,有人把初始化代码写在 main.c 里,有人封装成 BSP_SDRAM_Init();有人使用硬编码的魔法数字 0xC0000000,有人用 #define SDRAM_BANK_ADDR 集中管理;有人在 HAL 初始化失败时默默忽略返回值,有人严格检查每一步并调用 Error_Handler()。经验丰富的工程师会自然地遵循分层架构、统一命名、防御性编程这些最佳实践,而初级工程师往往需要踩过几次坑之后才能形成这些习惯。
用 AI 生成代码时,这个问题同样存在——如果不加约束,AI 每次生成的代码风格可能都不一样:这次用 bsp_ 前缀,下次用 drv_ 前缀;这次把 GPIO 配置写在 MspInit 回调里,下次直接写在初始化函数中。代码能跑,但不一致、不可维护。
如何提高 AI 生成代码时的一致性?一种方式是使用 Steering。Steering 把硬件参数、编码规范和工具链约定写成持久化文档,并支持始终包含、按文件匹配、手动包含等加载方式。对于应影响整个项目的核心规范,可配置为始终包含;对于特定模块的详细规则,应选择更有针对性的加载方式。基于前两步的 Datasheet 查询和硬件连接信息整理,本文使用三份约束文档:
以 coding-standards.md 为例,它约束了:
- 文件组织:每个外设驱动成对出现在
bsp_xxx.h和bsp_xxx.c; - 接口命名:统一使用
BSP_<Module>_<Verb>()格式,如BSP_SDRAM_Init()、BSP_LCD_FillScreen(); - 错误处理:所有
HAL_xxx_Init()的返回值必须检查,失败时返回错误码或调用Error_Handler(); - GPIO 配置:统一在
HAL_xxx_MspInit()回调中完成,不散落在业务代码里; - 常量管理:硬件地址、引脚定义、时序参数全部以宏定义集中在头文件中,禁止魔法数字。
这些 Steering 有助于让后续生成的 BSP 驱动、FreeRTOS 任务和 LVGL 移植层保持一致。它的价值是把团队规范从口头约定或 Code Review 阶段前置到生成阶段,减少命名、分层和错误处理上的偏差。不过,Steering 不能替代代码审查、编译检查和硬件验证。
六、步骤 4:Spec 驱动——需求 → 设计 → 任务拆解
AI 编程助手已经能很好地完成局部任务:补全一个函数、修复一个 bug、解释一段代码。但嵌入式系统开发不是一个个孤立的函数——它是一项有严格依赖顺序的工程:SDRAM 必须在 LCD 之前初始化(因为帧缓冲位于 SDRAM);LVGL 必须在 FreeRTOS 之后启动(因为它依赖任务调度);DHT20 的采样周期必须与 UI 刷新率解耦(否则传感器阻塞会导致界面卡顿)。
这些系统级约束很难通过一条提示词完整表达。AI 可以生成一个 BSP_SDRAM_Init() 函数,但工程仍需明确它在 main() 中的调用位置、LVGL Draw Buffer 与 LCD 帧缓冲的边界,以及 FreeRTOS 任务之间的优先级和通信关系。
Kiro Spec 通过 Requirements → Design → Tasks 三层结构化文档,把“做一个温湿度监控系统”这类目标逐步细化为可执行任务,并在各阶段保留人工审查和确认的机会:
- Requirements:定义“系统应该做什么”——用 EARS 等结构化方式写出可验证的验收标准;
- Design:定义“系统怎么做”——包括架构分层、内存映射、任务模型和启动顺序;
- Tasks:定义“具体实现哪些内容”——标明相关文件、接口、依赖关系和 Requirement。
这三层文档不应一次生成就直接定稿。Kiro 先产出初稿,工程师根据手册、原理图和资源约束提出修改意见,再持续迭代,直到关键参数和验收方法具备可追溯依据。这就是结构化协作与单次提示词生成的主要区别。
6.1 Requirements(EARS 格式)
本文案例生成了 12 条需求,覆盖从底层串口驱动到上层曲线 UI 的主要功能,并为每条需求附上 EARS 风格的验收标准(Acceptance Criteria)。以下内容保留原始 Spec 示例;其中工具链描述仍混有早期 Keil/RVDS 方案,本文最终实现路线以 GCC、GCC FreeRTOS port、newlib-nano _write 重定向和 ELF/HEX 产物为准:
6.2 Design(架构设计)
Design 的核心思路是渐进可观测:系统被划分为 6 个阶段,每个阶段都定义串口日志、LED 行为或 LCD 显示等验证证据。工程师可以在每个阶段结束时烧录验证,而不是等全部代码完成后才进行首次集成。需要注意的是,后续阶段的验证不能反向证明早期参数必然正确,关键时序仍应依据 Datasheet 独立复核。
实现前提:实际 LCD 时序与像素时钟必须以具体面板型号和 Datasheet 为准,PLL3 参数还取决于开发板 HSE 频率;LVGL v8 必须额外提供毫秒 Tick,例如在 FreeRTOS Tick Hook 中调用 lv_tick_inc(),或配置 LV_TICK_CUSTOM。
Design 中最关键的三部分内容——六阶段渐进路线、SDRAM 内存映射与 FreeRTOS 任务模型——汇总如下。
6.2.1 六阶段渐进路线
| 阶段 | 核心交付 | 验证证据 |
| Phase 1 | USART1 + LED + main() 心跳 | LED 500ms 翻转 + 串口 [heartbeat] tick=N |
| Phase 2 | FreeRTOS 内核 + LED_Task | 串口 [LED_Task] toggle=N |
| Phase 3 | SDRAM + MPU 配置 | 串口 SDRAM OK: 32MB @ 0xC0000000 |
| Phase 4 | LTDC + 帧缓冲 | 屏幕红/绿/蓝全屏 |
| Phase 5 | LVGL + DMA2D + LVGL_Task | 屏幕 “ENV Monitor” + 空 Chart |
| Phase 6 | DHT20 + Sensor_Task + Chart | 曲线滚动 + 串口 T=25.32 H=48.71 |
6.2.2 SDRAM 内存映射
| 区域 | 起始地址 | 大小 | 用途 |
| LCD Framebuffer | 0xC0000000 | 1.46 MB | LTDC Layer 0 扫描区 |
| LVGL Draw Buffer 1 | 0xC0180000 | 150 KB | 双缓冲第一块 |
| LVGL Draw Buffer 2 | 0xC01A5800 | 150 KB | 双缓冲第二块 |
| Free | 0xC01CB000 | 约 30 MB | 预留扩展 |
6.2.3 FreeRTOS 任务模型
| 任务 | 优先级 | 栈 | 周期 | 职责 |
| LVGL_Task | 3 | 4096 words | 5ms | lv_timer_handler() 渲染 + 消费采样队列 |
| Sensor_Task | 2 | 512 words | 1000ms | DHT20 采样并写入队列 |
| LED_Task | 1 | 128 words | 500ms | LED 心跳翻转 |
6.3 Tasks(实现计划)
Design 随后被拆解为 40 余个 Task,各 Task 尽量明确文件路径、函数签名、依赖关系及其关联的 Requirement 编号。以下为原始任务清单,代码与命令内容按本轮要求保持不变;正式实施时应统一为 GCC 工具链,并修正其中已标记的时序、LVGL Tick、DMA2D 完成标志和时间戳处理问题:
可以看到kiro生成的任务里面除了必选的任务还有一些可选任务,可选任务用于辅助测试功能单元是否符合预期,并且kiro非常擅长编写脚本(如Python,Power Shell等)辅助程序的开发。
七、步骤 5:代码生成——Kiro 逐 Task 辅助实现
Spec 确认后,可以让 Kiro 按 Phase 顺序处理 Task:读取任务描述与关联的 Requirement,结合 Steering 约束生成或修改对应文件。工程师仍需逐 Task 审查,并在每个 Phase 结束后依据 tasks.md 中定义的串口日志、LED 行为和 LCD 显示完成验证。
八、步骤 6:GCC 编译
当用户指定用GCC编译代码时,kiro会根据系统环境变量检查工具链是否存在,若工具链不存在,kiro会指导用户完成工具链的安装,有效地降低用户部署开发环境的耗时。当kiro被给予相应的权限,部署开发环境的工作甚至可以在没有人的干预下独立完成。
传统嵌入式 IDE 通常通过图形界面管理头文件路径、预处理宏、链接脚本和浮点 ABI。切换到 GCC 开源工具链后,需要在 Makefile 或 CMakeLists.txt 中显式配置源文件、Include 路径、链接脚本、FPU 和浮点 ABI。若使用 newlib-nano,还需要通过 -u _printf_float 显式启用浮点格式化;--specs=nano.specs 的作用是选择 newlib-nano,二者不应混为一谈。
这些构建配置的复杂度在大型工程中尤为突出。本项目涉及 HAL 库(50 余个 .c 文件)、FreeRTOS 内核(8 个源文件 + portable 层)、LVGL 图形库(200 余个源文件)、BSP 驱动(5 个模块)和应用层(6 个源文件)。仅仅是把这些源文件和头文件路径正确地组织进 Makefile,对不熟悉 GCC 工具链的工程师来说就是不小的挑战。
Kiro 可以根据 Steering 中的工具链约束(toolchain.md)和 Design 中的目录结构生成 Makefile 初稿,工程师随后需要核对启动文件、链接脚本、源文件集合、库选项和目标芯片参数。本文最终采用 GCC 路线,核心配置如下:
原始编译示例输出如下。具体文件大小取决于源码、编译器版本和优化选项,本轮按要求不修改代码块内容:
九、步骤 7:烧录与验证
嵌入式开发中,代码编译通过并不意味着程序可以在目标硬件上正常运行。烧录这件事看似简单,实际涉及一连串琐碎的配置:调试器驱动是否识别?目标芯片型号选对了没有?Flash 擦除算法是否匹配?烧录完要不要自动复位?串口波特率和引脚对不对?不同调试器(ST-Link、J-Link、DAPLink)各有各的工具和命令行参数,换一个调试器可能整套流程都要重新摸索。
在传统 IDE 中,这些配置通常分布在多个调试选项中。本文把烧录命令整理为 Makefile 目标:make flash 用于烧录,make reset 用于复位,底层调用 pyOCD(开源的 CMSIS-DAP 调试工具)。这样可以把命令和目标型号纳入版本管理,也便于在具备调试探针和目标板的自托管 CI 环境中集成。实际可复现性仍取决于工具版本、探针固件、目标板状态和权限配置。
示例串口日志如下。正式发布时应使用可追溯的原始日志替换或注明测试日期、固件版本与硬件版本:
十、步骤 8:AI 辅助调试——先观察,再验证
嵌入式开发通常需要多轮验证。这一步以两个场景说明如何使用 Kiro 汇总代码、原理图和 Datasheet 线索;最终根因仍应通过日志、寄存器状态、总线波形或对照实验确认。
10.1 场景 1:DHT20 I2C 通信异常
10.1.1 现象
10.1.2 Kiro 诊断过程
- 查询 Datasheet:“DHT20 上电后需要等待多久?”——要求是不少于 100 ms;
- 检查代码:
BSP_DHT20_Init()中只写了HAL_Delay(50),等待时间不足; - 对照原理图确认 PH4/PH5 引脚和 4.7 kΩ 上拉电阻配置,随后仍需通过 I2C 波形或应答状态排除连线、供电和时序问题。
10.1.3 修复
/* 修复前 */
HAL_Delay(50); // ← 不够,DHT20 需要 ≥100ms
/* 修复后 */
HAL_Delay(100); // ← Kiro 根据 Datasheet 修正
重新编译、烧录后,如果串口持续输出合理的温湿度值,并且 I2C 状态与 CRC(如启用)均正常,才能确认该问题已解决。DHT20 的有效工作温度范围为 -40°C 至 +80°C,转换公式的理论输出范围不能替代器件工作范围校验。
10.2 场景 2:LCD 花屏
10.2.1 现象
LCD 显示花屏/雪花点;SDRAM 自检通过,但帧缓冲数据错乱。
10.2.2 Kiro 诊断过程
- 核对 SDRAM 数据手册中的刷新周期和各项最小时序;
- 确认 FMC 实际内核时钟、SDCLK 分频和刷新计数公式;
- 确认 STM32H7 HAL 时序结构体接收实际周期数,底层再写入减 1 后的寄存器编码。
修正刷新计数和不满足最小值的时序参数后,应重新执行全地址或抽样读写测试、长时间保持测试和 LCD 连续刷新测试。仅凭一次 SDRAM 自检通过,不能排除边界时序问题。
10.3 AI 辅助调试的作用
| 维度 | 常见人工流程 | Kiro 可辅助的环节 |
| I2C 异常 | 抓取波形并逐页查阅 Datasheet | 检索相关时序、状态位和命令,生成核对清单 |
| LCD 花屏 | 逐项核对时钟、SDRAM、LTDC 和缓存配置 | 关联代码、网表和 Datasheet,提出待验证假设 |
| 定位效率 | 取决于经验、证据完整度和问题复杂度 | 可缩短资料整理时间,但不能替代测量与复测 |
十一、步骤 9:Skills 沉淀——经验固化为团队资产
项目完成后,可以把开发过程中积累的经验整理为 7 个 Skill。下面的代码块按本轮要求保留原始逻辑清单;按照当前 Kiro Skills 规范,实际落盘时每个 Skill 应是一个独立目录,并在目录内包含必需的 SKILL.md,而不是直接把多个 Markdown 文件平铺在 .kiro/skills/ 下。
跨项目复用
这些 Skill 可以作为后续项目的参考,但复用范围取决于 MCU、板卡、外设型号、工具链和软件版本。所有硬件参数在新项目中都应重新验证:
| 场景 | 可参考内容 | 需要补充或复核 |
| 同板子增加 BMP280 | 现有工程结构、I2C 调试流程、构建与烧录方法 | 新增 BMP280 Skill,并核对地址、时序和总线占用 |
| 更换为 STM32F4 | DHT20 协议、FreeRTOS 与 LVGL 的通用方法 | 重新核对时钟、缓存、SDRAM、LCD、DMA 和移植层 |
| 新人接手维护 | 各 Skill 可作为操作与审查入口 | 补充项目架构、版本基线、已知限制和实测记录 |
十二、参考资料
- Kiro Steering 官方文档
- Kiro Specs 官方文档
- Kiro Skills 官方文档
- Amazon S3:启用 EventBridge 事件投递
- Amazon Bedrock Knowledge Bases 文档
- LVGL v8 Tick 接口文档
- STM32H7 HAL FMC 官方源码
- DHT20 Datasheet
十三、总结
13.1 流程对比
| 维度 | 未采用结构化 AI 流程时 | Kiro 可辅助的环节 |
| 硬件理解 | 人工查阅原理图、网表和 Datasheet | 整理连接关系并基于 Datasheet 检索相关段落 |
| 需求文档 | 由团队自行选择文档粒度 | 生成 Spec 初稿和 EARS 风格验收标准 |
| 架构设计 | 依赖人工设计与评审 | 辅助形成 Design 文档、架构图和内存映射草案 |
| 驱动编写 | 人工实现并持续查阅手册 | 生成代码初稿,由工程师审查、测试和修正 |
| 调试定位 | 结合仪器、日志和经验逐项排查 | 汇总证据并生成待验证的根因假设 |
| 经验沉淀 | 通过文档、代码评审和团队培训积累 | 把可复用流程整理为 Skills 并纳入版本管理 |
13.2 流程概览
本文以 9 个步骤介绍了使用 Kiro 辅助完成硬件信息整理、Spec 拆解、代码实现、编译、烧录和调试的一套流程。核心不是让 AI 替代工程师,而是用结构化协作减少资料整理和模板性工作;架构选型、时序计算、代码审查、仪器测量和实机验证仍由工程师负责。
➡️ 下一步行动:
相关产品:
- Amazon S3 — 适用于 AI、分析和存档的几乎无限的安全对象存储
- Amazon EventBridge — 大规模构建事件驱动应用程序
- Amazon Bedrock — 用于构建生成式人工智能应用程序和代理的端到端平台
- Amazon SNS — 发布/订阅和推送通知
- Amazon Step Functions — 分布式应用程序的可视工作流
相关文章:
- AI 时代的 EKS 升级范式:用 Kiro-cli 让 Agent 接管识别、升级与排障
- 构建无服务器Kiro调度平台:用Kiro CLI + EventBridge + ECS Fargate实现定时AI任务
- AI 驱动的跨云网络搭建:用 Claude Code 和 Kiro CLI 实现 AWS-腾讯云 IPSec VPN 双隧道互联
- 用 Kiro Skill 打造你的专属 AI 工作流:以会议纪要自动生成为例
- 从 SDLC 到 AIDLC:CI&T 对 AI 驱动软件开发模式的探索及Kiro最佳实践
*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。
本篇作者
AWS 架构师中心:云端创新的引领者探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用 |
![]() |






