(转载)关于FLASH寿命的读写方法
Posted 雨航
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(转载)关于FLASH寿命的读写方法相关的知识,希望对你有一定的参考价值。
http://blog.chinaunix.net/uid-20737871-id-1881191.html
NAND FLASH 比NOR FLASH 容量大,价格低, NAND flash中每个块的最大擦写次数为100万次,而NOR 10W次, FLASH 编程原理都是只能把1变成0,而不能把0写为1, 所以在FLASH 编程之前,都要把对应的块擦除,擦除的过程就是把所有位都写为1,块内所有字节都变为0xFF。
NAND Flash芯片的种种不足,则需要靠控制芯片或操作系统软件来补足,动态平均抹写(Dynamic Wear Leveling)就是NAND Flash控制芯片技术上的一项重要设计,可以将写入的资料平均在每一个NAND Flash芯片的区块上,而非重复写入同一个区块,造成NAND Flash芯片的损害,可以顺利延长NAND Flash芯片使用寿命,因此Wear-Leveling技术几乎是NAND Flash控制芯片设计上的必备。
Static Wear Leveler
Let the Static Wear Leveler (SW Leveler) be associated with a Block Erasing Table (BET) to remember which block has been erased in a selected period of time. The SW Leveler is activated by some system parameters for the needs of static wear levelling. When the SW Leveler is running, it either resets the BET or picks up a block that has not been erased so far (based on the BET information) and triggers the Cleaner to do garbage collection on the block. The selection procedure of a block must be done in an efficient way within a bounded amount of time. Note that the BET must be updated whenever a block is erased. It could be done by a triggering action to the SW Leveler. The design of the BET must be scalable because of the rapid increasing of flash-memory capacity and the limited RAM space on a controller. Whenever a block is recycled by garbage collection, any modification to the address translation is done as the original design of a Flash Translation Layer driver. The implementation of the SW Leveler could be a thread or a procedure triggered by a timer or the Allocator/Cleaner based on some preset conditions.
The SW Leveler is invoked by the Cleaner to update the BET whenever any block is erased by the Cleaner in garbage collection when static wear levelling is needed. We can use two variables to keep track of the total number of block erases done since the BET is reset and the number of 1’s in the BET. If the ratio of the two tracked number is too high, the SW Leveler is triggered to move cold data from their original place by requesting the Cleaner to reclaim those blocks whose corresponding bit in the Block Erasing Table is 0.
Block Erasing Table
The purpose of the Block Erasing Table (BET) is to remember which block has been erased in a pre-determined time frame, referred to as the resetting interval, so as to locate blocks of cold data. A BET is a bit array, in which each bit corresponds to a set of 2k contiguous blocks where k is an integer that is larger or equal to 0. Whenever a block is erased by the Cleaner, the SW Leveler is triggered to set the corresponding bit as 1.
动态平均读写解决了块的 Erase 周期的次数限制。动态平均读写算法并不是随机使用可用的块,而是平均使用块,因此,每个块都获得了相同的使用机会。静态平均读写算法解决了一个更有趣的问 题。除了最大化 Erase 周期的次数外,某些 flash 设备在两个 Erase 周期之间还受到最大化 Read 周期的影响。这意味着如果数据在块中存储的时间太长并且被读了很多次,数据会逐渐消耗直至丢失。静态平均读写算法解决了这一问题,因为它可以定期将数据移 动到新块。开发电子产品时,常常需要断电后保存某些数据,这就需要使用FLASH或EEPROM芯片,这两种芯片,可擦除的次数是有限制的,通常FLASH为10万 次,EEPROM要多一点,为100万甚至1000万次。FLASH的擦除不能单个字节进行,有一个最小单位,存储容量相对比较大,适合大量数据的存 储;EEPROM可以单个字节进行擦除,存储容量不大,只适合存储少量的设置数据。
先以FLASH和EEPROM需要写入一个字节为例来说明新数据是如何写入的。假定都是在首地址要写入新数据0x55。不管是FLASH还是EEPROM
对于FLASH,写操作只能将数据位从1改写为0,如果想要将数据位从0改为1,就需要进行擦除操作,而且这个擦除最小单位是page(可能是256字节 或更多)。现在要在首地址写入0x55,稳妥的方法是先擦除这个地方,也就是要擦除第一个page,擦除操作会一并将首地址后面的另外255个字节也擦除 掉,如果这255个字节保存有其它数据,还需要把这些数据先进行备份,擦除第一个page后再将0x55和备份的255个字节写进去。也不是必须擦除第一 个page,写操作可以完成数据位1到0的转变,利用这一特性结合首地址原来的内容,我们就有可能不用进行擦除操作,比如原来内容为0xFF,显然可以直 接写入0x55,原内容为0xF5,同样也可以写入0x55,但如果原内容为0xAA,执行写0x55则会得到完全错误的结果,写完后内容依然为 0x00,因为对于0x55所有需要保持为1的位数据0xAA都是0,写0x55会把0xAA为1的位全清0,原来为0的位不会改变。
对于EEPROM,写操作既可以将数据位从1改写为0,也可以将数据位从0改写为1,不需要进行单独的擦除操作,要写0x55直接将0x55写到首地址, 不管原来内容为什么,完成写操作后内容都是0x55。
一开始我们说了FLASH和EEPROM都有可擦除的最大次数(EEPROM实际上没有擦除操作),虽然这个数字看着不小,但对于程序来说并不大,比如 EEPROM为10万次,如果我们以每秒一次的间隔依次写入0xFF和0x00,则只能维持100000/3600=27.78小时,也就是一天多就可以 超出其最大寿命次数,不能再可靠写入所需的内容。
这种可写入的最大次数是芯片的特性决定的,我们无法改变,所以在使用这些芯片时,我们应充分考虑最大写入次数这一参数,要确保产品在实际工作中不超过这一 参数。实际上许多时候只要程序做出针对性处理,有可能让产品的最大写入次数超过芯片的寿命,还是以EEPROM来做说明。
假定现在有一个产品,需要保存一些参数,参数的个数并不多,总共为10个字节,用EEPROM来保存就可以满足需求,我们选用了容量为256字节的 EEPROM,如果我们不做过多考虑,很有可能就是直接将这10个字节从EEPROM的首地址开始保存,每次改写也是直接修改这部分内容,这样我们最多可 以保存参数10万次。只要我们做一点简单处理,就可以将保存参数的次数成倍增加,来看看我们应该如何实现。
直接保存的最简方法:
地址 0x00 0x01 0x02 ... 0x09
内容 data1 data2 data3 ... data10
改进的保存方法:
处理方法是将256字节按16字节大小分成16等份,按后面格式存储参数
地址 0x10*n +0x00 +0x01 +0x02 ... +0x09 +0x0A +0x0B +0x0C +0x0D +0x0E +0x0F
内容 flag data1 data2 ... data9 data10 保留1 保留2 保留3 保留4 check_sum
check_sum=(flag+data1+data2+...+data10+保留1+...+保留4 )&0xFF
flag为0xA5表示当前16个字节为正在使用的记录,为其它值表示当前16字节已经丢弃
读取参数的时候先从地址0x10*n+0x00读flag,如果为0xA5表明当前记录为正在使用中,读出全部内容,并按前面公式进行校验,如果校验出 错,则当前参数不可靠,直接使用默认参数,并将当前区域的flag改写为0,同时在地址0x10*(n+1)位置开始将默认参数写入,地址0x10* (n+1)写入内容为0xA5。如果所有区域都没有发现有效记录,在地址0写入默认参数。
每次需要更改参数设定时,先将当前记录位置的flag改为0,然后再下一条记录位置写入新的参数,这个顺序可以做出适当改进,比如对写入时断电等意外情况 做出考虑,从而得到更可靠的写入结果,不过就按此方法也都可以满足应用需求。
再来对比一下两种方法,最简方法只能保存10万次,改进的方法理论上增加了16倍,达到160万次,如果预估最简方法产品是3年内绝对不会出错,现在就增 加到了48年,一个电子产品使用超过3年还是有可能,但用48年的可能性就非常之小,可以视同为0。对于FLASH芯片也是同样道理,这里就不重复举例说 明,在应用中也应该做出同样的处理。
以上是关于(转载)关于FLASH寿命的读写方法的主要内容,如果未能解决你的问题,请参考以下文章
STM32+ESP8266+AIR202/302远程升级方案-程序优化-如果判断Flash需要擦除再擦除Flash,提高Flash使用寿命