STM32启动时将RAM数据复制至Flash的实现步骤与原理问询
启动阶段RAM到Flash的复制:实现步骤与底层原理
先搞懂核心逻辑
Flash是非易失性只读存储,默认锁定防止误写,而且只能把存储单元的1改成0——要写入新数据,必须先擦除整页(把所有位恢复成1)。启动阶段把RAM内容复制到Flash,本质就是在系统刚启动时,把RAM里临时存的固件、配置数据之类的内容,持久化到Flash里,常见于固件升级、出厂数据烧录这类场景。
一步步实现(以STM32为例,其他MCU逻辑通用)
1. 提前摸清楚硬件参数
- 查芯片手册,确定目标Flash的页大小、起始地址、总容量:比如STM32F103小容量型号是1KB/页,大容量是2KB/页,擦除和写入必须按页来。
- 确认RAM中待复制数据的起始地址和长度:最好让数据长度是Flash页大小的整数倍,要是有零头,最后一页单独处理。
2. 解锁Flash控制器
Flash默认是锁死的,得先输密钥解锁。以STM32为例,操作FLASH_KEYR寄存器:
// STM32解锁示例 FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB;
原理:芯片厂商给Flash控制器设了密钥验证机制,只有写入正确的密钥序列,才能解除写保护,允许后续的擦除和写入操作。
3. 擦除目标Flash页
擦除是写入的前提,必须整页擦:
// STM32页擦除示例 while (FLASH->SR & FLASH_SR_BSY); // 等Flash空闲,忙的时候不能操作 FLASH->CR |= FLASH_CR_PER; // 开启页擦除模式 FLASH->AR = FLASH_TARGET_PAGE_ADDR; // 指定要擦除的页起始地址 FLASH->CR |= FLASH_CR_STRT; // 触发擦除 while (FLASH->SR & FLASH_SR_BSY); // 等擦完 FLASH->CR &= ~FLASH_CR_PER; // 关闭页擦除模式
原理:Flash的存储单元是浮栅结构,擦除操作是给浮栅放电,把所有位恢复成逻辑1(也就是0xFF),这样才能后续写入(因为只能把1改成0)。
4. 从RAM往Flash写数据
按MCU的总线宽度(比如STM32是32位,按字写效率最高)循环写入:
// STM32按字写入示例 uint32_t *ram_src = (uint32_t *)RAM_DATA_START_ADDR; uint32_t *flash_dst = (uint32_t *)FLASH_TARGET_START_ADDR; uint32_t word_count = TOTAL_DATA_LEN / 4; // 按32位字计算数量 for (uint32_t i = 0; i < word_count; i++) { while (FLASH->SR & FLASH_SR_BSY); // 等空闲 FLASH->CR |= FLASH_CR_PG; // 开启编程模式 *flash_dst++ = *ram_src++; // 写入一个字 while (FLASH->SR & FLASH_SR_BSY); // 等写入完成 FLASH->CR &= ~FLASH_CR_PG; // 关闭编程模式 // 检查写入错误 if (FLASH->SR & FLASH_SR_PGERR) { FLASH->SR |= FLASH_SR_PGERR; // 清错误标志 // 这里加错误处理逻辑,比如停止复制、上报错误 break; } }
原理:编程时,Flash控制器给目标存储单元加高压,让浮栅捕获电子,对应位就变成0。每写完一个单元,必须关闭编程模式,防止误写。
5. 重新锁定Flash
操作完赶紧锁上,防止后续误操作:
FLASH->CR |= FLASH_CR_LOCK; // 锁定Flash控制器
必须注意的坑
- 别被中断打断:启动阶段最好关中断,Flash操作被中断很容易出问题;要是非得开中断,把Flash操作的优先级设最高。
- 电源要稳:擦除和写入Flash需要稳定的供电,电压波动可能直接搞坏Flash。
- 写完要校验:复制完后,把Flash里的数据和RAM里的做CRC或者逐字节比对,确保没写错。
- 别照搬代码:不同MCU的Flash寄存器不一样,比如NXP Kinetis系列的解锁序列、寄存器名称都和STM32不一样,一定要查自己芯片的参考手册。
内容的提问来源于stack exchange,提问作者Rakshit Sonawane
相关产品推荐
相关产品推荐

