微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 使用片上Flash存储参数

使用片上Flash存储参数

时间:10-02 整理:3721RD 点击:

我们的项目中需要保存一些系统配置参数,这些数据的特点是:数量少而且不需要经常修改,但又不能定义为常量,因为每台设备可能不一样而且在以后还有修改的可能。这就需要考虑这些参数保存的问题。将这类数据存在指定的位置,需要修改时直接修改存储位置的数值,需要使用时则直接读取,会是一种方便的做法。考虑到这些数据量比较少,使用专门的存储单元既不经济,也没有必要,恰好有些MCU拥有比较大的FLASH,使用少量来存储这些参数则既方便有经济。STM32F4的Flash架构如下:




这次NUCLEO-F412ZG测试板上的STM32F412ZG拥有1M的Flash,所以我们可以试试将参数保存到其片上Flash中。其Flash的组织模式如下:




根据上面的Flash组织模式,我们可以根据自己的使用方便来作相应的定义。从Sector5到Sector11大小都是128K,所以我们做如下宏定义:


  #defineSECTOR_SIZE           1024*128    //字节


虽然ST的库函数比较全面,但都是基本操作,为了使用方面,根据我们自己的需要对其进行再次封装。


对于读操作相对比较简单,内置闪存模块可以在通用地址空间直接寻址,就像读取变量一样。


//从指定地址开始读取多个数据


void FLASH_ReadMoreData(uint32_tstartAddress,uint16_t *readData,uint16_t countToRead)


{


  uint16_tdataIndex;


for(dataIndex=0;dataIndex<countToRead;dataIndex++)


  {


   readData[dataIndex]=FLASH_ReadHalfWord(startAddress+dataIndex*2);


  }


}



//读取指定地址的半字(16位数据)


uint16_t FLASH_ReadHalfWord(uint32_t address)


{


  return*(__IO uint16_t*)address;


}



//读取指定地址的全字(32位数据)


uint32_t FLASH_ReadWord(uint32_t address)


{


  uint32_ttemp1,temp2;


temp1=*(__IO uint16_t*)address;


temp2=*(__IO uint16_t*)(address+2);


  return(temp2<<16)+temp1;


}



对于写操作相对来说要复杂得多,写操作包括对用户数据的写入和擦除。为了防止误操作还有写保护锁。但这些基本的操作ST的库函数已经为我们写好了,我们只需要调用即可。


STM32复位后,FPEC模块是被保护的,只有在写保护被解除后,我们才能操作相关寄存器。STM32闪存的编程每次必须写入16位,任何不是半字的操作都会造成错误。如下图是Flash写的过程:




STM32的FLASH在编程的时候,也必须要求其写入地址的FLASH是被擦除了的(也就是其值必须是0XFFFF),否则无法写入。Flash的擦除要求必须整页擦除,所以也必须整页写入,否则可能会丢失数据。如下图是Flash页擦除过程:




如下为Flash全擦除过程,





根据以上图示我们便写数据写入函数如下:


//从指定地址开始写入多个数据


void FLASH_WriteMoreData(uint32_tstartAddress,uint16_t *writeData,uint16_t countToWrite)


{


if(startAddress<FLASH_BASE||((startAddress+countToWrite*2)>=(FLASH_BASE+1024*FLASH_SIZE)))


  {


   return;//非法地址


  }


FLASH_Unlock();         //解锁写保护


  uint32_toffsetAddress=startAddress-FLASH_BASE;               //计算去掉0X08000000后的实际偏移地址


  uint32_tsectorPosition=offsetAddress/SECTOR_SIZE;            //计算扇区地址,


  


  uint32_tsectorStartAddress=sectorPosition*SECTOR_SIZE+FLASH_BASE;    //对应扇区的首地址



FLASH_ErasePage(sectorStartAddress);//擦除这个扇区


  


  uint16_tdataIndex;


for(dataIndex=0;dataIndex<countToWrite;dataIndex++)


  {


   FLASH_ProgramHalfWord(startAddress+dataIndex*2,writeData[dataIndex]);


  }


  


FLASH_Lock();//上锁写保护


}


在擦除之前应该将页面上的数据读取出来与要写入的数据合并,待擦除后再写入,但这样数据量很大,所以考虑到是少量数据存储,所以每次都将全部数据同时写入,简化操作,也减少数据处理量。经测试以上程序写入和读出数据均正确,可以实现内部Flash的读写操作。

参考了ST的编程手册PM0081——STM32F40xxx 和 STM32F41xxx Flash编程手册。

学习了解一下                  

这个是方便,但是片上的Flash不能频繁的使用,有寿命

加个掉电保护就更好了

只是存储必要的参数

请问怎么加掉电保护呢?
谢谢!

写之前把原有数据读出来,如果掉电了恢复原有数据,根据标志判断

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top