打印
[APM32F1]

【小白篇】如何操作FLASH的擦读写

[复制链接]
612|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
多云转晴|  楼主 | 2022-4-14 17:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 多云转晴 于 2022-4-14 17:51 编辑

         FLASH,全称为“FLASH Memory”,属于内存器件的一种,是一种不挥发性(Non-Volatile)内存。但由于它特殊的物理特性,导致它与其他常见内存有根本性的差异;比如像SDRAMRDRAM都属于挥发性内存,只要掉电,内存里的数据就无法保持,但FLASH不同,它在无电流供应的条件下也可以长久地保存数据,相当于一个硬盘。
         FLASH根据不同容量大小,闪存模块组织又有小容量、中容量、大容量等不同的分类,因此在使用之前需要先查看手册,了解当前所使用的FLASH为哪类产品,它的FLASH大小为多少,每一页共有多少个字节以及其他必要信息。
    下面,将介绍如何进行FLASH的擦读写操作。
          PS:将通过程序实例进行介绍,使用的芯片型号为APM32F103RBT6
          FLASH128K  每页1k   SRAM:20K


一、头文件包含和宏定义操作
#ifndef __FLASH__H_
#define __FLASH__H_

#include "apm32f10x.h"
#include "Board.h"
#include "apm32f10x_fmc.h"

/*FLASH 128K  SRAM 20K*/
#define Start_Addr                       ((uint32_t)0x08000000)        //FLASH的起始地址
#define End_Addr                        ((uint32_t)0x08020000)        //FLASH的结束地址
#define Flash_Page_Size              ((uint32_t)0x00000400)        //每页FLASH的大小
#define FLASH_PASS                   1                                        //FLASH擦写成功标志
#define FLASH_FAILED                0                                       //FLASH擦写失败标志

void Flash_Init(uint32_t start_addr,uint32_t end_addr);

#endif


二、定义一个函数(用于FLASH的初始化等操作)
void Flash_Init(uint32_t start_addr,uint32_t end_addr)
设置的两个形参用于向函数传入FLASH操作的起始地址和结束地址。


三、定义各类变量,以便后续使用
uint32_t Write_addr = 0,i = 0;//定义写入的起始地址
uint32_t Data_Input[2] = {0x5a5a5a5a,0xa5a5a5a5};//定义写入的数据
uint32_t Data_counter = 0,Data_flag = 0;//定义写入数据的标志位
uint32_t Memory_Flag = FLASH_PASS;//定义写入数据状态标志位
uint32_t Flash_Page = ((end_addr - start_addr)/Flash_Page_Size);//页数计算

PS:
          Write_addr作为一个局部变量,在每次需要对地址进行偏移时,可以操作该变量,保证传入的起始地址一直为同一个。
          Data_Input是一个数组,存放写入FLASH的值。
          Data_counter用来计数,Data_flag用来做标志位判断,使FLASH能写入不同的值。
          Memory_Flag用来判定FLASH的操作是否成功。
          Flash_Page是根据传入的起始地址和结束地址计算FLASH一共分为多少页。


四、对FLASH进行解锁操作(FLASH在锁定状态下无法擦写)
FMC_Unlock();//FLASH解锁
FMC_ClearStatusFlag(FMC_FLAG_OC|FMC_FLAG_PE|FMC_FLAG_WPE);//清除标志位


五、FLASH进行擦除操作
Write_addr = start_addr;//将传输进来的起始地址赋给局部变量操作
①全擦操作:
  /*先执行擦除操作*/
  FMC_EraseAllPage();//全片擦除
②页擦操作:
  /*页擦*/
  for(i = 0;i < Flash_Page;i++)
  {
    FMC_ErasePage(Write_addr);
    Write_addr += start_addr + (Flash_Page_Size * i);
  }
PS:全擦即为FLASH的整片擦除;页擦是根据自己的需要,向页擦函数传入首地址,擦除指定的区域,上面的页擦函数是通过页擦,擦除整片FLASH的操作(每擦除一页进行一次地址偏移)。


六、FLASH进行擦除验证
Write_addr = start_addr;//将传输进来的起始地址赋给局部变量操作
  /*擦除校验*/
  while(Write_addr < end_addr)
  {
    if(*(uint32_t*)Write_addr != 0XFFFFFFFF)
    {
      Memory_Flag = FLASH_FAILED;
    }
    Write_addr += 4;
  }
PS:在擦除操作结束后,通过判断每个位是否为FF,来判断程序是否擦除成功;若擦除失败或有部分擦除不成功,标志位会被置为FAILED状态(后续可通过自己的想法增加判断的方法,例如串口打印等)。


七、FLASH进行写操作
Write_addr = start_addr;//将传输进来的起始地址赋给局部变量操作
  /*进行写入数据操作*/
  while(Write_addr < end_addr)
  {
    FMC_ProgramWord(Write_addr,Data_Input[Data_flag]);//数据写入对应地址
    Data_counter++;//计数标志位开始累加
    Write_addr += 4;//地址偏移
    if(Data_counter == 256)
    {
      Data_counter = 0;//计数标志位清零
      Data_flag = !Data_flag;//翻转标志位进行翻转
    }
    FMC_ClearStatusFlag(FMC_FLAG_OC|FMC_FLAG_PE|FMC_FLAG_WPE);//清除标志位
  }
PS:从起始地址开始写入数据,每次写入一个字的大小,同时Data_counter开始计数,即每写入1k字节就换一个数据,直至写到结束地址。


八、对写入的数据进行校验
Write_addr = start_addr;//将传输进来的起始地址赋给局部变量操作
  /*写入数据验证*/
  Data_counter = 0;//计数标志位清零
  Data_flag = 0;//初始化翻转标志位
  while(Write_addr < end_addr)
  {
    if(*(uint32_t*)Write_addr != Data_Input[Data_flag])
    {
      Memory_Flag = FLASH_FAILED;
    }
    Data_counter++;//计数标志位开始累加
    Write_addr += 4;//地址偏移
    if(Data_counter == 256)
    {
      Data_counter = 0;//计数标志位清零
      Data_flag = !Data_flag;//翻转标志位进行翻转
    }
  }
PS:校验方法与擦除校验的方法类似,通过地址偏移来判断每个位是否准确写入了预定的数据,若出现异常,则可以通过标志位判断出来。


九、重新上锁、并做最终判断
FMC_Lock();//FLASH重新上锁
Data_counter = 0;
Data_flag = 0;

if(Memory_Flag == FLASH_PASS)
{
   //FLASH擦写成功
}
else
{
   //FLASH擦写失败
}


十、注意事项
(1)若进行FLASH操作,那么存储和运行程序的工作就得交给SRAM执行,如何使用SRAM操作,可以查看我的上一篇帖子;
(2)上面只说到FLASH的擦和写,读的方法是在debug调试状态时,通过memory来查看对应地址的信息,就可以知道FLASH是否操作成功;
(3)上面已经提到过,在操作之前,要先知道自己使用的FLASH是多大容量,每页有多少字节,地址范围是多少以及使用的芯片的SRAM大小。


使用特权

评论回复
沙发
onemoren| | 2022-4-15 09:54 | 只看该作者
有参考意义。谢谢!

使用特权

评论回复
板凳
一个人破| | 2022-4-15 10:12 | 只看该作者
有用,适合我这种小白。如果有手册查找指南就好咯,懒如我,哈哈哈

使用特权

评论回复
地板
duo点| | 2022-4-17 19:18 | 只看该作者
比较有参考意义

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

11

帖子

0

粉丝