STM32F407 - 嵌入式Flash接口

时间:2023-02-20 17:06:37

主要特性

● 对于STM32F40xSTM32F41x,容量高达1 MB对于STM32F42xSTM32F43x,容量高达2 MB

这里,STM32F407ZGT6:1MB,STM32F407ZET6:512KB

● 128位宽数据读取
● 字节、半字、字和双字数据写入
● 扇区擦除与全部擦除
● 存储器组织结构
    Flash 结构如下:
主存储器块,分为 4 16 KB扇区、164 KB扇区和7128 KB扇区
系统存储器,器件在系统存储器自举模式下从该存储器启动
— 512 字节 OTP(一次性可编程),用于存储用户数据
   OTP 区域还有 16 个额外字节,用于锁定对应的 OTP 数据块。
选项字节,用于配置读写保护、 BOR 级别、软件/硬件看门狗以及器件处于待机或
    停止模式下的复位。
● 低功耗模式

Flash模块构成STM32F40xSTM32F41x

STM32F407 - 嵌入式Flash接口

读接口:

-- CPU时钟频率与Flash读取时间之间的关系 --

为了准确读取 Flash数据,必须根据CPU时钟(HCLK)频率和器件电源电压在Flash存取控制寄存器(FLASH_ACR)中正确地编程等待周期数(LATENCY)

等待周期通过 FLASH_ACR寄存器的LATENCY[2:0]三个位设置。复位后, CPU时钟频率为16MhzFLASH_ACR寄存器中的等待周期(WS)为0

供电电压是3.3V所以我们设置168Mhz频率作为CPU时钟之前,必须先设置LATENCY5,否则FLASH读写可能出错,导致死机。

STM32F407 - 嵌入式Flash接口


-- 自适应实时存储器加速器(ART Accelerator™) --

最大工作频率 168Mhz 时,虽然FLASH理论上需要6CPU等待周期,

凭借ART加速器所获得的性能相当于 FlashCPU频率高达 168MHz时以0个等待周期执行程序 (内部机制,知道就行,暂无深究必要

擦除和编程操作
执行任何 Flash 编程操作(擦除或编程)时,CPU时钟频率(HCLK)不能低于1 MHz。如果在Flash操作期间发生器件复位,无法保证Flash中的内容。

在对STM32F4xxFlash执行写入或擦除操作期间,任何读取Flash的尝试都会导致总线阻塞。

只有在完成编程操作后,才能正确处理读操作。这意味着,/擦除操作进行期间不能Flash中执行代码或数据获取操作


-- Flash控制寄存器解锁 --
复位后, Flash 控制寄存器(FLASH_CR)不允许执行写操作,以防因电气干扰等原因出现对
Flash的意外操作。(配置前,需要进行解锁

此寄存器的解锁顺序如下:

1.Flash密钥寄存器(FLASH_KEYR)中写入KEY1 = 0x45670123

2.Flash密钥寄存器(FLASH_KEYR)中写入KEY2 = 0xCDEF89AB

顺序不能错,否则将返回总线错误并锁定 FLASH_CR 寄存器,直到下一次复位。


-- 编程/擦除并行位数 --

STM32F4 闪存的编程位数可以通过 FLASH_CRPSIZE字段配置,PSIZE的设置必须和电源电压匹配

STM32F407 - 嵌入式Flash接口

通过FLASH_CR寄存器中的PSIZE 字段配置并行位数(每次对 Flash 进行写操作时将编程的字节数

进行任何编程/擦除操作前,必须在 FLASH_CR 寄存器中对其进行正确配置 

外部VPP电源为3.3V,所以PSIZE设置为10,即32位并行位数。擦除或者编程,都必须以32位为基础进行


-- 擦除 --

Flash 擦除操作可针对扇区整个Flash(批量擦除)执行。执行批量擦除时,不会影响OTP扇区或配置扇区。

STM32F4 的 FLASH 在编程的时候,也必须要求其写入地址的 FLASH 是被擦除了的(也就是其值必须是 0XFFFFFFFF),否则无法写入。

扇区擦除步骤:
1. 检查 FLASH_SR寄存器中的BSY位,以确认当前未执行任何 Flash操作
2. FLASH_CR寄存器中,将SER位置 1,并从主存储块的12(STM32F405xx/07xxSTM32F415xx/17xx)24(STM32F42xxxSTM32F43xxx)扇区中选择要擦除
的扇区
(SNB)
3.
FLASH_CR 寄存器中的 STRT 位置1
4.
等待 BSY 位清零

批量擦除步骤:
1. 检查FLASH_SR寄存器中的BSY位,以确认当前未执行任何Flash操作
2. FLASH_CR寄存器中的MER位置1(STM32F405xx/07xxSTM32F415xx/17xx器件)
3. FLASH_CR寄存器中的MERMER1位置1STM32F42xxxSTM32F43xxx器件)
4. FLASH_CR寄存器中的STRT位置1
5.
等待 BSY位清零


-- 编程 --

标准编程步骤:

1. 检查FLASH_SR中的BSY 位,以确认当前未执行任何 Flash操作。
2. FLASH_CR寄存器中的PG位置1
3. 针对所需存储器地址(主存储器块或OTP区域内)执行数据写入操作:
并行位数为 x8时按字节写入
并行位数为 x16时按半字写入
并行位数为x32时按字写入字 = 32位
并行位数为 x64时按双字写入
4. 等待 BSY位清零。

注意:1、设置 FLASH_CR 之前要先解锁; 2、编程前,要确保要写如地址的FLASH已经擦除(0xFFFFFFFF)。


寄存器

-- 寄存器一览 --

① FLASH_ACR : Flash访问控制寄存器 (Flash access control register

② FLASH_KEYR : Flash 密钥寄存器 (Flash key register

③ FLASH_OPTKEYR : Flash选项密钥寄存器 (Flash option key register

④ FLASH_SR : Flash状态寄存器 (Flash status register

⑤ FLASH_CR : Flash控制寄存器 (Flash control register

⑥ FLASH_OPTCR : Flash选项控制寄存器 (Flash option control register


-- FLASH_ACR(访问控制寄存器)--

LATENCY[2:0] :必须根据我们MCU的工作电压和频率,来进行正确的设置,否则,可能死机

DCENICEN和 PRFTEN  : 一般都设置为1即可


-- FLASH_KEYR (秘钥寄存器)--

用来解锁 FLASH_CR


-- FLASH_CR (控制寄存器)--

LOCK : 用于指示FLASH_CR寄存器是否被锁住,该位在检测到正确的解锁序列后,硬件将其清零。在一次不成功的解锁操作后,在下次系统复位之前,该位将不再改变。

STRT : 用于开始一次擦除操作。在该位写入1,将执行一次擦除操作。

PSIZE[1:0] : 用于设置编程宽度,3.3V时,我们设置PSIZE =2 即可。

SNB[3:0] : 4个位用于选择要擦除的扇区编号,取值范围为0~11

SER  :  用于选择扇区擦除操作,在扇区擦除的时候,需要将该位置1

PG  : 用于选择编程操作,在往FLASH写数据的时候,该位需要置1 


-- FLASH_SR(状态寄存器 --

BSY : 该位位1时,表示正在执行FLASH 操作。该位为0时,表示当前未执行任何FLASH操作。 


库函数

-- 锁定解锁函数 --

void FLASH_Unlock(void); //FLASH进行写操作前必须先解锁,解锁操作也就是必须在FLASH_KEYR寄存器写入特定的序列(KEY1KEY2

void FLASH_Lock(void) //在对FLASH写操作完成之后,我们要锁定FLASH


-- 写操作函数 --

FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data); //双字

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); //字

FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); //半字

FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_t Data); //字节


-- 擦除函数 --

FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange); //擦除某个sector

FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange); //擦除全部的sectors

FLASH_Status FLASH_EraseAllBank1Sectors(uint8_t VoltageRange); //用于STM32F42X系列和STM32F43X系列

FLASH_Status FLASH_EraseAllBank2Sectors(uint8_t VoltageRange); //用于STM32F42X系列和STM32F43X系列


-- 获取FLASH状态 --

FLASH_Status FLASH_GetStatus(void) //返回 FLASH操作的几个状态

返回值 :

typedef enum
{
FLASH_BUSY = 1,         //
操作忙
FLASH_ERROR_RD,         //读保护错误
FLASH_ERROR_PGS,        //编程顺序错误
FLASH_ERROR_PGP,        //编程并行位数错误
FLASH_ERROR_PGA,        //编程对齐错误
FLASH_ERROR_WRP,        //写保护错误
FLASH_ERROR_PROGRAM,   //编程错误
FLASH_ERROR_OPERATION, //操作错误
FLASH_COMPLETE           //操作结束
}FLASH_Status;


-- 等待操作完成函数 --

FLASH_Status FLASH_WaitForLastOperation(void) //在进行写或擦除操作时,不能进行代码或数据的读取操作。 

                                                       //在每次操作之前,我们都要等待上一次操作完成这次操作才能开始。