STM32F407ZG FLASH + 定时读写FLASH计数值

本文详细介绍了STM32F407ZG开发板中闪存的读取、编程和擦除过程,以及如何通过控制寄存器进行操作。还阐述了定时读写Flash计数值的实现,利用TIM3定时器每10秒自增计数并保存到Flash中,同时展示了相关代码和实验结果。

闪存 FLASH

简介

Flash 又称为闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还可以快速读取数据(NVRAM的优势),使数据不会因为断电而丢失。
STM32 的 Flash 接口可管理 CPU 通过 AHB I-Code 和 D-Code 对 Flash 进行的访问。该接口可针对 Flash 执行擦除和编程操作,并实施读写保护机制。Flash 接口通过指令预取和缓存机制加速代码执行。
特性
特性
STM32F407ZG 的具体分区如下:
分区
主存储器,存放代码和数据常数(如const 类型的数据)。从上图可以看出主存储器的起始地址就是 0X08000000 。当 B0 、 B1 都接 GND 的时候,就是从 0X08000000 开始运行代码的。
系统存储器,主要用来存放STM32F4 的 bootloader 代码,此代码是出厂的时候就固化
在 STM32F4 里面了,专门来给主存储器下载代码的。当 B0 接 V3.3 B1 接 GND 的时候,从
该存储器启动(即进入串口下载模式)。
OTP 区域,即一次性可编程区域,共 528 字节,被分成两个部分,前面 512 字节( 32 字节为 1 块,分成 16 块),可以用来存储一些用户数据(一次性的,写完一次,永远不可以擦除!!),后面 16 字节,用于锁定对应块。这里的一次性是指写入一次后,再次写入的话是前后相与的值,两次不相同则会置零。
选项字节,用于配置读保护、BOR 级别、软件 硬件看门狗以及器件处于待机或停止模式下的复位。

闪存的读取

STM32F4 可通过内部的 I Code 指令总线D Code 数据总线访问内置闪存模块。为了准确读取 Flash 数据,必须根据 CPU 时钟 (HCLK) 频率和器件电源电压在 Flash 存取控 制寄存器 (FLASH_ACR) 中正确地编程等待周期数 (LATENCY)。当电源电压低于 2.1 V 时,必须关闭预取缓冲器。
等待周期设置
于是一般正常工作时(168MHz,3.3V),应设置 LATENCY 为 5 WS。

提高CPU频率
降低CPU频率
Flash 读取,即对 Flash 某个地址读一个字(32位),只要知道地址即可通过如下语句读取:
data = * (vu32 * )addr; //volatile unsigned int 32,每次读取需要重新取,不能直接读寄存器的值。

闪存的编程和擦除

执行任何 Flash 编程操作(擦除或编程)时,CPU 时钟频率 (HCLK) 不能低于 1 MHz。如果 在 Flash 操作期间发生器件复位,无法保证 Flash 中的内容。
在对 STM32F4xx 的 Flash 执行写入或擦除操作期间,任何读取 Flash 的尝试都会导致总线阻塞。只有在完成编程操作后,才能正确处理读操作。这意味着,写/擦除操作进行期间不能从 Flash 中执行代码或数据获取操作。
闪存的擦除和编程是通过设置寄存器的值来控制的。

编程步骤

  1. 检查 FLASH_SR 中的 BSY 位,确保当前未执行任何 FLASH 操作。
  2. 将 FLASH_CR 寄存器中的 PG 位置 1 ,激活 FLASH 编程。
  3. 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作:
    — 并行位数为 x8 时 按字节写入( PSIZE = 00 )
    — 并行位数为 x16 时按半字写入( PSIZE = 01 )
    — 并行位数为 x32 时按字写入( PSIZE = 02 )
    — 并行位数为 x64 时按双字写入( PSIZE = 03 )
  4. 等待 BSY 位清零,完成一次编程。

注意写入操作必须要在保证写入地址已被擦除。

擦除步骤

  1. 检查 FLASH_CR 的 LOCK 是否解锁,如果没有则先解锁
  2. 检查 FLASH_SR 寄存器中的 BSY 位,确保当前未执行任何 FLASH 操作
  3. 在 FLASH_CR 寄存器中,将 SER 位置 1 ,并从主存储块的 12 个扇区中选择要擦除的扇区(SNB)
  4. 将 FLASH_CR 寄存器中的 STRT 位置 1 ,触发擦除操作
  5. 等待 BSY 位清零

寄存器

访问控制寄存器 (FLASH_ACR)

用于使能/失能 数据缓存、指令缓存、预取 相关的功能,最重要的是在于低三位用于设置 LATENCY 的值。
在这里插入图片描述

控制寄存器 (FLASH_CR)

CR 有两种,分别对应 stm32f405xxx/407xxx/415xxx/417xxx 和 42xxx/43xxx 。这里贴出前者。
在这里插入图片描述
在这里插入图片描述

秘钥寄存器 (FLASH_KEYR)

此寄存器用于解锁 CR ,有固定的两个设置值,否则会将 CR 锁定。
在这里插入图片描述

状态寄存器 (FLASH_SR)

包括 BSY 繁忙标志各种错误标志EOP 操作结束标志 。具体见官方手册。
一般来说只有使能了相关错误中断,这些错误标志位才有意义。

选项控制寄存器 (FLASH_OPTCR)

对于OPT的控制,具体见官方手册。

选项秘钥寄存器 (FLASH_OPTKEYR)

与 KEYR 类似,用于解锁 OPTCR 。
在这里插入图片描述

定时读写 FLASH 计数值

需求

定时读写Flash,开机读取Flash计数值,每10秒钟计数加1并重新写入Flash保存。

思路

使用通用定时器 TIM3 设定重装值使定时为10s,每次自动重装时转入中断函数读取 Flash 计数值自增,并重新擦除写入。

实验过程中的一些问题

TIM 相关

  1. 实验中发现 TIM 初始化时,最开始也会进入一次中断,因此会导致还没开始计时就自增了一次。解决方法是使用了一个标志位,首次中断不做处理。
  2. TIM 触发中断后,会自动重装计数值,且中断函数的执行和计数互不影响。也就是说虽然对 Flash 的操作会有一定延迟,但并不影响计时,也不影响下一次中断(经实验擦写大概需要1s)。

代码

tim3 的配置详情见我的另一篇文章: STM32F4ZG TIM
tim3 的中断函数:

void TIM3_IRQHandler(void)
{
   
   
   if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) //判断发生中断
    {
   
   
        if(first_flag == 0) //首次中断仅打印计数值初始值
        {
   
   
            first_flag = 1;
            printf("%d\r\n", counter);
        }
        else
        {
   
   
            u32 load[1];
            LED1 = !LED1;
            counter++;
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值