宁开亮电子博客 English
stm32 flash 擦除 page

stm32 flash 擦除 page:STM32的Flash擦除为什么必须以页为单位?

作者:宁开亮电子博客 · 时间:20261017

本文解答了关于“stm32 flash 擦除 page”:STM32的Flash擦除为什么必须以页为单位?STM32F1系列Flash页大小和擦除步骤是怎样的?STM32F4系列Flash擦除页的选择与注意事项?擦除一页Flash后数据变成什么值?如何验证擦除成功?在STM32程序运行中擦除Flash页需要注意什么?

Q: STM32的Flash擦除为什么必须以页为单位?

A: STM32的Flash属于NOR型浮栅存储结构,擦除时需要在浮栅上加高压使电子隧穿回衬底,这个过程只能以物理上连通的存储块为单位进行。页是最小可独立擦除的物理单元,无法像RAM那样按字节覆写。不同系列页大小不同,如F1为1KB,F4为16/64/128KB,擦除前必须按页对齐地址。

Q: STM32F1系列Flash页大小和擦除步骤是怎样的?

A: STM32F1大容量产品页大小为2KB,中小容量为1KB。擦除步骤:解锁FLASH_KEYR写入0x45670123和0xCDEF89AB;置位FLASH_CR的PER位并配置AR为目标页起始地址;置位STRT启动擦除;查询BSY位等待完成;最后置位LOCK锁定并清除PER位。擦除期间总线会停顿,代码若在Flash运行需注意。

Q: STM32F4系列Flash擦除页的选择与注意事项?

A: STM32F4按扇区(Sector)擦除,Sector0到3为16KB,4为64KB,5到11为128KB。擦除前通过FLASH_CR的SNB字段选择扇区号,PSIZE配置并行位宽。注意擦除是整扇区,小数据更新会浪费空间;且擦除电压敏感,需保证供电稳定,擦写期间不要复位,否则可能损坏扇区。

Q: 擦除一页Flash后数据变成什么值?如何验证擦除成功?

A: STM32 Flash擦除后所有位被置为1,即每个字节读出0xFF。验证方法:擦除后通过指针或HAL_FLASH_Read读取整页,检查是否全为0xFF;也可用CRC校验比对。若出现非0xFF值说明擦除未完成或电压不足。编程时只能将1写为0,因此写前必须擦除,写后可用读回比较确认。

Q: 在STM32程序运行中擦除Flash页需要注意什么?

A: 若程序本身在Flash中运行,擦除会锁定总线导致取指停顿,建议在RAM中执行擦除函数或关闭中断并确保擦除代码不在被擦扇区。擦除前保存关键数据,擦除中避免看门狗复位。使用HAL库时调用HAL_FLASHEx_Erase并检查返回值,擦除后恢复中断,并注意Flash寿命通常约1万次擦写。

stm32 flash 擦除 page

关于“stm32 flash 擦除 page”的经验之谈

交流“stm32 flash 擦除 page”的常见场景

【新手工程师小陈】 前辈,我在做 STM32 的 Flash 存储功能,想请教一下擦除 page 的问题。我用的芯片是 STM32F103C8T6,它的 Flash 页大小是多少啊?

【资深嵌入式工程师老张】 F103C8T6 属于中容量产品,Flash 页大小是 1KB,总共 64KB,也就是 64 页。你擦除的时候要以页为单位,不能像大容量那样按 2KB 来算。

【新手工程师小陈】 原来如此!我之前看手册看到有 2KB 的,还以为是这个型号的。那擦除 page 具体怎么操作呢?是不是直接调用 HAL_FLASHEx_Erase 就行?

【资深嵌入式工程师老张】 对,用 HAL 库的话先 HAL_FLASH_Unlock(),然后填 FLASH_EraseInitTypeDef 结构体:TypeErase 设为 FLASH_TYPEERASE_PAGES,PageAddress 填你要擦的页起始地址,NbPages 填页数。最后调用 HAL_FLASHEx_Erase 并检查返回值。

【新手工程师小陈】 PageAddress 是随便填一个地址就行吗?比如我想擦第 10 页,地址怎么算?

【资深嵌入式工程师老张】 PageAddress 必须是页的起始地址,也就是 0x08000000 + 页号 × 1024。第 10 页就是 0x08000000 + 10×0x400 = 0x08002800。地址填错会返回错误或者擦错页,要小心。

【新手工程师小陈】 明白了,那擦除之前需要先判断这一页是不是已经被擦过了吗?还是说直接擦就行?

【资深嵌入式工程师老张】 可以直接擦,但有个坑:Flash 擦除会把整页变成 0xFF。如果你这一页里有别的数据,会被一起擦掉。所以设计存储方案时一定要按页规划好数据布局。

【新手工程师小陈】 那如果我想保存几个不同的参数,是每个参数占一页,还是可以放在同一页里?

【资深嵌入式工程师老张】 同一页可以放多个参数,但更新任何一个参数都得整页擦除再重写。常见做法是:把这一页所有参数读出来到 RAM,修改后整页擦除,再全部写回去。或者用双页交替存储做掉电保护。

【新手工程师小陈】 双页交替这个思路听起来不错,能简单说说吗?

【资深嵌入式工程师老张】 比如用第 10 页和第 11 页,写入时先擦下一页,把当前页数据拷贝过去再追加新数据,加个版本号或 CRC 标记哪页最新。这样即使擦除过程中掉电,至少还有一页完整的数据。

【新手工程师小陈】 这个方案好,那我写的时候用 HAL_FLASH_Program 吗?一次能写多少?

【资深嵌入式工程师老张】 F103 支持字(32 位)、半字(16 位)编程。HAL_FLASH_Program 第一个参数选 FLASH_TYPEPROGRAM_WORD,地址要 4 字节对齐,数据是 32 位。注意只能把 1 写成 0,不能反向,所以写之前必须擦除。

【新手工程师小陈】 那擦除一页大概需要多久?会不会影响程序运行?

【资深嵌入式工程师老张】 F103 页擦除典型时间大约 20ms 左右,具体看手册的电气特性表。擦除期间 CPU 从 Flash 取指会被暂停,所以中断响应会延迟。如果对实时性要求高,可以把擦写代码放到 RAM 里执行,或者选双 Bank 的型号。

【新手工程师小陈】 放到 RAM 里执行是怎么实现的?需要特殊配置吗?

【资深嵌入式工程师老张】 可以用 __attribute__((section(".ramfunc"))) 把函数放到 RAM,然后在链接脚本里配置这个段,启动时拷贝到 RAM 并允许执行。不过对 F103 来说,如果擦写不频繁,通常没必要这么折腾。

【新手工程师小陈】 好的,最后一个问题,擦除失败一般是什么原因?我该怎么排查?

【资深嵌入式工程师老张】 常见原因有:没解锁、地址没对齐或不在合法范围、目标页被写保护(选项字节)、擦除过程中电压不稳。排查时先看 HAL 返回的 HAL_ERROR 还是 HAL_TIMEOUT,再检查 FLASH->SR 里的错误标志位,对应手册逐个排除就行。

【新手工程师小陈】 太感谢了前辈,思路清晰多了,我这就去按页规划一下存储结构!

此页面文章来自宁开亮电子博客, 更多关于“stm32” 的知识问答请关注宁开亮电子博客。