peripherals-from-datasheet
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePeripherals from Datasheet
基于数据手册的外设驱动开发
Purpose
目的
Guide agents through a repeatable methodology for writing peripheral drivers from MCU reference manuals: locating register maps, interpreting bit definitions, following init sequences, respecting timing constraints, and producing maintainable register-level code. Pair with for doc-navigation methodology (kept as separate skills).
skills/baremetal/datasheet-and-refmanual-reading指导Agent掌握从MCU参考手册编写外设驱动的可复用方法论:定位寄存器映射、解析位定义、遵循初始化序列、遵守时序约束,并编写可维护的寄存器级代码。可搭配技能使用,后者专注于文档导航方法论(两者为独立技能)。
skills/baremetal/datasheet-and-refmanual-readingWhen to Use
适用场景
- Starting a driver without vendor HAL
- Porting a peripheral between MCU families
- Verifying HAL behavior against the reference manual
- Debugging a peripheral that "should work" per examples
- 无厂商HAL支持时开发驱动
- 在不同MCU系列间移植外设驱动
- 对照参考手册验证HAL的行为
- 调试那些“按示例本应正常工作”的外设问题
Workflow
工作流程
1. Reference manual navigation
1. 参考手册导航
Typical RM structure
├── Memory map (peripheral base addresses)
├── Peripheral chapter (UART, SPI, GPIO, ...)
│ ├── Functional description
│ ├── Register map (table of offsets)
│ ├── Register bit definitions
│ └── Timing / electrical notes
└── Electrical characteristics (clock limits, setup/hold)Start with the programming model section before copying register writes.
典型RM结构
├── 内存映射(外设基地址)
├── 外设章节(UART、SPI、GPIO等)
│ ├── 功能描述
│ ├── 寄存器映射(偏移量表)
│ ├── 寄存器位定义
│ └── 时序/电气说明
└── 电气特性(时钟限制、建立/保持时间)在复制寄存器写入代码前,先从编程模型部分开始阅读。
2. Extract register map
2. 提取寄存器映射
c
/* From RM — USART base 0x40004400 */
typedef struct {
volatile uint32_t SR; /* 0x00 status */
volatile uint32_t DR; /* 0x04 data */
volatile uint32_t BRR; /* 0x08 baud */
volatile uint32_t CR1; /* 0x0C control */
/* ... */
} USART_TypeDef;
#define USART2 ((USART_TypeDef *)0x40004400UL)Verify offset column matches struct layout (padding for reserved words).
c
/* 来自RM — USART基地址0x40004400 */
typedef struct {
volatile uint32_t SR; /* 0x00 状态寄存器 */
volatile uint32_t DR; /* 0x04 数据寄存器 */
volatile uint32_t BRR; /* 0x08 波特率寄存器 */
volatile uint32_t CR1; /* 0x0C 控制寄存器 */
/* ... */
} USART_TypeDef;
#define USART2 ((USART_TypeDef *)0x40004400UL)验证偏移列是否与结构体布局匹配(预留字段需添加填充)。
3. Init sequence checklist
3. 初始化序列检查清单
Peripheral bring-up order
├── 1. Enable bus clock (RCC/APB/AHB register)
├── 2. Reset peripheral (if RM requires)
├── 3. Configure pins (GPIO alternate function)
├── 4. Configure peripheral registers (mode, baud, etc.)
├── 5. Enable peripheral (UE, TE, RE bits)
├── 6. Enable NVIC IRQ (if interrupt-driven)
└── 7. Verify status flags before first transactionBad — enable UART before clock:
c
USART2->CR1 |= USART_CR1_UE; /* USART clock still off — no effect */外设启动顺序
├── 1. 启用总线时钟(RCC/APB/AHB寄存器)
├── 2. 复位外设(若RM要求)
├── 3. 配置引脚(GPIO复用功能)
├── 4. 配置外设寄存器(模式、波特率等)
├── 5. 启用外设(UE、TE、RE位)
├── 6. 启用NVIC中断(若采用中断驱动)
└── 7. 首次事务前验证状态标志错误示例 — 先启用UART再开启时钟:
c
USART2->CR1 |= USART_CR1_UE; /* USART时钟仍未开启 — 无效果 */4. Bit definition discipline
4. 位定义规范
c
/* From RM: CR1 M[1:0], PCE, PS, TE, RE, UE */
#define USART_CR1_UE (1U << 13)
#define USART_CR1_TE (1U << 3)
#define USART_CR1_RE (1U << 2)Document RM section number in comment for audit trail.
c
/* 来自RM: CR1寄存器的M[1:0]、PCE、PS、TE、RE、UE位 */
#define USART_CR1_UE (1U << 13)
#define USART_CR1_TE (1U << 3)
#define USART_CR1_RE (1U << 2)在注释中记录RM章节编号,便于审计追溯。
5. Timing and busy-wait
5. 时序与忙等待
c
/* RM: poll BUSY flag until reset complete */
while (RCC->CR & RCC_CR_PLLRDY == 0)
;Respect startup times (oscillator settle, PLL lock) from electrical characteristics chapter.
c
/* RM要求:轮询BUSY标志直到复位完成 */
while (RCC->CR & RCC_CR_PLLRDY == 0)
;需遵守电气特性章节中规定的启动时间(振荡器稳定、PLL锁定等)。
6. Good vs bad driver structure
6. 驱动结构的优劣对比
Good — layered, RM-referenced:
c
void usart2_init(uint32_t baud) {
rcc_enable_usart2();
gpio_config_usart2_pins();
usart2_set_baud(baud);
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}Bad — magic numbers, no clock enable:
c
*(uint32_t*)0x4000440C = 0x2000; /* what peripheral? which bit? */良好示例 — 分层设计、参考RM:
c
void usart2_init(uint32_t baud) {
rcc_enable_usart2();
gpio_config_usart2_pins();
usart2_set_baud(baud);
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}糟糕示例 — 魔法数字、未启用时钟:
c
*(uint32_t*)0x4000440C = 0x2000; /* 这是什么外设?对应哪一位? */7. Agent usage examples
7. Agent使用示例
/peripherals-from-datasheet Walk me through USART init from STM32 RM
/peripherals-from-datasheet What sections of the ref manual matter for SPI timing?/peripherals-from-datasheet 引导我根据STM32 RM完成USART初始化
/peripherals-from-datasheet 参考手册中哪些章节对SPI时序至关重要?Common Problems
常见问题
| Symptom | Cause | Fix |
|---|---|---|
| Peripheral dead | Clock not enabled | RCC/APB enable bit first |
| Wrong baud rate | PCLK assumption wrong | Recompute using actual clock tree |
| GPIO AF wrong | MUX value from wrong table | Cross-check pinout + AF table |
| IRQ stuck | Status flag clear sequence wrong | RM "clearing flags" subsection |
| Silent data corruption | Endian or width mismatch | Match register access size |
| 症状 | 原因 | 解决方法 |
|---|---|---|
| 外设无响应 | 未启用时钟 | 先设置RCC/APB使能位 |
| 波特率错误 | PCLK假设错误 | 根据实际时钟树重新计算 |
| GPIO复用功能错误 | 复用值来自错误表格 | 交叉核对引脚分配表与AF表 |
| 中断卡住 | 状态标志清除顺序错误 | 查看RM中“标志清除”小节 |
| 数据静默损坏 | 字节序或宽度不匹配 | 匹配寄存器访问宽度 |
Related Skills
相关技能
- — fast RM navigation
skills/baremetal/datasheet-and-refmanual-reading - — register access patterns
skills/baremetal/mmio-and-bit-manipulation - — pin mux before peripheral enable
skills/baremetal/gpio-baremetal - — memory map alignment
skills/embedded/linker-scripts
- — 快速导航RM
skills/baremetal/datasheet-and-refmanual-reading - — 寄存器访问模式
skills/baremetal/mmio-and-bit-manipulation - — 外设启用前的引脚复用配置
skills/baremetal/gpio-baremetal - — 内存映射对齐
skills/embedded/linker-scripts