embedded-code-skill

Generate, rewrite, or review embedded C code. Use when creating/rewriting/reviewing embedded C for microcontrollers, drivers, firmware. Triggers automatically when user mentions: generate, create, write code, implement driver, rewrite, refactor, review, check, audit.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "embedded-code-skill" with this command: npx skills add leon-2050/embedded-code-skill

Embedded C 代码生成规范

概述

本规范用于生成生产级嵌入式 C 代码,适用于 STM32、PowerPC、RISC-V 等平台。

核心原则: 像嵌入式软件架构师一样思考,生成可演进、可测试、可移植的代码。


思维方式

生成代码时必须以嵌入式软件架构师的思维进行:

维度要求
系统视角设计可演进的系统,考虑模块边界、接口契约、依赖关系
资源意识内存精确计算缓冲区,CPU 减少中断嵌套,优化关键路径
实时性ISR 应尽可能短,考虑 WCET,防范优先级反转/死锁/队列溢出
可靠性看门狗策略、异常恢复、关键数据冗余存储
硬件无关寄存器抽象为结构体,驱动与业务逻辑分离
可测试公共接口易 mock,状态机可单步测试,边界条件覆盖

编码规范

1. 类型规范

类型用途禁止
uint8_t单字节、GPIOchar, signed char
uint16_t16位寄存器short, unsigned short
uint32_t32位寄存器、时间戳int, long, unsigned int
int32_t有符号值-
uint64_t64位数据-
bool布尔标志-

必须包含的头文件:

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

2. 命名规范

元素格式示例
变量snake_casesensor_value, data_count
全局变量g_snake_caseg_system_ticks
常量/宏SCREAMING_SNAKEMAX_BUFFER_SIZE, SPI_CR_EN
函数camelCaseinitUart(), getSensorData()
结构体类型snake_case_tuart_config_t
枚举类型snake_case_tgpio_state_t
枚举值PREFIXED_SNAKEGPIO_STATE_LOW
指针p_snake_casep_rx_buffer
寄存器结构体module_name_reg_tspi_reg_t
寄存器头文件module_reg.hspi_reg.h

3. 错误处理

所有 public 函数必须:

  1. 返回 embedded_code_status_t 枚举类型
  2. 验证所有输入指针(NULL 检查)
  3. 返回具体错误码
typedef enum {
    EmbedCode_Ok = 0,
    EmbedCode_ErrNullPtr = -1,
    EmbedCode_ErrInvalidArg = -2,
    EmbedCode_ErrTimeout = -3,
    EmbedCode_ErrBusy = -4,
    EmbedCode_ErrNotInit = -5
} embedded_code_status_t;

#define VALIDATE_NOT_NULL(ptr) \
    do { if ((ptr) == NULL) return EmbedCode_ErrNullPtr; } while(0)

4. 注释规范

注释语言: 优先使用中文

原则说明
中文优先便于团队阅读和维护
解释 WHY注释应说明原因和意图,而非描述代码在做什么
代码自说明如果代码本身已清楚表达含义,无需注释

Doxygen 文件头格式:

/**
 * @file spi_reg.h
 * @brief SPI 寄存器结构体定义
 * @author Claude Code
 * @date 2026-04-10
 */

行内注释示例:

config |= SPI_CR_EN_MASK;  /* 启用 SPI,低电平有效 */

5. 寄存器结构体定义

每个外设模块必须有独立的 reg.h 文件:

必需元素说明
XXX_BASE_ADDR基地址定义,格式:XXX_BASE_ADDR
xxx_reg_t寄存器结构体,使用 volatile uint32_t
XXX_XXX_MASK/SHIFT位字段宏定义
XXX_REG结构体指针访问宏

reg.h 模板:

/**
 * @file spi_reg.h
 * @brief SPI 外设寄存器定义
 */
#ifndef SPI_REG_H
#define SPI_REG_H

#include <stdint.h>

/* 基地址 */
#define SPI_BASE_ADDR  (0xA0010000U)

/* 寄存器结构体 */
typedef struct {
    volatile uint32_t CTRL;     /* 0x00: 控制寄存器 */
    volatile uint32_t STATUS;   /* 0x04: 状态寄存器 */
    volatile uint32_t DATA;     /* 0x08: 数据寄存器 */
} spi_reg_t;

/* 位字段定义 */
#define SPI_CTRL_EN_MASK      (1U << 0)
#define SPI_CTRL_MODE_MASK    (3U << 2)

/* 寄存器访问 */
#define SPI_REG  ((spi_reg_t *) SPI_BASE_ADDR)

#endif /* SPI_REG_H */

6. 寄存器赋值规范

禁止直接赋字面值,必须使用已定义的宏:

// ❌ 错误
SPI_REG->CTRL = 0x47U;
SPI_REG->BAUD = 250U;

// ✅ 正确
SPI_REG->CTRL = SPI_CTRL_INIT_VAL;
SPI_REG->BAUD = SPI_BAUD_DIV;

7. 安全编码

禁止必须
malloc, free, calloc, realloc固定大小缓冲区
new, delete环形缓冲区用于数据流
VLA (变长数组)精确计算的缓冲区大小
#define BUFFER_SIZE 256U
uint8_t buffer[BUFFER_SIZE];

8. 数据结构

场景方式
相关配置数据struct
相关常量集合enum
相关状态数据struct
/* 配置结构体 */
typedef struct {
    uint32_t base_address;
    uint16_t interrupt_priority;
    bool     enable_dma;
} peripheral_config_t;

/* 句柄结构体 */
typedef struct {
    bool                initialized;
    peripheral_config_t config;
} peripheral_handle_t;

工作模式

GENERATE 模式

直接应用本规范生成代码,无需保留任何旧代码。

REWRITE 模式

核心原则: 功能流程优先

⚠️ 用户提供的源代码代表着原有的功能实现流程。即使代码有错误,在修改前必须先完整理解其功能流程,再进行符合规范的改写。不得为符合规范而破坏原有的功能流程。

执行步骤:

步骤内容
Step 1: 理解原代码梳理数据流、识别状态机/算法、标注寄存器操作
Step 2: 识别重写部分确定需重构的函数/模块
Step 3: 按规范重写类型/命名/结构体符合规范,功能逻辑保持一致
Step 4: 回查验证验证功能流程未改变,所有规范已满足

关于原代码中的 bug:

  • 原代码的 bug 属于"功能流程"的一部分
  • 如果 bug 是用户期望保留的行为(如已知的工作around),保持原样
  • 如果原代码有语法错误无法编译,标注问题但不擅自修复
  • 除非用户明确要求,否则不修改原代码的功能逻辑

REVIEW 模式

检查现有代码是否符合嵌入式 C 规范。

执行步骤:

步骤内容
Step 1: 对照检查按回查清单逐项检查
Step 2: 标注问题列出不符合规范的地方
Step 3: 提出建议提供具体的修改建议

项目文件结构

project/
├── inc/
│   ├── module_reg.h      # 寄存器结构体定义(每个外设必须有)
│   ├── module_config.h   # 配置参数
│   └── module.h          # 公共接口
└── src/
    └── module.c          # 实现

PDCA 工作流

┌─────────────────────────────────────────────────────────┐
│  P (Plan) - 分析需求,检查完备性                         │
│    • 确定模式: GENERATE / REWRITE / REVIEW              │
│    • 检测领域/架构/外设关键词                            │
│    • 检查关键信息是否完备(基地址等)                     │
│    ⚡ REWRITE模式: 优先理解原代码功能流程                │
├─────────────────────────────────────────────────────────┤
│  D (Do) - 生成/重写代码                                 │
│    • GENERATE: 直接应用本规范                           │
│    • REWRITE: 保持原功能流程,应用本规范                 │
│    • 创建或更新 reg.h 寄存器结构体定义                   │
│    • 生成符合规范的代码                                  │
├─────────────────────────────────────────────────────────┤
│  C (Check) - 回查验证                                   │
│    • 对照回查清单逐项检查                               │
│    • 验证寄存器结构体定义是否正确                        │
│    ⚡ REWRITE模式: 验证功能流程是否保持一致             │
├─────────────────────────────────────────────────────────┤
│  A (Act) - 修正输出                                     │
│    • 修正所有发现的问题                                  │
│    • 重新回查确认                                       │
│    • 输出合格代码                                        │
└─────────────────────────────────────────────────────────┘

回查清单

生成后必须逐项检查:

#检查项不合格则修正
1是否有对应的 reg.h 文件?创建 reg.h
2寄存器是否用 volatile uint32_t 结构体定义?重构为结构体
3位字段是否有宏定义 (MASK/SHIFT)?添加位字段宏
4类型是否仅用 stdint.h?替换所有非标准类型
5命名是否符合规范表?修正所有命名
6所有 public 函数有错误处理?添加状态返回
7无任何 malloc/free/VLA?替换为固定缓冲区
8注释是否使用中文?重写注释
9文件头是否完整 (Doxygen)?添加 Doxygen
10生成的代码是否符合规范?修正生成代码
⚡ 11REWRITE 模式: 原代码的功能流程是否保持一致?确保数据流/状态机/算法逻辑不变
⚡ 12寄存器赋值是否都使用宏?添加宏定义,禁止字面值赋值

常见错误

错误 1: 寄存器定义散落各处

// ❌ 错误
#define SPI_CTRL_ADDR  (*(volatile uint32_t *)0xA0010000)
void spiInit(void) { SPI_CTRL_ADDR = 0x47; }

// ✅ 正确 - 独立的 reg.h,统一的命名风格
#include "spi_reg.h"
void spiInit(void) { SPI_REG->CTRL = SPI_CTRL_INIT_VAL; }

错误 2: 魔法数字

// ❌ 错误 - 含义不清
if (SPI_REG->STATUS & 0x04) { }
SPI_REG->CTRL |= (1U << 7);

// ✅ 正确 - 命名位字段宏
if (SPI_REG->STATUS & SPI_STATUS_TF_EMPT_MASK) { }  /* TX FIFO empty */
SPI_REG->CTRL |= SPI_CTRL_SCPOL_MASK;               /* 时钟极性 */

错误 3: 使用 __I/__IO 前缀

// ❌ 错误 - ARM CMSIS 特有,不具可移植性
typedef struct {
    __I uint32_t DATA;
    __IO uint32_t CTRL;
} spi_reg_t;

// ✅ 正确 - 标准 volatile
typedef struct {
    volatile uint32_t DATA;
    volatile uint32_t CTRL;
} spi_reg_t;

错误 4: 直接赋字面值

// ❌ 错误 - 魔法数字
SPI_REG->BAUD = 250U;
SPI_REG->CTRL = 0x08U;

// ✅ 正确 - 使用宏定义
SPI_REG->BAUD = SPI_BAUD_DIV;
SPI_REG->CTRL = SPI_CTRL_INIT_VAL;

输出格式

GENERATE 模式输出每个外设模块:

module/
├── module_reg.h    # 寄存器结构体定义
├── module.h        # 公共接口
└── module.c       # 实现

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

Embedded Dev

单片机嵌入式全栈开发技能,覆盖从底层硬件到上层应用的全链路技术问题。当用户询问嵌入式开发、微控制器、RTOS、电机控制、传感器接口、固件编写、调试上线等任何软硬件相关问题时应调用此技能。

Registry SourceRecently Updated
2060Profile unavailable
General

Framebuffer Dump

Dump the current STM32 LCD framebuffer via J-Link and convert it to PNG for visual comparison with Figma. Use when user asks to export, snapshot, dump, or ca...

Registry Source
2730Profile unavailable
Coding

Qwen ASR (C-based Offline)

Offline Chinese and mixed Chinese-English speech-to-text recognition in pure C without Python or FFmpeg dependencies, suitable for edge devices.

Registry SourceRecently Updated
2490Profile unavailable
Coding

Rdk X5 Media

RDK X5 多媒体处理:音频录制/播放(arecord/aplay/PulseAudio)、hobot_codec 视频编解码、RTSP 拉流/推流、HDMI 分辨率配置、MIPI LCD 触摸屏适配、VNC 远程桌面服务端安装与配置。Use when the user wants to record or p...

Registry SourceRecently Updated
2800Profile unavailable