zoukankan      html  css  js  c++  java
  • STM32(二十五)读写内部flash

    一、内部flash简介

    • STM32 芯片内部有一个 FLASH 存储器,它主要用于存储代码 。
    • 我们在电脑上编写好应用程序后,使用下载器把编译后的代码文件烧录到该内部 FLASH 中 。
    • FLASH 储器的内容在掉电后不会丢失,芯片重新上电复位后,内核可从内部 FLASH 中加载代码并运行。  
    • 访问内部flash的速度比外部的SPI-Flash要快。
    • flash擦除时是按扇区擦除,使用电擦除,设备电压1.8V ~2.1V按字节(8bit)擦除,2.1V ~2.7V擦除半字(16bit),2.7V ~ 3.6V擦除一个字(32bit)

               2.7V to 3.6V +外部电压擦除两个字(64bit),

    二、内部flash的构成

      STM32 的内部 FLASH 包含主存储器系统存储器以及选项字节区域,它们的地址分布及大小见下表。

     1、主存储器
    • 一般我们说STM32内部FLASH的时候,都是指这个主存储器区域,它是存储用户应用程序的空间,芯片型号说明中的256K FLASH、512K FLASH都是指这个区域的大小。
    • 主存储器分为256页,每须大小为2KB,共512KB。这个分页的概念,实质就是FLASH存储器的扇区,与其它FLASH - -样,在写入数据前,要先按页(扇区)擦除。

     

    2、系统存储区

      系统存储区是用户不能访问的区域,它在芯片出厂时已经固化了启动代码,它负实现串口、 USB 以及 CAN ISP 烧录功能。 

    3、选项字节

      选项字节用于配置 FLASH 的读写保护、待机/停机复位、软件/硬件看门狗等功能,这部分共 16 字节。可以通过修改 FLASH 的选项控制寄存器修改。 

    三、对内部flash的写入过程

    1.解锁

      由于内部FLASH空间主要存储的是应用程序,是非常关键的数据,为了防止误操作修改了这些内容,芯片复位后默认会给控制寄存器FLASH _CR上锁,这个时候不允许设置FLASH的控制寄存器,从而不能修改FLASH中的内容。所以对FLASH写入数据前,需要先给它解锁。解锁的操作步骤如下:

    (1) 往FPEC键寄存器FLASH_ KEYR中写入KEY1 = 0x45670123

    (2)再往FPEC键寄存器FLASH_ KEYR中写入KEY2 = 0xCDEF89AB

    2.页擦除.

      在写入新的数据前,需要先擦除存储区域,STM32提供了页(扇区)擦除指令和整个FLASH擦除(批量擦除)的指令,批量擦除指令仅针对主存储区。页擦除的过程如下:

      (1) 检查FLASH_ SR寄存器中的“忙碌寄存器位BSY”,以确认当前未执行任何Flash操作;

      (2)在FLASH_ CR寄存器中,将“激活页擦除寄存器位PER”置1。

      (3)用FLASHAR寄存器选择要擦除的页;

      (4) 将FLASH _CR寄存器中的“开始擦除寄存器位STRT"置1,开始擦除;

      (5)等待BSY位被清零时,表示擦除完成。

    3.写入数据

      擦除完毕后即可写入数据,写入数据的过程并不是仅仅使用指针向地址赋值,赋值前还还需要配置一-系列的寄存器,步骤如下:

      (1) 检查FLASH_ SR中的BSY位,以确认当前未执行任何其它的内部Flash操作;

      (2) 将FLASH_ CR寄存器中的“激活编程寄存器位PG”置1;

      (3)向指定的FLASH存储器地址执行数据写入操作,每次只能以16位的方式写入;

      (4)等待 BSY位被清零时,表示写入完成。

    /**
      * @brief  InternalFlash_Test,对内部FLASH进行读写测试
      * @param  None
      * @retval None
      */
    int InternalFlash_Test(void)
    {
    	uint32_t EraseCounter = 0x00; 	//记录要擦除多少页
    	uint32_t Address = 0x00;				//记录写入的地址
    	uint32_t Data = 0x3210ABCD;			//记录写入的数据
    	uint32_t NbrOfPage = 0x00;			//记录写入多少页
    	
    	FLASH_Status FLASHStatus = FLASH_COMPLETE; //记录每次擦除的结果	
    	TestStatus MemoryProgramStatus = PASSED;//记录整个测试结果
    	
    
      /* 解锁 */
      FLASH_Unlock();
    
      /* 计算要擦除多少页 */
      NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
    
      /* 清空所有标志位 */
      FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);	
    
      /* 按页擦除*/
      for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
      {
        FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
      
    	}
      
      /* 向内部FLASH写入数据 */
      Address = WRITE_START_ADDR;
    
      while((Address < WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
      {
        FLASHStatus = FLASH_ProgramWord(Address, Data);
        Address = Address + 4;
      }
    
      FLASH_Lock();
      
      /* 检查写入的数据是否正确 */
      Address = WRITE_START_ADDR;
    
      while((Address < WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
      {
        if((*(__IO uint32_t*) Address) != Data)
        {
          MemoryProgramStatus = FAILED;
        }
        Address += 4;
      }
    	return MemoryProgramStatus;
    }
    

      

    思考题1flash擦除完之后,扇区里面所有的数据是什么?

      :所有的数据都是为0xFF,所有bit位都是1。
    0

    思考题2假如说现在已经擦除完扇区,先写入了1个字,然后在下一个偏移地址再次写入新的字是否在需要擦除扇区?

      答案:不需要的。

    思考题3:假如说现在已经擦除完扇区,先写了1个字,然后在同一个地址再次写入新的字是否需要擦除扇区?

      答案:需要进行擦除!
    例子,已经写入数据为0x12345678,然后再写入新的数据为0x1111111,最后得到的数据居然是0x101010.
    0

    总结:

      判断是否允许写入字,只需要判断当前的地址存储的数据是否为0xFFFFFFFF,若为0xFFFFFFFF,可以写入数据,不需要进行扇区擦除。
     

     

     

     

  • 相关阅读:
    kvm虚拟迁移(5)
    kvm虚拟化网络管理(4)
    计算系数
    排列组合
    错排
    加分二叉树
    皇宫看守
    战略游戏
    数字转换
    JDK8 HashMap源码分析
  • 原文地址:https://www.cnblogs.com/yuanqiangfei/p/14468852.html
Copyright © 2011-2022 走看看