stm32内部flash地址架构映射
因为我的stm32f407的内部flash是1M的所以块2不存在,但他的地址仍然存在,只是没有作用,这是stm32的整体框架。
主存储器
一般我们说 STM32 内部 FLASH 的时候,都是指这个主存储器区域,它是存储用户应用程序的空间,芯片型号说明中的 1M FLASH、2M FLASH 都是指这个区域的大小。
主存储器分为两块,共 2MB,每块内分 12 个扇区,其中包含 4 个 16KB 扇区、1 个 64KB 扇区和 7 个 128KB 的扇区。如我们实验板中使用的 STM32F407ZGT6 型号芯片,它的主存储区域大小为 1MB,所以它只包含有表中的扇区 0-扇区 11。
与其它 FLASH 一样,在写入数据前,要先按扇区擦除,而有的时候我们希望能以小规格操纵存储单元,所以 STM32F42x/43x 针对 1MB FLASH 的产品还提供了一种双块的存储格式,见表 1MB 产品的双块存储格式 。(2M 的产品按表 STM32 内部 FLASH 的构成 的格式)
通过配置 FLASH 选项控制寄存器 FLASH_OPTCR 的 DB1M 位,可以切换这两种格
式。
我的STM32F40x芯片没有这种模式
系统存储区
系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负责实现串口、USB 以及 CAN 等 ISP 烧录功能
OTP 区域
OTP(One Time Program),指的是只能写入一次的存储区域,容量为 512 字节,写入后数据就无法再更改,OTP 常用于存储应用程序的加密密钥。
选项字节
选项字节用于配置 FLASH 的读写保护、电源管理中的 BOR 级别、软件/硬件看门狗等功能,这部分共 32 字节。可以通过修改 FLASH 的选项控制寄存器修改。
写入过程
1、解锁
由于内部 FLASH 空间主要存储的是应用程序,是非常关键的数据,为了防止误操作修改了这些内容,芯片复位后默认会结 FLASH 上锁,这个时候不允许设置 FLASH 的控制寄存器,并且不能对修改 FLASH 中的内容。
所以对 FLASH 写入数据前,需要先给它解锁。解锁的操作步骤如下:
(1) 往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY1 = 0x45670123
(2) 再往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY2 = 0xCDEF89AB
2、数据操作位数
在内部 FLASH 进行擦除及写入操作时,电源电压会影响数据的最大操作位数,该电源电压可通过配置 FLASH_CR 寄存器中的 PSIZE 位改变,见表数据操作位数 。
一般直接选择32位模式,电压也不需要改变,选择64位需外接8-9V电压给Vpp
3、 擦除扇区
跟操作外部flash一样,写入之前也是要擦除的。
扇区擦除的过程如下:
(1)
检查
FLASH_SR
寄存器中的“忙碌寄存器位
BSY
”,以确认当前未执行任何
Flash
操作;
(2)
在
FLASH_CR
寄存器中,将“激活扇区擦除寄存器位
SER
”置
1
,并设置“扇区编号寄存器位 SNB
”,选择要擦除的扇区;
(3)
将
FLASH_CR
寄存器中的“开始擦除寄存器位
STRT
”置
1
,开始擦除;
(4)
等待
BSY
位被清零时,表示擦除完成
4、写入数据
擦除完毕后即可写入数据,写入数据的过程并不是仅仅使用指针向地址赋值,赋值前还还需要配置一系列的寄存器,步骤如下:
(1)
检查
FLASH_SR
中的
BSY
位,以确认当前未执行任何其它的内部
Flash
操作;
(2)
将
FLASH_CR
寄存器中的“激活编程寄存器位
PG
”置
1
;
(3)
针对所需存储器地址(主存储器块或
OTP
区域内)执行数据写入操作;
(4)
等待
BSY
位被清零时,表示写入完成。
5、上锁
写完数据记得上锁内部flash防止误操作修改到code数据等等。
6、读取数据
读取数据是不受上锁影响的,上锁后可以根据地址读取变量的值核对是否写入成功。
代码流程
#include "stm32f4xx.h"
#include "./uart/bsp_debug_uart.h"
#include "./inter_flash/inter_flash.h"
#define TEST_DATA 0x12
#define TEST_ADDR 0x08008000
/**
* 本地擦除第二扇区,第一扇区存放代码code,通过查看map文件预留空间
*
*/
void inter_flash_test(void)
{
/*
1、解锁
2、擦除
3、写入
4、上锁
5、读取检验
*/
//解锁
FLASH_Unlock();
//擦除
if(FLASH_EraseSector(FLASH_Sector_2,VoltageRange_3) == FLASH_COMPLETE)
{
printf("\r\n擦除成功");
}
else
{
printf("\r\n擦除失败");
}
//写入
if(FLASH_ProgramByte(TEST_ADDR,TEST_DATA) == FLASH_COMPLETE)
{
printf("\r\n写入成功");
}
else
{
printf("\r\n写入失败");
}
//上锁
FLASH_Lock();
//检验
printf("\r\n 读取地址0x%x的内容是:0x%x",TEST_ADDR,(char *)(TEST_ADDR));
}