FLASH延长写寿命算法

NOR(或非)和NAND(与非)是市场上两种主要的Flash闪存,sNORFLASH 和CPU之间不须要其余电路控制,NOR flash能够芯片内执行程序,而NAND FLASH 和CPU 的接口必须由相应的控制电路进行转换, NAND FLASH 以块的方式进行访问,不支持芯片内执行。 
    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 Levelerapi

    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.spa

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.scala

    动态平均读写解决了块的 Erase 周期的次数限制。动态平均读写算法并非随机使用可用的块,而是平均使用块,所以,每一个块都得到了相同的使用机会。静态平均读写算法解决了一个更有趣的问题。除了最大化 Erase 周期的次数外,某些 flash 设备在两个 Erase 周期之间还受到最大化 Read 周期的影响。这意味着若是数据在块中存储的时间太长而且被读了不少次,数据会逐渐消耗直至丢失。静态平均读写算法解决了这一问题,由于它能够按期将数据移动到新块。设计

    开发电子产品时,经常须要断电后保存某些数据,这就须要使用FLASH或EEPROM芯片,这两种芯片,可擦除的次数是有限制的,一般FLASH为10万次,EEPROM要多一点,为100万甚至1000万次。FLASH的擦除不能单个字节进行,有一个最小单位,存储容量相对比较大,适合大量数据的存储;EEPROM能够单个字节进行擦除,存储容量不大,只适合存储少许的设置数据。指针

    先以FLASH和EEPROM须要写入一个字节为例来讲明新数据是如何写入的。假定都是在首地址要写入新数据0x55。无论是FLASH仍是EEPROMorm

    对于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芯片也是一样道理,这里就不重复举例说明,在应用中也应该作出一样的处理。

 

《用变址寻址原理突破EEPROM存储器的擦写寿命极限》

    通常地,EEPROM存储器(如93C46/56/66系列)的擦写次数为10万次,超过这一极限时,该单元就没法再使用了。但在实际应用中,可能有些数据要反复改写。这时,可经过变址寻址的方式来突破EEPROM存储器的擦写寿命极限。

    好比,咱们有一个单字节的数据要保存在E2PROM(93C56)中,可按如下方法来作:

    一、将93C56的00H单元定义为地址指针存放单元。
    二、将要寻址的单元地址(假设为01H)放入93C56的00H地址中。
    三、每次要对E2PROM中的数据进行读写时,先读取00H中的数据,并以读出的值为地址,访问其指向的单元。
    四、在每次写完数据后,当即将数据再读出,并与写入的地址作比较。
        A、若是相等,则表明本次写入数据成功。
        B、若是不相等,则表明本次写入数据失败。这时,将00H中的值+1,让其指向后一个新的地址单元,再将数据写入新的地址单元。
   
    93C56共有128个字节单元,按照以上方法,可将数据的擦写次数提高120多倍!达到1200多万次!

    对于24C16/32/64系列的芯片,也可采用这种方法。

    这个方法,小匠使用过屡次,证实是可行的。

 

补充二点

1. EEPROM单元坏与不坏界线非常模糊. EEPROM单元能写入信息是由于它的浮栅能俘获电子并将其困在其中. 但随着时间的推移电子因为热运动或外界给予能量会逐渐逃逸, 因此说EEPROM保持信息是有必定年限的(好比100年). 写入与擦除信息便是向浮栅注入和释放电子,电子能量比较高,可能改变周围的晶格结构,致使浮栅俘获电子能力的降低,也就是表现为保存信息的时间变短, 因此才会有一个保守的写入次数限制(这里说保守是由于半导体的离散性大,实际的次数大得多). 到了规定写入次数并非说该单元就坏了, 而是说该单元保持信息的时间已不可信赖(而实际上它可能还能保存至关长时间甚至几十上百年),因此实际上短期很难断定某个单元是否可用(坏了). 如匠人的方法检测, 写入时测试好好的, 可能几秒钟以后该单元的数就逃了.

2. 写坏一个单元是很费时间的, "这个方法,小匠使用过屡次,证实是可行的。", 不知匠人在使用过程当中是否碰到过有写坏的状况?

我的意见请朋友们扔....

 

 云起 发表于 2002-1-22 05:01 侃单片机 ←返回版面    

能够改进

00H存放地址,01H 02H存放次数,每次读写次数+1,达到65535次(FFH),地址指针+1,轮流写过去。

 

一、SOHO的分析真是深入,你提出“写入时测试好好的, 可能几秒钟以后该单元的数就逃了.”我想,若是用亢余技术来处理的话,也许能回避你所说的问题。

二、TO 云起:你的方法是不可行的,若是按你的方法,数据改写10万次, 01H 02H单元的次数也改写了10万次,那不是也坏了吗?

三、TO telesoft :你的担忧是多余的,时序的问题,小匠固然考虑到了。;--)

四、TO jw5th:被你称为“智者”,小匠真是脸红……

 soho 发表于 2002-1-22 20:22 侃单片机 ←返回版面    

匠人提供了一个好思路, 方法稍做修改如何

为了保证EEPROM内的数据能够长久保存, 每一个单元的写入次数不能超过规定的限值, 借用匠人和云起的思路,本人提出改进方案:

数据以块为单位存放, 每块可取4个字节, 前三个字节记录写入次数,第四个字节为要保存的数. 每次做写入操做时, 把次数+1连同数据一超写入EEPROM.
EEPROM前面开辟一个索引指针区(可供N个数据保存用), 存放数据块的地址由指针计算所得, 计算方法是:基址+指针值*数据块长度. 当某块区域的写入次数到达时, 调整指针指向下一个可用的数据区域.

这样,EEPROM的空间利用率<<25%, 用来换取写入次数>>写入寿命, 方法是否可取, 请诸位拍转.

 

 

 程序匠人 发表于 2002-1-25 23:36 侃单片机 ←返回版面    

妙啊!

晓奇的方法很好!

优势是明显的:
EEPROM的空间利用率大为提升,尤为是当要保存的数据为多字节时。

固然,还有一些须要改进的地方:
一、每次读写数据时都要去找当前的活动区,未免太让CPU操劳了。
二、万一EEPROM中有一个单元的革命意志不坚决,提早退休了,那整片芯片也就完蛋了(这就是所谓的水桶效应——水桶的容量取决于最短的那块板)
三、若是每次要改写的只是个别数据,那怎么办呢?

无论怎么样,这个思路不错,若是再完善一下,必定是个好方法。

 

 zxcasd 发表于 2002-1-26 03:27 侃单片机 ←返回版面    

看来晓奇的"要死一块儿死"的办法最好了

 

 xgdzd 发表于 2002-1-27 23:32 侃单片机 ←返回版面    

晓奇的方法很好!可是……

“同时对上一次为'55'的标志字节写入'aa'”,则做为标志的字节其写入次数是数据区的2倍,恐怕要提早“壮烈牺牲”了,难以作到“要死一块儿死”。若能解决则不失为“妙法”!!!

 

 xiaohh2000 发表于 2002-1-28 10:35 侃单片机 ←返回版面    

改良

在晓奇的方法上稍作改进以下:把标志字放在最后,(顺便说一句,标志字最好分析一下系统,取一个系统不可能出现的数字,若是以为1byte不可靠,可取2byte,另外标志字最好别选A,5之类).查找标志字再写数据(覆盖标志字),而后在所写数据的结尾写标志字.这样能够避免标志字写2遍的问题.至于查找指针的问题,我以为能够这样:上电时读出写数指针放入RAM中,写了新数后更新指针.

 

 ymc8 发表于 2002-1-28 12:30 侃单片机 ←返回版面    

曾经使用过的方法

EEPROM用X25045:
不常改写的数据共30字节,写入第1~8页。
改写频繁的数据有2字节,保存在20H~1FFH中,以4字节页为单位使用,每页中前2字节做为计数器,后2字节为要保存的数据。
全部计数器第一次使用前先初始化为0FFH。读出数据时先读第一块的计数器,=0,则读下一块的计数器,非0,则直接读出。写入数据时,先读第一块的计数器,=0,则读下一块的计数器,非0,则直接写入,写入后计数器减1,若计数器=0,则同时写入下一块。最后一块写满65535次后,将全部计数器再初始化为0FFH,而后进入下一循环……
分析:
    每页中的四个字节写入次数相同,应该具备接近的寿命;
    共使用120页,理论寿命应是只用固定2个字节的120倍;
    大部分操做为读计数器,速度快,而且程序断定=0比较容易;
    空间利用率通常:50%
适用场合:系统对速度要求不高(若当前块为最后一块,则需读119次计数器);

有几台设备已写入200多万次(估算),目前仍在正常运转。

 

 

 xiaohh2000 发表于 2002-1-28 13:32 侃单片机 ←返回版面    

对不起,俺没说清楚

设定eeprom的初值0xff.第一次写完数据后,在数据后写标志字.之后的操做:先找标志字,写数时,从标志字开始日后写(必须覆盖标志字),紧接着数据写标志字,读书时,从标志字往前读.  为了防止找标志字太费功夫,能够在系统上电时找到标志字的位置,记录在RAM中,并跟踪变化.  

 

 

 程序匠人 发表于 2002-2-5 23:06 侃单片机 ←返回版面    

匠人的改进方法

小匠的这篇帖子,引发大伙一些很是深刻的讨论。小匠也从中找到了更完善的方法。不敢独吞,再次现丑了。

    首先回顾一下,我原来的方法:
    一、将93C56的00H单元定义为地址指针存放单元。
    二、将要寻址的单元地址(假设为01H)放入93C56的00H地址中。
    三、每次要对E2PROM中的数据进行读写时,先读取00H中的数据,并以读出的值为地址,访问其指向的单元。
    四、在每次写完数据后,当即将数据再读出,并与写入的地址作比较。
        A、若是相等,则表明本次写入数据成功。
        B、若是不相等,则表明本次写入数据失败。这时,将00H中的值+1,让其指向后一个新的地址单元,再将数据写入新的地址单元。


    我分析了一下,我要存入E2PROM中的数据为BCD码,而且它的规律是,每次改写都是递增的。在这种状况下,能够在我原先的方法作一些改进。
    即,每当被改写的数值递增后发生进位时,就将00H的值+1,让其指向后一个新的地址单元,再将数据写入新的地址单元。
    这里借用了晓奇的方法,——“要死一块儿死”,可是,却省下了大量标志的空间。从理论上来讲,空间利用率可接近100%了。
  
      其实,在许多场合下,对于这种频繁改写E2PROM的状况,其改写的值都是有必定规律的,要么递增,要么递减,要么有其它规律,若是对这种规律善加利用,必定可作出最佳的程序。

      上述改进方法,我已用到最近的一个案子中了,尚待验证。固然,实际的程序要更复杂一些。       各位有高见,请提出……