【STM32】FLASH闪存
【STM32】FLASH闪存
- 一、FLASH简介
- 二、闪存模块组织
- 三、FLASH基础操作
- 3.1 FLASH基本结构
- 3.2 FLASH解锁
- 3.3 使用指针访问存储器
 
- 四、程序存储器
- 4.1 全擦除
- 4.2 页擦除
- 4.3 编程
 
- 五、选项字节
- 5.1 组织结构
- 5.2 选项字节编程
- 5.3 选项字节擦除
 
- 六、器件电子签名
一、FLASH简介
- STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程
- 读写FLASH的用途:
 利用程序存储器的剩余空间来保存掉电不丢失的用户数据
 通过在程序中编程(IAP),实现程序的自我更新
- 在线编程(In-Circuit Programming – ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序
- 在程序中编程(In-Application Programming – IAP)可以使用微控制器支持的任一种通信接口下载程序
二、闪存模块组织

1. 主存储器
 主存储器以“页”为单位组织,是闪存中用于存储用户程序、数据的主要区域。
- 页的数量与容量:从“页0”到“页127”,共128页;每页长度为1K字节(即1024字节)。
- 地址范围规律:每页地址跨度为0x400(因为0x0800 0400 - 0x0800 0000 = 0x400,对应1024字节)。例如:- 页0:0x0800 0000 – 0x0800 03FF
- 页1:0x0800 0400 – 0x0800 07FF
- ……
- 页127:0x0801 FC00 – 0x0801 FFFF
 
- 页0:
- 功能:用于存放用户的应用程序代码、运行时数据等,是程序执行的核心存储区域。
2. 信息块
 信息块用于存储系统级的关键信息,包括启动程序和用户配置数据。
- 启动程序代码: - 地址范围:0x1FFF F000 – 0x1FFF F7FF
- 长度:2K字节(2048字节)
- 功能:存储系统启动时的初始化程序(如Bootloader),负责引导主存储器中的应用程序运行。
 
- 地址范围:
- 用户选择字节: - 地址范围:0x1FFF F800 – 0x1FFF F80F
- 长度:16字节
- 功能:存储用户自定义的配置信息(如系统参数、功能选项等),供程序运行时读取或修改。
 
- 地址范围:
3. 闪存存储器接口寄存器
 这部分是操作闪存的硬件寄存器集合,通过对这些寄存器的读写,可实现闪存的擦除、编程、状态查询等操作。每个寄存器长度为4字节(32位),地址连续且跨度为0x4(符合32位寄存器的地址对齐要求)。
| 寄存器名称 | 地址范围 | 功能简述 | 
|---|---|---|
| FLASH_ACR | 0x4002 2000 – 0x4002 2003 | 闪存访问控制寄存器,配置闪存的访问周期等 | 
| FLASH_KEYR | 0x4002 2004 – 0x4002 2007 | 闪存密钥寄存器,用于解锁闪存的编程/擦除操作 | 
| FLASH_OPTKEYR | 0x4002 2008 – 0x4002 200B | 选项字节密钥寄存器,用于解锁选项字节的操作 | 
| FLASH_SR | 0x4002 200C – 0x4002 200F | 闪存状态寄存器,指示闪存的忙、错误等状态 | 
| FLASH_CR | 0x4002 2010 – 0x4002 2013 | 闪存控制寄存器,触发闪存的编程、擦除等操作 | 
| FLASH_AR | 0x4002 2014 – 0x4002 2017 | 闪存地址寄存器,指定编程/擦除的目标地址 | 
| 保留 | 0x4002 2018 – 0x4002 201B | 预留地址,用户不可操作,用于硬件扩展或未来功能 | 
| FLASH_OBR | 0x4002 201C – 0x4002 201F | 选项字节寄存器,存储闪存的配置选项(如读写保护) | 
| FLASH_WRPR | 0x4002 2020 – 0x4002 2023 | 写保护寄存器,配置闪存的区域写保护功能 | 
4. 总结
- 「主存储器」是用户程序/数据的“主战场”;
- 「信息块」是系统启动和用户配置的“专属区”;
- 「闪存存储器接口寄存器」是操作闪存的“控制中心”,通过软件读写这些寄存器,可完成闪存的擦写、状态查询等底层操作。
三、FLASH基础操作
3.1 FLASH基本结构

- 闪存存储器接口/闪存编程和擦除控制器(FPEC):是操作闪存的“控制核心”,负责执行闪存的擦除、编程(写入)等操作。
- 程序存储器(C8T6-64K):用于存储用户应用程序,以“页”为单位组织,每页1K字节,从0x0800 0000开始,包含页0、页1……页63等(图中展示了部分页的地址和容量)。
- 系统存储器:存储Bootloader(启动程序),地址0x1FFF F000,容量2K字节,负责系统启动时的程序引导。
- 选项字节:地址0x1FFF F800,容量16字节,用于存储闪存的配置信息(如读写保护、功能选项等)。
3.2 FLASH解锁
1. FPEC键值说明
 FPEC(闪存编程和擦除控制器)通过“键值验证”实现操作权限控制,共有三个关键键值:
- RDPRT键(0x000000A5):用于选项字节(如读写保护配置)的操作解锁。
- KEY1(0x45670123)和KEY2(0xCDEF89AB):用于主闪存(程序存储器、信息块)的编程/擦除操作解锁,是最常用的闪存操作权限密钥。
2. 解锁:
- 复位后,FPEC 被保护,不能写入 FLASH_CR
- 在 FLASH_KEYR 先写入 KEY1,再写入 KEY2,解锁
- 错误的操作序列会在下次复位前锁死 FPEC 和 FLASH_CR
 3. 加锁:
- 设置 FLASH_CR 中的 LOCK 位锁住 FPEC 和 FLASH_CR
在库函数中都有对应操作函数,直接调用即可
3.3 使用指针访问存储器
- 使用指针读指定地址下的存储器:
 uint16_t Data = *((__IO uint16_t *)(0x08000000));
- 使用指针写指定地址下的存储器:
 *((__IO uint16_t *)(0x08000000)) = 0x1234;
- 其中:
 #define __IO volatile
 在 C 语言中,volatile是一个类型修饰符,它的核心作用是告诉编译器,被它修饰的变量的值可能会在程序未明确修改的情况下被意外改变。__IO被定义为volatile,就是为了确保对硬件地址(如0x08000000对应的 FLASH 或寄存器)的读写操作不会被编译器优化,保证每次都实际访问硬件层的存储单元。
四、程序存储器
4.1 全擦除

- 步骤1:检查锁定状态
 读取FLASH_CR寄存器的LOCK位,判断闪存是否处于锁定状态。若LOCK位=1,需先执行“解锁过程”(如之前介绍的写入KEY1和KEY2)。
- 步骤2:触发全擦除操作
 若LOCK位=0(已解锁),设置FLASH_CR的MER位(全擦除使能)和STRT位(启动擦除),触发整个程序存储器的擦除操作。
- 步骤3:等待擦除完成
 持续检查FLASH_SR寄存器的BSY位(忙标志),若BSY位=1,说明擦除仍在进行,需等待;若BSY位=0,表示擦除完成。
- 步骤4:验证擦除结果
 读出并验证所有页的数据,确认是否均被擦除为0xFF(闪存擦除后的默认值)。
/*** 函    数:FLASH全擦除* 参    数:无* 返 回 值:无* 说    明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在*/
void MyFLASH_EraseAllPages(void)
{FLASH_Unlock();					//解锁FLASH_EraseAllPages();			//全擦除FLASH_Lock();					//加锁
}
4.2 页擦除

 步骤与全擦除类似,多一个传参,传入页地址
/*** 函    数:FLASH页擦除* 参    数:PageAddress 要擦除页的页地址* 返 回 值:无*/
void MyFLASH_ErasePage(uint32_t PageAddress)
{FLASH_Unlock();					//解锁FLASH_ErasePage(PageAddress);	//页擦除FLASH_Lock();					//加锁
}
4.3 编程

- 步骤1:检查锁定状态
 读取FLASH_CR寄存器的LOCK位,判断闪存是否锁定。若LOCK位=1,需先执行“解锁序列”(如写入KEY1和KEY2)。
- 步骤2:使能编程功能
 若LOCK位=0(已解锁),设置FLASH_CR的PG位(编程使能)。
- 步骤3:写入数据
 在指定地址写入16位的“半字”数据。
- 步骤4:等待编程完成
 持续检查FLASH_SR寄存器的BSY位(忙标志),BSY位=1表示编程进行中,需等待;BSY位=0表示编程完成。
/*** 函    数:FLASH编程字* 参    数:Address 要写入数据的字地址* 参    数:Data 要写入的32位数据* 返 回 值:无*/
void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
{FLASH_Unlock();							//解锁FLASH_ProgramWord(Address, Data);		//编程字FLASH_Lock();							//加锁
}/*** 函    数:FLASH编程半字* 参    数:Address 要写入数据的半字地址* 参    数:Data 要写入的16位数据* 返 回 值:无*/
void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{FLASH_Unlock();							//解锁FLASH_ProgramHalfWord(Address, Data);	//编程半字FLASH_Lock();							//加锁
}
五、选项字节
5.1 组织结构

- RDP:写入RDPRT键(0x000000A5)后解除读保护
- USER:配置硬件看门狗和进入停机/待机模式是否产生复位
- Data0/1:用户可自定义使用
- WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)
5.2 选项字节编程
- 检查FLASH_SR的BSY位,以确认没有其他正在进行的编程操作
- 解锁FLASH_CR的OPT WRE位
- 设置FLASH_CR的OPTPG位为1
- 写入要编程的半字到指定的地址
- 等待BSY位变为0
- 读出写入的地址并验证数据
5.3 选项字节擦除
- 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
- 解锁FLASH_CR的OPT WRE位
- 设置FLASH_CR的OPTER位为1
- 设置FLASH_CR的STRT位为1
- 等待BSY位变为0
- 读出被擦除的选择字节并做验证
六、器件电子签名
- 电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名
- 闪存容量寄存器:
 基地址:0x1FFF F7E0
 大小:16位
- 产品唯一身份标识寄存器:
 基地址:0x1FFF F7E8
 大小:96位
有关【STM32】FLASH闪存 就到这,希望对你有所帮助,感谢观看!
码文不易,留个赞再走吧~
