一、简介
•STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程
•读写FLASH的用途:
利用程序存储器的剩余空间来保存掉电不丢失的用户数据
通过在程序中编程(IAP),实现程序的自我更新
•在线编程(In-Circuit Programming -- ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序
•在程序中编程(In-Application Programming -- IAP)可以使用微控制器支持的任一种通信接口下载程序
二、闪存模块组织

一、闪存模块组织架构总览
这款中容量产品的闪存被划分为三大核心区域:
- 主存储器:程序代码与数据的核心存储区,按页(Page)组织
- 信息块:存储启动代码、用户配置等关键系统信息
- 闪存存储器接口寄存器:控制闪存读写、擦除等操作的硬件寄存器组
二、主存储器区域详解
- 组织方式:以"页(Page)" 为最小单位,共 128 页(页 0~ 页 127)
- 单页容量:1KB(1024 字节)
- 地址范围 :
0x0800 0000~0x0801 FFFF - 总容量 :128 × 1KB = 128KB
- 特点 :这是用户程序的主要存放区域,STM32 中通常从
0x0800 0000开始存放中断向量表和应用代码。
三、信息块区域详解
信息块是系统级的特殊存储区域,包含两类关键信息:
-
启动程序代码
- 地址:
0x1FFF F000~0x1FFF F7FF - 容量:2KB
- 作用:存储芯片出厂时的 Bootloader,负责芯片上电后的初始化、程序加载(如串口 / USB 下载)等。
- 地址:
-
用户选择字节
- 地址:
0x1FFF F800~0x1FFF F80F - 容量:16 字节
- 作用:存储用户配置信息,如读保护、写保护、看门狗设置等选项字节。
- 地址:
四、闪存接口寄存器区域详解
这组寄存器(基地址0x4002 2000)是 CPU 与闪存硬件交互的桥梁,每个寄存器占 4 字节(32 位),核心寄存器功能如下:

三、FLASH基本结构

1. 核心存储分区
主存储器:
-
程序存储器(64KB)
- 地址范围:
0x0800 0000~0x0800 FFFF - 组织形式:共 64 页 ,每页大小 1KB(页 0~ 页 63)
- 用途:存放用户应用程序代码、常量数据,是 CPU 执行指令的主存储区
- 地址范围:
信息块:
-
系统存储器(2KB)
- 地址范围:
0x1FFF F000~0x1FFF F7FF - 内容:芯片出厂时固化的 Bootloader,负责上电初始化、串口 / USB 等方式的程序下载
- 特性:用户不可擦写,保障芯片基础启动功能
- 地址范围:
-
选项字节(16 字节)
- 地址范围:
0x1FFF F800~0x1FFF F80F - 用途:存储系统安全与配置信息,如读保护、写保护、看门狗设置、复位引脚配置等
- 地址范围:
2. 闪存控制核心:FPEC
- 全称:Flash Program and Erase Controller(闪存编程与擦除控制器)
- 核心作用:
- 负责程序存储器的页擦除、全擦除与字编程操作
- 管理选项字节的擦除与编程,实现系统安全配置
- 提供寄存器接口(如
FLASH_KEYR解锁、FLASH_CR控制命令、FLASH_SR状态查询),供 CPU 调用
3. 典型开发应用
- 固件升级:通过 FPEC 擦除目标页,再将新固件写入程序存储器对应地址
- 安全加固:配置选项字节开启读保护,防止外部调试器读取固件代码
- 参数存储:利用未使用的程序存储器页,存储用户配置参数(如校准数据、设备序列号)
四、FLASH解锁
FPEC共有三个键值:
RDPRT键 = 0x000000A5
KEY1 = 0x45670123
KEY2 = 0xCDEF89AB
解锁**:**
复位后,FPEC被保护,不能写入FLASH_CR
在FLASH_KEYR先写入KEY1,再写入KEY2,解锁
错误的操作序列会在下次复位前锁死FPEC和FLASH_CR
加锁:
设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR
五、使用指针访问寄存器
使用指针读指定地址下的存储器:
uint16_t Data = *((__IO uint16_t *)(0x08000000));
去地址 0x08000000 这个位置,把里面存的 16 位数读出来,放到 Data 里。
一步步拆:
(uint16_t *)0x08000000→ 把数字0x08000000当成 16 位指针*→ 取指针指向的内容(读数据)
使用指针写指定地址下的存储器:
*((__IO uint16_t *)(0x08000000)) = 0x1234;
把 0x1234 这个 16 位数,直接写入地址 0x08000000。
STM32 闪存必须按规则写入:解锁 → 擦除 → 编程,不能直接赋值!这里只是拿来看一下,要写闪存 Flash的话,必须按规则来,不过0x02000000 → 内存 RAM ✅ 可以直接写。
注:
#define __IO volatile
告诉编译器:这个地址的值会 "自己变",不许优化,每次都必须真的去硬件读 / 写!
如果不加:
- 编译器可能觉得 "地址没变,数据也没变",直接给你优化掉
- 硬件读出来的值 可能是错的
加了 volatile(__IO):
- 每次都老老实实访问真实地址
- 嵌入式操作寄存器、闪存、内存 必须加
六、程序存储器全擦除、页擦除、编程
注:下面的流程图中有进行判断是否解锁,在标准库函数中不进行判断,不管是否解锁都执行解锁过程。
程序存储器全擦除
过程图

流程步骤拆解
1、检查锁定状态
操作:读取 FLASH_CR 寄存器的 LOCK 位
逻辑:
- 若
LOCK = 1(闪存处于锁定状态):必须先执行解锁流程 (向FLASH_KEYR写入固定密钥序列) - 若
LOCK = 0(已解锁):直接进入下一步
2、启动全擦除命令
操作:
- 置
FLASH_CR的MER(Mass Erase)位为1,开启全擦除模式 - 置
FLASH_CR的STRT(Start)位为1,触发擦除操作(让CPU工作)
3、等待操作完成
操作:循环读取 FLASH_SR 寄存器的 BSY(Busy)位
逻辑:
- 若
BSY = 1:闪存正在执行擦除,继续等待 - 若
BSY = 0:擦除操作完成,退出等待
4、验证擦除结果
操作:逐页读取闪存数据,验证所有页是否已被擦除(擦除后闪存内容为 0xFF)
程序存储器页擦除
过程图

流程步骤拆解
1、检查锁定状态
- 操作:读取
FLASH_CR寄存器的LOCK位 - 逻辑:
- 若
LOCK = 1(闪存锁定):必须先执行解锁流程 (向FLASH_KEYR写入0x45670123和0xCDEF89AB两个密钥) - 若
LOCK = 0(已解锁):直接进入下一步
- 若
2、配置并启动页擦除
- 操作:
- 置
FLASH_CR的PER(Page Erase)位为1,开启页擦除模式 - 在
FLASH_AR(地址寄存器)中写入目标页的起始地址,选择要擦除的页 - 置
FLASH_CR的STRT(Start)位为1,触发擦除操作
- 置
3、等待操作完成
- 操作:循环读取
FLASH_SR寄存器的BSY(Busy)位 - 逻辑:
- 若
BSY = 1:闪存正在执行擦除,继续等待 - 若
BSY = 0:擦除操作完成,退出等待
- 若
4、验证擦除结果
- 操作:读取目标页的所有数据,验证是否已被擦除(擦除后闪存内容为
0xFF)
程序存储器编程
流程图

流程步骤拆解
1、检查锁定状态
- 操作:读取
FLASH_CR寄存器的LOCK位 - 逻辑:
- 若
LOCK = 1(闪存锁定):必须先执行解锁序列 (向FLASH_KEYR依次写入0x45670123和0xCDEF89AB两个密钥) - 若
LOCK = 0(已解锁):直接进入下一步
- 若
2、开启编程模式
- 操作:置
FLASH_CR的PG(Programming)位为1,使能闪存编程模式
3、写入半字数据
- 操作:在指定的闪存地址写入半字(16 位数据)
- 注意:STM32F1 闪存编程最小单位为半字(16 位),不支持单字节写入
4、等待操作完成
- 操作:循环读取
FLASH_SR寄存器的BSY(Busy)位 - 逻辑:
- 若
BSY = 1:闪存正在执行编程操作,继续等待 - 若
BSY = 0:编程操作完成,退出等待
- 若
5、验证写入结果
- 操作:读取刚编程的地址,检查写入的数据是否与预期一致
七、选项字节编程、擦除,电子签名
信息块中选项字节(Option Bytes) 的 32 位寄存器布局

•RDP:写入RDPRT键(0x000000A5)后解除读保护
•USER:配置硬件看门狗和进入停机/待机模式是否产生复位
•Data0/1:用户可自定义使用
•WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)
选项字节编程
•检查FLASH_SR的BSY位,以确认没有其他正在进行的编程操作
•解锁FLASH_CR的OPTWRE位
•设置FLASH_CR的OPTPG位为1
•写入要编程的半字到指定的地址
•等待BSY位变为0
读出写入的地址并验证数据
选项字节擦除
•检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
•解锁FLASH_CR的OPTWRE位
•设置FLASH_CR的OPTER位为1
•设置FLASH_CR的STRT位为1
•等待BSY位变为0
读出被擦除的选择字节并做验证
电子签名
•电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名
•闪存容量寄存器:
基地址:0x1FFF F7E0
大小:16位