STM32 片内FLASH模拟EEPROM的优化方法

2019-07-20 10:05发布

芯片:STM32F407,1M片内FLASH。首先要知道STM32F407的FLASH的每个扇区的大小并不都一样,第0-3扇区每个扇区是16K,第4扇区是64K,后面的 每个扇区是128K。而出于某些方面的考虑,我们需要把某些数据存储到FLASH中,也就是把FLASH当作EEPROM来使用,这时就有个问题,STM32F407的FLASH在写操作之前,必须保证写入地址的数据为OXFF,否则无法写入。如果数据为非0XFF,则需要先把该扇区擦除后才能操作。而STM32F407的固件库只提供了四个 FLASH擦除函数:FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector,uint8_t VoltageRange); FLASH_Status FLASH_EraseAllSectors(uint8_tVoltageRange); FLASH_Status FLASH_EraseAllBank1Sectors(uint8_tVoltageRange); FLASH_Status FLASH_EraseAllBank2Sectors(uint8_tVoltageRange);   对于前面两个函数比较好理解,一个是用来擦除某个Sector,一个使用来擦除全部的 sectors。对于第三个和第四个函数,这里的话主要是针对STM32F42X 系列和 STM32F43X 系列芯片而言的,因为它们将所有的sectors 分为两个 bank。所以这两个函数用来擦除 2 bank 下的sectors的。 好,为FLASH_Sector_0~FLASH_Sector_11(对于我们使用的 STM32F407 最大是FLASH_Sector_11),对于这些函数的第二个参数,我们这里电源电压范围是 3.3V,所以选择 VoltageRange_3 即可。也就是说STM32F407FLASH不支持其他型号的芯片那种所谓的页擦除,如果我们存储数据在FLASH_Sector_11,那么在写入之前就要擦除整个128K的扇区,然后再往里面写数据,但这将需要1-2秒,如果在这段时间内突然就断电,那么写入FLASH中的数据将是不正确的。而且芯片的FLASH是有寿命的,如果我们不断的擦除,并且频率比较高,那芯片有可能就挂掉了。为此我们需要对FLASH模拟EEPROM进行优化。首先,为了提高安全性,直接使用FLASH_Sector_10FLASH_Sector_11这两个扇区,每个扇区是128K,加起来就是用了256K,那还剩下768K来给程序运行使用,这个是足够的。为了方便使用数据,建议将需要存储的数据做成结构体,比如 typedef struct{      U8saved[128];      U8data[128];      U32 total;}savedinfo;结构体的大小最好是4字节对齐。对于FLASH操作的普通思路是先擦除扇区,然后再写数据,但如果要写入的数据也就几百个字节,那这128K的扇区是真浪费了,但不擦除又写不进去。事实上,只要对扇区擦除过一次之后,扇区内的数据每位都是1,这个才是写入数据的前提。那么可以理解为,只要我们要写入的地址的数据不是0,那就可以往里面写数据。这样一来,我们就可以把128K扇区分成N块,每次写一块,然后下次再写下一块。但有个问题,比如我们存储数据的结构体大小为400字节,那是不是可以把128K扇区分成256块,每块512字节?理论上可行,但实际上STM32F407的FLASH貌似是以2K为一块来操作,也就是说你往FLASH_Sector_10的起始地址0x080C0000写400个字节的数据,而0x080C0800(0x080C0000+2048)以内的数据都被改变了,400字节以外的地址的数据从OXFF变成了0!所以128K最少要分成64块,每块2K。我们从FLASH_Sector_10开始存储,存满了64块之后,接着从FLASH_Sector_11开始存(这时就把FLASH_Sector_10给擦除掉),等FLASH_Sector_11存满之后又从FLASH_Sector_10开始存(这时就把FLASH_Sector_11给擦除掉)。在存储的过程中,需要先按照分好的块来查找需要写入的地址的数据是否是0XFF,不是则继续查找下一块,如此循环下去。       FLASH中读出数据的思路就是一个逆向的过程,先从FLASH_Sector_11的最后一块开始从后往FLASH_Sector_10地址开始查找,只要找到那个块的数据是非0XFF,就把数据读出来,而这个数据就是最新存储进去的数据。       为了方便从FLASH中读取数据和写数据,在结构体中最好记录下当前所在的扇区和块。思路给出了,程序就不贴了,目前这个方法在使用中比较稳定,FLASH的写入操作由于不用频繁进行扇区擦除而加快了很多。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。