STM32F4内部Flash模拟EEPROM:磨损均衡与掉电保护的工程化实现
👁 1 阅读 · 2026-08-27 · 嵌入式
在嵌入式系统中,当外部EEPROM成本或空间受限时,利用STM32F4内部Flash模拟EEPROM成为常见方案。然而,Flash的擦写寿命(典型10K次)和掉电风险是两大痛点。本文深入剖析磨损均衡算法与掉电保护策略,结合F4的硬件特性,给出一个可落地的工程实现框架,涵盖扇区管理、双区备份、写失败恢复等关键细节,助你构建高可靠的参数存储系统。
# STM32F4内部Flash模拟EEPROM:磨损均衡与掉电保护的工程实现
## 1. 为什么需要模拟EEPROM?
STM32F4系列内置Flash容量大(如F407有1MB),但擦写寿命有限(典型10K次/扇区)。当系统需要频繁保存配置参数(如校准值、运行状态)时,直接擦写Flash会迅速耗尽寿命。外部EEPROM(如AT24C02)虽可靠,但增加BOM成本和PCB面积。因此,在成本敏感或空间受限的场景,用内部Flash模拟EEPROM成为优选。
核心挑战:
- **寿命限制**:Flash擦除次数远低于EEPROM(1M次)。
- **掉电风险**:写入过程中掉电可能导致数据损坏或半写状态。
- **擦除粒度**:Flash按扇区擦除(F4通常16KB/扇区),而写入可字节/半字/字。
## 2. 硬件基础与关键特性
STM32F4的Flash控制器支持:
- **编程**:以16位(半字)为单位写入,需先置位PG位。
- **擦除**:按扇区或整片擦除,需置位SER位并等待BSY位清零。
- **选项字节**:可配置读保护等,但模拟EEPROM时通常不用。
关键寄存器:`FLASH_CR`(控制)、`FLASH_SR`(状态)、`FLASH_ACR`(延迟)。
## 3. 磨损均衡策略
### 3.1 扇区划分与日志结构
将Flash划分为多个逻辑扇区(如4个物理扇区,每个16KB)。采用**日志结构**:数据以记录(Record)形式顺序写入当前活动扇区,每个记录包含:
- **头部**:魔数(0xA5A5)、数据长度、CRC16校验。
- **数据**:用户参数(固定长度或变长)。
- **状态**:有效/无效标记。
当活动扇区写满时,触发**扇区切换**:
1. 选择下一个空闲扇区作为新活动区。
2. 将最新有效数据从旧扇区复制到新扇区。
3. 擦除旧扇区,并标记为待用。
### 3.2 磨损均衡算法
采用**轮询+计数器**方式:
- 维护一个全局擦写计数(存储于Flash首扇区)。
- 每次切换扇区时,递增计数并选择擦写次数最少的扇区作为新活动区。
- 若所有扇区擦写次数接近,则顺序轮询。
示例代码(简化):
```c
#define SECTOR_NUM 4
#define SECTOR_SIZE 0x4000 // 16KB
uint32_t erase_count[SECTOR_NUM];
uint32_t select_next_sector(uint32_t current) {
uint32_t min_count = erase_count[(current+1)%SECTOR_NUM];
uint32_t next = (current+1)%SECTOR_NUM;
for (int i=0; i SECTOR_SIZE) {
switch_sector();
}
// 构造头部
RecordHeader hdr = {0xA5A5, len, crc32(data, len)};
// 写入头部和数据(注意Flash写入需半字对齐)
flash_write_halfword(active_sector*SECTOR_SIZE + write_offset, hdr.magic);
flash_write_halfword(active_sector*SECTOR_SIZE + write_offset+2, hdr.len);
flash_write_word(active_sector*SECTOR_SIZE + write_offset+4, hdr.crc);
// 写入数据(按32位对齐)
for (int i=0; i