plugins/languages/c/skills/embedded/SKILL.md
C embedded firmware conventions: memory-mapped I/O with volatile structs, short ISR with main-loop hand-off, MISRA C:2023 (incl. AMD4 atomics/concurrency guidance) compliance, static-only allocation strategies (pools, bitfields, unions, static buffers), Flash/RAM/stack budgeting, and bare-metal critical-section primitives. Use when writing MCU firmware, drivers, RTOS tasks, or any resource-constrained C. Triggers on "MCU", "嵌入式 C", "ISR", "中断处理", "volatile 寄存器", "MISRA", "静态分配", "no malloc", "bare metal", "Cortex-M", "RTOS".
npx skillsauth add lazygophers/ccplugin c-embeddedInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
malloc / calloc / realloc / free);改用静态池 / 栈 / arena。volatile。disable_irq / restore_irq 显式保护;时间窗最小化。-fstack-usage)。const,链接器放入 Flash 段。| 规则 | 说明 | 等级 |
|------|------|------|
| Dir 4.1 | 最小化运行时错误 | Mandatory |
| Rule 1.3 | 无未定义 / 关键未指定行为 | Required |
| Rule 2.2 | 无死代码 | Required |
| Rule 10.x | 类型转换必须显式且不窄化 | Required |
| Rule 11.3 | 指针类型转换不改变指向对象类型 | Required |
| Rule 17.7 | 非 void 返回值不可丢弃 | Required |
| Rule 21.3 | 不使用 malloc / free 等动态内存 | Required |
| Rule 21.6 | 不使用 <stdio.h> 标准 I/O | Advisory |
| AMD4 Rule 22.x | 原子 / 多线程使用规范(C11 _Atomic) | Required(启用后) |
工具链:Cppcheck --addon=misra、PC-lint Plus、Coverity、Polyspace、ECLAIR。
typedef struct {
volatile uint32_t CR;
volatile uint32_t SR;
volatile uint32_t DR;
uint32_t _rsv;
volatile uint32_t BRR;
} UART_TypeDef;
#define UART1 ((UART_TypeDef *)0x40011000U)
#define BIT_SET(r, b) ((r) |= (1U << (b)))
#define BIT_CLR(r, b) ((r) &= ~(1U << (b)))
#define BIT_GET(r, b) (((r) >> (b)) & 1U)
static volatile bool rx_ready;
static volatile uint8_t rx_byte;
void UART1_IRQHandler(void) {
if (UART1->SR & (1U << 5)) { // RXNE
rx_byte = (uint8_t)UART1->DR; // 读 DR 清 flag
rx_ready = true;
}
}
int main(void) {
for (;;) {
if (rx_ready) { rx_ready = false; on_byte(rx_byte); }
__asm__ volatile ("wfi");
}
}
static inline uint32_t irq_save(void) {
uint32_t p; __asm__ volatile ("mrs %0, primask\n\tcpsid i" : "=r"(p));
return p;
}
static inline void irq_restore(uint32_t p) {
__asm__ volatile ("msr primask, %0" :: "r"(p) : "memory");
}
C11 _Atomic 也可用于 ISR ↔ 主循环单字共享(按 MISRA AMD4 章节使用)。
#define POOL_N 8
#define BUF_SZ 128
static uint8_t pool[POOL_N][BUF_SZ];
static bool used[POOL_N];
uint8_t *buf_alloc(void) {
for (int i = 0; i < POOL_N; i++)
if (!used[i]) { used[i] = true; return pool[i]; }
return NULL;
}
void buf_free(uint8_t *p) {
for (int i = 0; i < POOL_N; i++)
if (pool[i] == p) { used[i] = false; return; }
}
// const 进 Flash
__attribute__((section(".rodata")))
static const uint8_t lut[256] = { /* ... */ };
// 位域压缩
struct Flags {
unsigned enabled : 1;
unsigned mode : 3;
unsigned error : 1;
unsigned ready : 1;
unsigned _rsv : 2;
};
static_assert(sizeof(struct Flags) == 1, "1 byte");
// 联合体复用
union Msg {
struct { uint16_t id; uint8_t d[6]; } can;
struct { uint8_t a, r; uint16_t v; } i2c;
uint8_t raw[8];
};
// 大缓冲区放 BSS,不占栈
void task(void) { static uint8_t big[1024]; /* ... */ }
工具:-fstack-usage + arm-none-eabi-size,对每个 ISR / 任务函数做最坏栈分析。
需要 volatile:
volatile uint32_t *const)setjmp/longjmp 间需保留的局部变量sig_atomic_t)不需要:
_Atomic 的变量(语义重叠)# 大小报告
arm-none-eabi-size -A -d build/firmware.elf
# 最坏栈
gcc -fstack-usage -c src/foo.c # 产 src/foo.su
# 静态分析
cppcheck --addon=misra --std=c17 src/
malloc / free / 动态分配volatile-Wconversion -Wsign-conversion -Wshadow 通过-fstack-usage — https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.htmldevelopment
Go 数据库规范——GORM Model 命名 ModelXxx、表名单数、枚举 uint8 + 常量、索引 idx_ 前缀 + deleted_at leading column、禁 time.Time 统一 int64 unix、禁指针/nullable 字段、TEXT/BLOB/JSON 禁 default、AutoMigrate 禁改主键。设计 DB model、写 GORM tag、建索引、做 migration 审查时触发。
development
Go HTTP API 规范——响应始终 200 + body code 字段、路由 /api/* 全 POST 单段 <Action><Model>、中间件逐路由注册禁 Group(prefix,mw...)、handler 仅返回 (rsp,error)、认证走 header。设计 HTTP API、写路由/handler/中间件时触发。
development
Go 项目结构规范——三层架构(API → Impl → State)、全局状态模式、internal/ 私有包、cmd/ 仅 main.go、go.work 多模块、禁止 Repository 接口和 DI 容器、struct 公共字段开头全 omitempty、handler var rsp 顶声明、禁 legacy migration。设计项目骨架、新建目录、组织包、做架构评审时触发。
development
Go 命名规范——Id/Uid 字段(非 ID)、IsActive/HasMFA 布尔前缀、CreatedAt 时间字段、接收者统一用 p、包名全小写无下划线、泛型类型参数描述性命名、集合字段 xxx_list 禁 xxxs 复数、Enum 0 值 XxxNil 禁 Unknown、禁 Status 统一 State、Set/Update 语义区分。定义结构体字段、函数、变量、包、接收者名、泛型、枚举时触发。