学习使用FLASH存储器的STM32教程

一、FLASH简介

  • STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程。
  • 程序存储器(主存储器):存储程序代码;起始地址:0x0800 0000
  • 系统存储器:存储Bootloader,用于串口下载;起始地址:0x1FFF F000
  • 选项字节:存储独立的配置参数;起始地址:0x1FFF F800
  • 闪存存储器接口即为STM32的FLASH外设,由于直接对FLASH进行操作较为复杂,所以借助FLASH外设,通过操作外设的寄存器,由外设自动对FLASH进行擦除和编程。
  • 读写FLASH的用途:
  • 利用程序存储器的剩余空间来保存掉电不丢失的用户数据
  • 通过在程序中编程(IAP),实现程序的自我更新
  • 在线编程(In-Circuit Programming – ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序
  • 在程序中编程(In-Application Programming – IAP)可以使用微控制器支持的任一种通信接口下载程序。

  • 二、FLASH外设基本结构

  • 橙色部分为FLASH存储器;绿色部分为FLASH外设,是FLASH存储器的“管理员”。

  • 三、FLASH流程

    FLASH解锁

  • FPEC共有三个键值:
  • RDPRT键 = 0x000000A5
  • KEY1 = 0x45670123
  • KEY2 = 0xCDEF89AB
  • 解锁:
  • 复位后,FPEC被保护,不能写入FLASH_CR
  • 在FLASH_KEYR先写入KEY1,再写入KEY2,解锁
  • 错误的操作序列会在下次复位前锁死FPEC和FLASH_CR
  • 加锁:
  • 设置FLASH_CR中的LOCK位锁住FPEC和FLASH_CR
  • 程序存储器编程(写入)

  • 注意:每次只能写入一个半字(16位),任何非半字的数据都会导致错误
  • 程序存储器页擦除

    程序存储器全擦除

    选项字节

  • RDP:写入RDPRT键(0x000000A5)后解除读保护
  • USER:配置硬件看门狗和进入停机/待机模式是否产生复位
  • Data0/1:用户可自定义使用
  • WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)

  • 四、FLASH配置

    uint32_t MyFlash_ReadWord(uint32_t Address)
    {
    	return *((__IO uint32_t *)(Address));
    }
    
    uint16_t MyFlash_ReadHalfWord(uint32_t Address)
    {
    	return *((__IO uint16_t *)(Address));
    }
    
    uint8_t MyFlash_ReadByte(uint32_t Address)
    {
    	return *((__IO uint8_t *)(Address));
    }
    
    void MyFlash_EraseAllPages(void)
    {
    	FLASH_Unlock();				// 解锁
    	FLASH_EraseAllPages();		// 全擦除
    	FLASH_Lock();				// 加锁
    }
    
    void MyFlash_EraseAPage(uint32_t PageAddress)
    {
    	FLASH_Unlock();					// 解锁
    	FLASH_ErasePage(PageAddress);	// 页擦除
    	FLASH_Lock();					// 加锁	
    }
    
    void MyFlash_ProgramWord(uint32_t Address, uint32_t Data)
    {
    	FLASH_Unlock();						// 解锁
    	FLASH_ProgramWord(Address, Data);	// 写入字
    	FLASH_Lock();						// 加锁	
    }
    
    void MyFlash_ProgramWord(uint32_t Address, uint32_t Data)
    {
    	FLASH_Unlock();							// 解锁
    	FLASH_ProgramHalfWord(Address, Data);	// 写入半字
    	FLASH_Lock();							// 加锁	
    
    '对闪存读写的基本逻辑是:上电时将闪存读取到SRAM内存中,下电前再写回闪存,避免频繁的读写闪存'
    '因为在读写FLASH闪存时,CPU会停止,会可能导致中断程序无法按时执行'
    }
    

    五、FLASH库函数

    void FLASH_SetLatency(uint32_t FLASH_Latency);
    void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess);
    void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer);
    void FLASH_Unlock(void);
    		// FLASH解锁
    void FLASH_Lock(void);
    		// FLASH加锁
    FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
    		// 擦除某页
    FLASH_Status FLASH_EraseAllPages(void);
    		// 全擦除
    FLASH_Status FLASH_EraseOptionBytes(void);
    		// 擦除选项字节
    FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);
    		// 在指定地址写入全字(32位),其实是写入两次半字
    FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
    		// 在指定地址写入半字(16位)
    // 以下四个函数为选项字节写入函数		
    FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
    FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
    FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);
    FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY);
    //以下三个函数为获取选项字节当前状态
    uint32_t FLASH_GetUserOptionByte(void);
    uint32_t FLASH_GetWriteProtectionOptionByte(void);
    FlagStatus FLASH_GetReadOutProtectionStatus(void);
    
    FlagStatus FLASH_GetPrefetchBufferStatus(void);
    void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState);
    		// 中断使能
    FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG);
    		// 获取标志位
    void FLASH_ClearFlag(uint32_t FLASH_FLAG);
    		// 清除标志位
    FLASH_Status FLASH_GetStatus(void);
    		// 获取状态
    FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
    		// 等待忙
    

    五、补充

    使用指针访问存储器

  • 使用指针指定地址下的存储器:
    uint16_t Data = *((__IO uint16_t *)(0x08000000));
  • 使用指针指定地址下的存储器:
    *((__IO uint16_t *)(0x08000000)) = 0x1234;
  • 其中:
    #define __IO volatile
    易变的,直接存取原始内存地址,防止编译器优化。
  • 电子签名

  • 存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名
  • 闪存容量寄存器:
    基地址:0x1FFF F7E0
    大小:16位
  • 产品唯一身份标识寄存器:
    基地址: 0x1FFF F7E8
    大小:96位

  • Reference
    STM32入门教程-2023版(江科大)

    物联沃分享整理
    物联沃-IOTWORD物联网 » 学习使用FLASH存储器的STM32教程

    发表评论