根据ST的手册,我们可以看到,外挂EEPROM和Dflash模拟EEPROM,区别如下:
很明显,模拟EEprom的写入速度要远远快于外挂eeprom(有数据传输机制);
其次,外挂EEPROM不需要擦除即可实现写入数据;而模拟EEProm需要写之前擦除,由于Flash编程和擦除操作是相当长的时间,电源故障和其他可能中断擦除过程的异常事件(如重置)需要在设计Flash内存管理软件时考虑。
模拟EEPROM需要考虑产品要求和Flash IP特性;ST提出了一种方法,需要NVM中两组Flash page。
第一组page在最初已经被擦除了,用于存储新的数据,Flash编程操作按照地址递增进行;一旦第一组page被数据填充满,该page就需要进行数据垃圾回收(即擦除);
第二组page仅用于收集第一组page中的有效数据,并且剩余的区域可以用于存储新的数据;一旦第一组的有效数据传给了第二组,第一组page就可以被擦除了。
注意,每一组page都可以由多个flash page构成。每个page的前32byte(64byte)用于存储当前page状态;状态共有5种,如下:
状态 |
描述 |
备注 |
ERASED |
该page为空,没有存储数据 |
|
RECEIVE |
当前page从其他已满的page中接收数据 |
|
ACTIVE |
当前page用于存储新数据 |
|
VALID |
Page已满;该状态会一直持续到有效数据传递给接收page完成 |
|
ERASING |
有效数据已经传完,当前page准备擦除 |
以下图为例,
初始时刻,第一组page中page0,page1状态分别为ACTIVE(没有满,可以继续存储新数据),ERASED(空状态),第二组page中page2、3为ERASED;
当写入一个完整page+1大小数据时,Page0状态变为VALID(已经满了,该写page1了),page状态变为ACTIVE,为什么page0状态没有变为ERASING?原因在于第一组page还没有满,相当于逻辑的page没有满(用户可见),实际的page满了(flash的物理page存满了);因为第一组page没有满,所以第二组page还是ERASED状态;
当page1也写满时,第一组page全部写满,那么此时第二组page中的page2状态变为RECEIVE(正在接收有效数据)(这里有效数据如何定义),数据是按flash地址排列,因此最开始page3状态不变(因为page2还没有写满);
如果有效数据超过1个page(物理),那么page2状态会变为VALID,page3变为ACTIVE;
当擦除完成后,软件得到flash 擦除完成标志位,第一组page状态均变为ERASED。
上图为状态迁移流程图。
根据STM32描述,大部分的最小写入位宽为64bit(128bit for STM32U5),且因为表示状态的HEADER为4个double words(32bytes=4*8byte )(STM为8个word),因此如果一个芯片物理page大小为2K,那么可以写入252个元素(252*8 = 2*1024 - 32)数据,相当于一个元素就占用了8个byte,为什么要这样设计?参见下文的CRC
Page状态通过如下格式来定义(以4个word为例)
状态 |
||
ERASED |
0x FFFF FFFF FFFF FFFF |
|
RECEIVE |
0x xxxx FFFF FFFF FFFF |
|
ACTIVE |
0x FFFF yyyy FFFF FFFF |
|
VALID |
0x FFFF FFFF zzzz FFFF |
|
ERASING |
0x FFFF FFFF FFFF aaaa |
每个变量元素都由一个虚拟地址和一个存储在Flash中的数据值定义,以供后续检索或更新。在实际使用中,有可能虚拟地址为16bit,数据长度8bit、16bit或者32bit。当数据被修改时,与同一虚拟地址相关联的修改后的数据被存储在一个新的flash位置中。数据检索返回最新的数据值。数据格式如下:
现有如下变量需要存储到flash中,
很明显,现只需要两个page即可完成模拟。
数据读访问是从ACTIVE或者VALID page从高地址向低地址开始读取。
如果数据是在给定的虚拟地址上最新写入的数据,并且使用CRC的完整性检查通过,则认为数据有效。还要注意,在数据传输机制中只复制有效数据。
需要存储到模拟EEPROM的数据通常应用需求决定,例如传感器、通信接口数据;
常见的数据粒度有:byte、half-word、word。
这里可以思考Fee如何实现数据空间位置优化?
磨损均衡算法监控以及平均分配了flash page写和擦除操作的使用频率;
没有磨损均衡算法之前,page使用频率不会相同;例如有些数据会经常更新(例如DTC),而一些数据则不会频繁更新(例如VIN码等),很明显、存DTC的Flash会经常擦写、而存VIN这些DID的会很久或者几乎不会修改。那么磨损均衡算法就是来解决这种矛盾,保证flash所有page的所有可用擦写次数都得到利用。
所有在3Demo章节中,采用了按照地址递增的方式进行数据存储,不管用户存的变量是什么,当一个page满了之后,再保存有效数据到下个page,擦除当前页;
可以这么理解,现在要存3个DTC和1个DID,磨损均衡算法都首先用active的page进行存储,DID存放之后不怎么变化,但是DTC每次上下电都有可能存储,因此会继续沿着当前page地址递增存储DTC,直到该page存满。
磨损均衡算法提高模拟EEPROM使用寿命,
在知道了模拟EEPROM的要求大小和目标使用次数,就有可能计算出用于该目的的Flash大小。
那么如何计算,参考如下公式
假设现在要存放4000个独立byte,已知当前flash endurance = 10kcycles,目标为100kcycle,每一个page可以存储252个8byte的元素;
故需要4000/252≈16个page;因此一组page个数为32,再加上需要100kcycle的耐久度,所以还需要乘以10,故总共需要的size为32*10=320个page;
注:这里的page为实际的物理sector。
如果是按CS的DFLASH来算,一个sector(page)=1K。一个page可以存124个元素;故存4000个独立byte,需要4000/124 = 33个sector,那么要实现模拟EEPROM,就至少需要66*10=660个sector;我们的DFLASH大小明显不符合要求;故需要重新设计存储数据格式。