版本:v1.0.0
状态:已实现(Python CLI 工具,约 70% 设计覆盖率)
适用范围:C 语言嵌入式工程(STM32 / 51 / ESP32 / Linux / 裸机)
实现路径.trae/skills/keyflow-integrator/keyflow_integrator.py(1019 行)


1. Skill 定位与目标

Skill 名称keyflow-integrator

核心能力:让 Agent 在任意嵌入式/C 工程中,一键完成:

  1. Install(安装) — 将 keyflow 的核心代码作为子模块/拷贝集成到项目
  2. Configure(配置) — 选择硬件平台(STM32 / 51 / ESP32 / Linux / 裸机)、分配 GPIO 引脚
  3. Integrate(对接) — 生成按键配置表、回调函数、扫描周期配置,并与业务逻辑对接
  4. Verify(验证) — 生成最小可运行示例/测试代码,编译并输出验证报告

设计原则

  • 零破坏性:不会删除/重写用户代码,仅在必要处追加最小补丁
  • 可回滚:所有修改前自动备份关键文件为 .bak
  • 显式决策:存在歧义时(如引脚选择、按键数量),必须通过对话明确而非猜测
  • 幂等:同一项目多次执行不产生重复代码

2. 输入 / 输出契约

2.1 用户输入(自然语言或结构化描述)

project:
  path: /absolute/path/to/project     # 用户工程根目录
  build_system: make|cmake|keil|iar|other  # 构建系统
  platform: stm32|51|esp32|linux|baremetal
  compiler: armcc|gcc|sdcc|other
  button_count: <N>                       # 按键数量
  button_list:                           # (可选)按键描述列表
    - name: "KEY_OK"
      pin: "GPIOA,5"                     # 或自定义描述
      active_level: low                   # low / high
      debounce_ms: 15
      long_press_ms: 1000
      event_handler: "on_ok_pressed"      # 业务回调函数名
    - ...
  scan_period_ms: 10                      # 主循环扫描周期
  features:                               # 需要启用的扩展模块
    - matrix_keypad: {rows: 4, cols: 4}  # (可选)矩阵键盘
    - exti_driven                         # (可选)中断驱动
    - event_queue                         # (可选)事件队列
    - combo_keys                          # (可选)组合键
  integration_style: table_driven         # table_driven(推荐) | manual
  code_output_dir: src/app/buttons        # 生成文件输出目录
  business_hooks:                         # 业务层回调映射
    - event: PRESSED
      handler: "app_on_button_pressed(idx)"
    - event: LONG_PRESS
      handler: "app_on_button_long_press(idx)"

2.2 Skill 输出

files_created:
  - /project/src/app/buttons/keyflow_config.h        # 按键配置表 + 回调声明
  - /project/src/app/buttons/keyflow_integration.c   # glue code(初始化 + 扫描循环)
  - /project/src/app/buttons/keyflow_port.c          # 平台端口实现(GPIO 读写)
  - /project/src/app/buttons/README.md              # 说明文档(中文,自动生成)
files_modified:
  - Makefile 或 CMakeLists.txt                       # 追加 keyflow 源码路径
  - main.c / xxx_init.c                              # 追加初始化调用
verification:
  - build_status: success|failed
  - test_output: "7/7 tests passed"

3. 核心流程设计(5 阶段)

阶段 1:项目探查(Exploration)

目标:在不修改任何文件的前提下,识别工程结构与约定。

探查内容

探查项 探查方法 示例
构建系统 ls *.c Makefile CMakeLists.txt project.uvprojx 识别为 Make / CMake / Keil
源码目录结构 find . -name "*.c" -type d | head -30 src/ app/ main hw/
头文件目录 定位 #include 模式 #include "stm32f1xx_hal.h" / #include "main.h"
GPIO HAL 接口类型 grep -rn "HAL_GPIO|digitalRead|P1\s*&\s*(1|PORT_WritePin" src 判断 STM32 HAL / Arduino / 51 / ESP-IDF / Linux sysfs
主循环入口 grep -n "while\s*(\s*1\s*)|main\s*(" src/main* 定位扫描代码放入何处
已有按键代码 grep -rn "button|key|按键" src/ 判断是否需要迁移已有按键
编译器/平台 从 Makefile / CMakeLists.txt 中提取 arm-none-eabi-gcc / sdcc / gcc

输出:结构化 JSON project_profile.json(仅内存使用,不写文件)

阶段 2:安装(Installation)

目标:把 keyflow 源码按工程约定放置。

安装策略(二选一)

策略 适用场景 操作
A. Git 子模块 Git 仓库已初始化 git submodule add keyflow 仓库到 third_party/keyflow/
B. 文件拷贝 非 Git / 简单工程 拷贝 include/button/*.hsrc/button/*.cthird_party/keyflow/

安装产物位置约定

project/
├── third_party/
│   └── keyflow/                     ← keyflow 完整仓库或仅需要的文件
│       ├── include/button/*.h
│       └── src/button/*.c
└── src/app/buttons/                 ← Skill 生成的 glue code(见阶段 4)

CMake/Makefile 修改策略

  • CMake 工程:在顶层 CMakeLists.txt 追加 add_subdirectory(third_party/keyflow/src/button)target_link_libraries(your_app keyflow::button)(demo 可选项,与 keyflow 当前项目类似)
  • Makefile 工程:定义 BUTTON_DIR := third_party/keyflow,在 SRCS += ... 追加 $(BUTTON_DIR)/src/button/*.c,并 CFLAGS += -I$(BUTTON_DIR)/include
  • Keil/IAR:基于 .uvprojx / .ewp 添加源文件条目(XML 解析/追加)

阶段 3:配置(Configuration)

目标:根据探查结果,生成 keyflow_port.c

平台判定规则

平台 判定条件 生成内容
STM32 包含 stm32fxxx_hal.h 头文件 ButtonPort_ReadPin 实现 → HAL_GPIO_ReadPinGetTickMsHAL_GetTick
51 单片机 包含 reg51.h / stc*.h,且编译器为 sdcc/keil c51 P1 & (1 << pin) 方式;GetTickMs → 基于定时器 systick
ESP32 包含 freertos/FreeRTOS.h / driver/gpio.h gpio_get_level(pin)GetTickMsxTaskGetTickCount * portTICK_PERIOD_MS
Linux 包含 unistd.h 且无 MCU 头文件 Linux sysfs GPIO 或 /dev/gpiochipN
裸机 以上均不满足 生成模板 + extern uint32_t SystemTick;

引脚抽象约定

引脚编码 port_pin_codeuint16_t,高 8 位为 port(如 A=0, B=1, …),低 8 位为 pin 编号。

阶段 4:对接(Integration)

核心生成策略

A. 生成配置表(keyflow_config.h + keyflow_integration.c
/* 示例(STM32) */
static ButtonManager g_keyflow_mgr;

/* 按键配置表 — 从用户输入的 button_list 转换而成 */
static const KeyflowEntry s_keyflow_keys[] = {
    {
        .cfg = {
            .pin = KEYFLOW_MAKE_PIN(KEYFLOW_PORT_A, 5),  /* GPIOA,5 */
            .active_level = 0,                           /* 低电平有效 */
            .debounce_ms = 15,
            .release_debounce_ms = 15,
            .long_press_ms = 1000,
            .double_click_ms = 250,
            .stable_cnt_required = 2,
            .long_press_repeat_ms = 0,
        },
        .name = "KEY_OK",
        .on_pressed      = app_on_key_ok_pressed,
        .on_long_press   = app_on_key_ok_long_press,
        .on_clicked      = app_on_key_ok_clicked,
    },
    /* ... more keys ... */
};

/* 统一事件分发回调 */
static void keyflow_event_cb(Button *btn, ButtonEventType ev, void *ud) {
    const KeyflowEntry *entry = (const KeyflowEntry *)ud;
    switch (ev) {
    case BUTTON_EVENT_PRESSED:
        if (entry->on_pressed) entry->on_pressed(entry->idx);
        break;
    case BUTTON_EVENT_LONG_PRESS:
        if (entry->on_long_press) entry->on_long_press(entry->idx);
        break;
    /* ... other events ... */
    }
}

/* 初始化 */
void keyflow_init(void) {
    ButtonManager_Init(&g_keyflow_mgr);
    for (int i = 0; i < ARRAY_SIZE(s_keyflow_keys); ++i) {
        ButtonManager_AddButton(&g_keyflow_mgr,
                                s_keyflow_keys[i].cfg,
                                keyflow_event_cb,
                                &s_keyflow_keys[i]);
    }
}

/* 主循环扫描 — 用户在主循环调用 */
void keyflow_task(void) {
    ButtonManager_UpdateAuto(&g_keyflow_mgr);
}
B. 矩阵键盘 / 中断驱动 / 事件队列 / 组合键

若用户在 features 中声明启用,分别生成:

功能 生成文件 核心内容
矩阵键盘 keyflow_matrix.c MatrixKeyScanner 初始化 + MatrixKey_Scan 在扫描任务内调用
中断驱动 keyflow_exti.c ExtiButton_OnInterrupt() 在 EXTI ISR 中调用,ExtiButton_Dispatch() 在主循环调用
事件队列 keyflow_queue.c ButtonEventQueue_Push 回调 + 主循环 ButtonEventQueue_Pop
组合键 keyflow_combo.c ComboKeyDetector 初始化 + 修饰键掩码匹配表
C. 业务层对接

business_hooks 中列出的业务函数,生成弱符号(__attribute__((weak)))或 extern 声明,让业务层自行实现:

/* keyflow_integration.h — 业务层需实现的回调 */
extern void app_on_key_ok_pressed(uint8_t idx);
extern void app_on_key_ok_long_press(uint8_t idx);
/* ... */

阶段 5:验证(Verification)

验证步骤

  1. 生成最小可运行示例 keyflow_demo.c — 单按键 + 长按连发测试
  2. 构建验证:执行用户项目的构建命令,捕获错误并仅打印,不修改非必要代码
  3. 静态检查gcc -Wall -Wextra -fsyntax-only 语法检查(不链接)
  4. 日志输出验证报告keyflow_integration_report.md — 中文,列出:按键数、事件类型、回调函数、编译状态、测试输出

3.6 实现状态对照

设计要求 实现状态 说明
Phase 1: 项目探查 ✅ 完全实现 explore_project() 扫描构建系统/平台/GPIO HAL/main 入口
Phase 2: 源码安装 ✅ 实现 支持 copy-localgit-submodule 两种方式
Phase 3: 端口生成 ✅ 完全实现 5 个平台模板(STM32/51/ESP32/Linux/baremetal)
Phase 4a: 配置表生成 ✅ 完全实现 动态生成按键配置表 + 弱符号回调声明
Phase 4b: 集成代码 ✅ 完全实现 模板包含 init + 循环注册 + 统一事件分发
Phase 4c: 扩展模块 ✅ 完全实现 matrix/exti/queue/combo 4 个独立模板
Phase 4d: Demo 示例 ✅ 完全实现 mock 端口注入 + 短按/长按自测试
Phase 5: 编译验证 ⚠️ 部分实现 Linux/baremetal 执行 gcc 语法检查,其他平台仅文件检查
Phase 0: Git 分支隔离 ✅ 完全实现 自动创建 feature 分支,失败可回滚
CMake/Makefile 修改 ❌ 未实现 需用户手动将生成的 .c 文件添加到编译列表
main.c 注入调用 ❌ 未实现 需用户手动在 main 中添加 keyflow_init()keyflow_task()
.bak 备份策略 ❌ 未实现 改用 Git 分支隔离替代
交互式模式 ❌ 未实现 当前仅支持命令行参数
幂等性检测 ⚠️ 部分实现 检测已存在目录时警告并覆盖,但不检测重复注册

当前版本使用须知:集成完成后,用户需手动完成两步:

  1. src/third_party/keyflow/ 下的 .c 文件添加到编译系统(CMakeLists.txt / Makefile)
  2. 在 main 函数中调用 keyflow_init()keyflow_task()

3.7 实际文件结构

.trae/skills/keyflow-integrator/
├── SKILL.md                              # Skill 使用说明
├── keyflow_integrator.py                 # 核心实现(1019 行)
└── templates/
    ├── keyflow_config_template.h         # 按键配置表模板
    ├── keyflow_integration_template.c    # init + task 集成模板
    ├── keyflow_port_stm32_template.c     # STM32 HAL 端口
    ├── keyflow_port_51_template.c        # 51 单片机端口
    ├── keyflow_port_esp32_template.c     # ESP32 IDF 端口
    ├── keyflow_port_linux_template.c     # Linux sysfs GPIO 端口
    ├── keyflow_port_baremetal_template.c # 裸机/自定义端口
    ├── keyflow_matrix_template.c         # 矩阵键盘扩展
    ├── keyflow_exti_template.c           # 中断驱动扩展
    ├── keyflow_queue_template.c          # 事件队列扩展
    ├── keyflow_combo_template.c          # 组合键/序列键扩展
    └── keyflow_demo_template.c           # 最小可运行示例

4. 安全性与幂等性设计

风险 防护策略
重复安装 third_party/keyflow/ 已存在时跳过安装,仅提示更新
重复生成 src/app/buttons/ 已存在时先 .bak 备份再覆盖,或提示用户选择覆盖/跳过
破坏已有按键实现 先扫描 grep -rn "button|key",若已存在按键代码,不删除仅追加补丁:把新实现放在独立目录,并在 README 中说明迁移建议
路径不完整 所有路径相对 project.path
Git 未初始化 B 策略(文件拷贝)自动降级
平台识别失败 生成模板占位符代码 + 在验证阶段提供多平台模板,让用户手动选择
业务回调不存在 弱符号 + 编译链接警告,验证阶段输出缺失列表

5. 示例运行流程(伪代码)

┌────────────────────────────────────────────┐
│ 用户输入:"把 keyflow 装到 /my_project"      │
└────────────────────────────────────────────┘
               │
               ▼
┌────────────────────────────────────────────┐
│ Phase 1: 项目探查(read-only)              │
│   - ls /my_project                         │
│   - grep 构建系统 / GPIO 头文件 / 按键关键字 │
│   输出: project_profile = {                │
│       build_system: cmake,                 │
│       platform: stm32,                     │
│       compiler: arm-none-eabi-gcc          │
│   }                                         │
└────────────────────────────────────────────┘
               │
               ▼
┌────────────────────────────────────────────┐
│ Phase 2: 安装 keyflow                       │
│   - git submodule add keyflow 到 third_party/│
│   或: cp keyflow/include/button/*.{h,c}    │
│   - CMakeLists.txt 追加 add_subdirectory    │
│   或: Makefile 追加 BUTTON_DIR + CFLAGS    │
└────────────────────────────────────────────┘
               │
               ▼
┌────────────────────────────────────────────┐
│ Phase 3: 生成端口                          │
│   - 生成 keyflow_port.c(基于 platform)    │
│   - 生成 keyflow_config.h(按键配置表)     │
│   - 生成 keyflow_integration.c(主循环扫描) │
│   - 生成 keyflow_<feature>.c(扩展模块)    │
└────────────────────────────────────────────┘
               │
               ▼
┌────────────────────────────────────────────┐
│ Phase 4: 业务对接                          │
│   - 生成 business_hooks → 弱符号 extern    │
│   - 让用户实现业务回调                      │
└────────────────────────────────────────────┘
               │
               ▼
┌────────────────────────────────────────────┐
│ Phase 5: 验证                              │
│   - cmake --build .                        │
│   - 语法检查                               │
│   - 生成验证报告 keyflow_integration_report.md │
└────────────────────────────────────────────┘
               │
               ▼
         ┌────────────────┐
         │   完成!       │
         └────────────────┘

6. 文件命名约定(与当前 keyflow 项目保持一致)

生成文件 路径(相对 project.path) 说明
keyflow_config.h src/app/buttons/ 按键配置表 + 回调声明
keyflow_port.c src/app/buttons/ GPIO 读写 + 时间戳
keyflow_integration.c src/app/buttons/ 初始化 + 主循环扫描
keyflow_demo.c src/app/buttons/ 最小可运行示例
keyflow_integration_report.md src/app/buttons/ 中文验证报告

7. 与当前 keyflow 项目的接口映射

keyflow API Skill 生成的 glue code
ButtonConfig keyflow_config.h → 结构体数组
ButtonManager_Init keyflow_integration.ckeyflow_init()
ButtonManager_AddButton keyflow_integration.c → 循环注册
ButtonManager_UpdateAuto keyflow_task()
MatrixKey_Init / Scan keyflow_matrix.c → 矩阵键盘
ExtiButton_OnInterrupt / Dispatch keyflow_exti.c → 中断驱动
ButtonEventQueue_Init / Push / Pop keyflow_queue.c → 事件队列
ComboKey_Init / Detect keyflow_combo.c → 组合键 / 序列键

8. 错误处理与用户交互策略

场景 Skill 行为 对用户的反馈
无法识别构建系统 停止并询问 “你的工程使用什么构建系统?(make/cmake/keil/…)”
无法识别平台 停止并询问 “你的目标硬件平台是?(stm32/51/esp32/linux/baremetal)”
button_list 为空 询问并生成参考 “请描述你的按键列表(名称/引脚/有效电平/消抖/长按阈值/回调函数名)”,或默认 3 按键示例
GPIO 语法无法解析 把 pin 标记为"需手动确认" 在报告中列出所有"需手动确认的 pin 映射"
编译失败 不修改代码,打印完整编译日志 “编译失败,错误日志已输出”

9. 回滚策略

  • 每次执行前自动:

    1. 备份 CMakeLists.txt / Makefile.bak
    2. 备份 src/app/buttons/ 若已存在 → .bak/
    3. 记录操作日志 keyflow_integration.log
  • 回滚命令(Skill 可执行):若用户说"撤销刚才的操作",执行 git checkout -- <files>mv .bak 文件恢复


10. Skill 元数据

skill:
  name: keyflow-integrator
  version: 1.0.0
  description: 将 keyflow 按键模块安装到目标 C/嵌入式工程,并生成配置表、端口抽象、业务对接代码与验证报告
  inputs:
    - 项目路径(绝对路径)
    - 构建系统(make/cmake/keil/iar/other)
    - 平台(stm32/51/esp32/linux/baremetal)
    - 按键数量 + 按键描述列表(可选)
    - 启用的扩展功能(矩阵/中断/事件队列/组合键)
    - 业务回调函数映射(可选)
  outputs:
    - third_party/keyflow/ 源码
    - src/app/buttons/*.{h,c} 业务对接代码
    - 修改后的构建文件(CMake/Makefile)
    - 中文集成报告 keyflow_integration_report.md

11. 与 keyflow 当前代码的关联

Skill 在生成代码时,严格遵循 keyflow 当前项目中 include/button/button.h 的 API 契约,不做任何 API 扩展或修改。生成的 glue code 仅做三件事:

  1. 调用现有 API
  2. 把业务层的业务逻辑通过回调与 keyflow 事件分发器连接
  3. 为目标平台实现 ButtonPort_* 的具体实现

实际实现中的关键映射:

keyflow API 模板中使用方式 模板文件
ButtonConfig keyflow_config_template.h → 结构体数组 keyflow_config_template.h
ButtonManager_Init keyflow_integration_template.ckeyflow_init() keyflow_integration_template.c
ButtonManager_AddButton 循环注册 + keyflow_event_cb 统一分发 keyflow_integration_template.c
ButtonManager_UpdateAuto keyflow_task() 中调用 keyflow_integration_template.c
ButtonPort_ReadPin/WritePin/GetTickMs 5 个平台模板分别实现 keyflow_port_*.c
MatrixKey_* / ExtiButton_* / ButtonEventQueue_* / ComboKey_* 4 个扩展模块独立实现 keyflow_*_template.c

12. 设计确认记录

以下为设计阶段提出的待确认事项及其最终处理结果:

# 待确认事项 最终决策 实现情况
1 Skill 名称 keyflow-integrator 已采用
2 生成文件位置 src/third_party/keyflow/(源码)+ src/app/buttons/(glue code)✅ 已调整路径约定
3 业务回调策略 弱符号 extern 声明 ✅ 已实现
4 扩展模块策略 用户声明时才生成 ✅ 已实现(4 个独立模板)
5 验证深度 仅编译 + 日志输出 ✅ 已实现(gcc 语法检查)
6 备份策略 Git 分支隔离替代 .bak 已实现(feature/keyflow-integration-<timestamp>

尚未实现的设计项(待后续版本补充):

  • CMake/Makefile 自动修改
  • main.c 自动注入 keyflow_init() / keyflow_task()
  • 交互式参数收集模式

项目仓库

免责声明

本文内容仅作为技术研究与学习交流之用,不构成任何形式的产品设计建议、电子工程建议或商业推荐。文中涉及的代码片段、状态机模型、消抖策略等技术方案,基于特定嵌入式场景与硬件条件设计,直接用于生产环境前请务必进行充分的测试与验证

使用本文内容所导致的任何直接或间接后果(包括但不限于设备损坏、数据丢失、商业损失等),作者及 AZE-BlackCore 不承担任何责任。 请根据你的实际项目需求,结合硬件手册、行业规范与最佳实践进行独立判断和决策。

版权声明:本文版权归 AZE-BlackCore 所有,转载请注明出处。封面与示意图由 AI 生成,仅供示意参考。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐