Nand Flash基础知识与坏块管理机制的研究
关于nand flash的oob区与坏块
nand flash的读写操作
NAND flash读写擦除操作(读写擦cmd)
NAND FLASH学习笔记之nand flash基础(一)
NAND FLASH学习笔记之nand flash基础(二)
NAND FLASH学习笔记之nand flash基础(三)
NAND FLASH专栏
nand flash坏块管理OOB,BBT,ECC
YAFFS2垃圾回收机制完全理解(终级)
YAFFS2文件系统的垃圾回收机制
Nand-flash存储器工作原理及其操作实例(以K9F1208UOB为例)
yaffs2文件系统坏块发生记(读写代码及注释)
SSD模拟器之Flashsim
ECC之Reed-Solomon算法
当一个块上面每个chunk(是逻辑概念,相当于物理上的页概念)都是删除的数据,那么这个块就应该被擦除后重用。然而考虑到有很多块里面只有很少的有用数据的情况,很明显就不能够直接擦除或者说删除上面的数据。这种情况应该怎么处理呢?当然我们需要先把这些有用的数据copy出来放在一些可以使用的存储位置上,然后进行擦除重用。这样的一种处理方式就是垃圾回收机制。
Yaffs Fatfs对比
YAFFS适合NAND,但并不适合Win环境下面用,嵌入式用FATFS很多时候只是为了照顾到USB和SD卡的存取同时方便从电脑拷贝数据。下面两段文字的观点有待进一步确认验证YAFFS文件系统是专门针对NAND设计的文件系统,可以很方便的在OS下或前后台系统下移植,YAFFS提供了很好的坏块管理、磨损管理和ECC校验等功能,确实是一个很优秀的日志型文件系统,但是运行YAFFS需要大量的内存资源,据官方给出的数据,读写一个64M的NAND需要410kB的内存资源,如此大的内存资源开销,如何在单片机上或是内部只有几十kB的ARM平台应用呢?!显然是不可行的。FatFS文件系统是一个很精简的文件系统,占用内存资源少,但它不是针对NAND设计的,没有坏块管理,磨损管理和ECC校验等。由于项目应用需要,本人在lpc2478上移植了FatfFS-R0.07c版本的文件系统,参考网上的一篇文章,基于NAND的FatFS文件系统的转译层设计,增加了坏块管理的功能,移植后FatFS文件系统需要消耗的内存资源仅有1kB(针对K9F2808U0C而言)。
NandFlash 位反转
对应位反转的类型,Nand Flash位反转的类型和解决办法,有两种:
- 一种是nand flash物理上的数据存储的单元上的数据,是正确的,只是在读取此数据出来的数据中的某位,发生变化,出现了位反转,即读取出来的数据中,某位错了,本来是0变成1,或者本来是1变成0了。此处可以成为软件上位反转。此数据位的错误,当然可以通过一定的校验算法检测并纠正。
- 另外一种,就是nand flash中的物理存储单元中,对应的某个位,物理上发生了变化,原来是1的,变成了0,或原来是0的,变成了1,发生了物理上的位的数据变化。此处可以成为硬件上的位反转。此错误,由于是物理上发生的,虽然读取出来的数据的错误,可以通过软件或硬件去检测并纠正过来,但是物理上真正发生的位的变化,则没办法改变了。不过个人理解,好像也是可以通过擦除Erase整个数据块Block的方式去擦除此错误,不过在之后的Nand Flash的使用过程中,估计此位还是很可能继续发生同样的硬件的位反转的错误。
以上两种类型的位反转,其实对于从Nand Flash读取出来的数据来说,解决其中的错误的位的方法,都是一样的,即通过一定的校验算法,常称为ECC,去检测出来,或检测并纠正错误。
如果只是单独检测错误,那么如果发现数据有误,那么再重新读取一次即可。
实际中更多的做法是,ECC校验发现有错误,会有对应的算法去找出哪位错误并且纠正过来。ECC纠错只能纠正一位,如果位反转2位或以上,就要标记为坏块,不能继续使用了。具体见坏块管理!
其中对错误的检测和纠正,具体的实现方式,有软件算法,也有硬件实现,即硬件Nand Flash的控制器controller本身包含对应的硬件模块以实现数据的校验和纠错的。
需要对前面由于Page Program错误发现的坏块进行一下特别说明。如果在对一个块的某个page进行编程的时候发生了错误就要把这个块标记为坏块,首先就要把块里其他好的 面的内容备份到另外一个空的好块里面,然后,把这个块标记为坏块。当然,这可能会犯“错杀”之误,一个补救的办法,就是在进行完块备份之后,再将这个坏块擦除一遍,如果Block Erase发生错误,那就证明这个块是个真正的坏块,那就毫不犹豫地将它打个“戳”吧!
1.2 Nand-Flash操作(参考)
1.2.1 页读操作
在初始上电时,器件进入缺省的“读方式1模式”。在这一模式下,页读操作通过将00h指令写入指令寄存器,接着写入3个地址(1个列地址,2个行地址)来启动。一旦页读指令被器件锁存,下面的页读操作就不需要再重复写入指令了。
1.2.2 页写操作
K9F1208UOB的写入操作也以页为单位。写入必须在擦除之后,否则写入将出错。
页写入周期总共包括3个步骤:写入串行数据输入指令(80h),然后写入3个字节的地址信息,最后串行写入数据。串行写入的数据最多为528字节,它们首先被写入器件内的页寄存器,接着器件进入一个内部写入过程,将数据从页寄存器写入存储宏单元。
串行数据写入完成后,需要写入“页写入确认”指令10h,这条指令将初始化器件的内部写入操作。如果单独写入10h而没有前面的步骤,则10h不起作用。10h写入之后,K9F1208UOB的内部写控制器将自动执行内部写入和校验中必要的算法和时序,这时系统控制器就可以去做别的事了。
内部写入操作开始后,器件自动进入“读状态寄存器”模式。在这一模式下,当RE和CE为低电平时,系统可以读取状态寄存器。可以通过检测R/B的输出,或读状态寄存器的状态位(I/O 6)来判断内部写入是否结束。在器件进行内部写入操作时,只有读状态寄存器指令和复位指令会被响应。当页写入操作完成,应该检测写状态位(I/O 0)的电平。
内部写校验只对没有成功地写为0的情况进行检测。指令寄存器始终保持着读状态寄存器模式,直到其他有效的指令写入指令寄存器为止。
1.2.3 块擦除
擦除操作是以块为单位进行的。擦除的启动指令为60h,块地址的输入通过两个时钟周期完成。这时只有地址位A14到A24是有效的,A9到A13则被忽略。块地址载入之后执行擦除确认指令D0h,它用来初始化内部擦除操作。擦除确认命令还用来防止外部干扰产生擦除操作的意外情况。器件检测到擦除确认命令输入后,在WE的上升沿启动内部写控制器开始执行擦除和擦除校验。内部擦除操作完成后,检测写状态位(I/O 0),从而了解擦除操作是否有错误发生。
1.2.4 读状态寄存器
K9F1208UOB包含一个状态寄存器,该寄存器反应了写入或擦除操作是否完成,或写入和擦除操作是否无错。写入70h指令,启动读状态寄存器周期。状态寄存器的内容将在CE或RE的下降沿处送出至I/O端口。
器件一旦接收到读状态寄存器的指令,它就将保持状态寄存器在读状态,直到有其他的指令输入。因此,如果在任意读操作中采用了状态寄存器渎操作,则在连续页读的过程中,必须重发00h或50h指令。
1.2.5 读器件ID
K9F1208UOB器件具有一个产品鉴定识别码(ID),系统控制器可以读出这个ID,从而起到识别器件的作用。读ID的步骤是:写入90h指令,然后写入一个地址00h.在两个读周期下,厂商代码和器件代码将被连续输出至I/O口。
同样,一旦进入这种命令模式,器件将保持这种命令状态,直到接收到其他的指令为止。
1.2.6 复位
器件提供一个复位(RESET)指令,通过向指令寄存器写入FFh来完成对器件的复位。当器件处于任意读模式、写入或擦除模式的忙状态时,发送复位指令可以使器件中止当前的操作,正在被修改的存储器宏单元的内容不再有效,指令寄存器被清零并等待下一条指令的到来。当WP为高时,状态寄存器被清为C0h.
Yaffs2 文件系统裸机移植
YAFFS2移植指南
Get Yaffs官网
yaffs源码下载
FLASH抽象层
关于yaffs2文件系统坏块产生总结报告
前段时间一直在跟踪9000系列设备的坏块产生问题;异常设备为9000 3.0和解码器。
两类异常设备均是由于异常访问而造成大量的坏块产生。针对异常设备的Flash数据(9000 3.0)主要进行了如下分析:
1、检测坏块数据是否有出现过ECC纠正或者错误;
2、检测坏块数据中OOB区关于yaffs2参数部分是否有出现过ECC纠正或者错误;
3、检测坏块中是不是所有的页都有数据;针对异常设备搭建环境拷机(9000 3.0和解码器)主要进行如下分析:
1、检测访问yaffs2文件系统时是否出现ECC纠正或者错误(做为yaffs2坏块产生的条件,累加超过3次,回收时标记为坏块);
2、检测访问yaffs2文件系统时是否出现读mtd接口异常(不做为yaffs2坏块产生的条件);
3、检测访问yaffs2文件系统时是否出现写mtd接口异常(做为yaffs2坏块产生的条件,和ecc异常一起累加,超过3次,回收时标记为坏块);
4、检测访问yaffs2文件系统时是否出现擦除mtd接口异常(做为yaffs2坏块产生的条件,擦除失败立马标记为坏块,除非标记也失败);
5、检测访问yaffs2文件系统时第一次申请一块的一个页时是否出现写接口异常(做为yaffs2坏块产生的条件, 这个条件与条件3类似,但这个条件比较苛刻,一经出现,回收时标记为坏块,都不用累加);
注:以上需要累加的标志对于同一个块来说,所有需要累加项均会累加到一个参数上,也就是说只要ECC异常和写异常一起累加超过3次,当前块就会被垃圾回收处理时标记为坏块。Yaffs2文件系统中产生坏块的原因之一:读chunk数据时,ECC出现过纠正或者错误达到三次以上。
Yaffs2文件系统在读页操作过程中,如果出现ECC纠正或者错误(包括整个页的数据区和OOB区),当前块就会被标记为优先回收块,同时也会标识当前系统下有要优先回收的块。垃圾回收进程回收垃圾块时会检测到当前系统有优先回收的块,垃圾回收机制对于优先回收块(一般标识为优先回收的块基本上都是有异常的块)回收必须满足两个条件:一是回收块为优先回收块;另一个是该优先回收块必须是最老的脏块。但对于运行中的文件系统来说,直接出现这种条件的可能性极低,所以垃圾回收机制对于这类型的块回收时采用的是优先回收最老的脏坏;只有当当前系统中所有的比这个优先回收块老的脏块都被回收过后,这个优先回收块才能变成最老脏块,也就是达到了优先回收的最老的脏块条件,从而被回收。从这里可以看出,垃圾回收机制并不是立马回收优先回收块,因为优先回收的块基本上都是出现过ECC纠正、错误或者写访问异常的块,这样的块本身访问就有可能出现异常,回收再复用的风险相对较大,所以yaffs2文件系统虽然标识其为优先,但实际操作中只有到没有可回收的最老的脏块时才回收它。
如果一个块因三次以上的ECC纠正或者错误而被标记为坏块,那么说明当前这个块有出现过位反转,这里有两种情况:一是某些位一直位反转;二是某些位只是偶尔反转。针对第一种情况,我们可以直接检查坏块中的数据,看是不是产生过ECC纠正或者错误;针对第二种情况则无法进行有效的检测,因为我们不知道它什么时候会出现ECC异常,唯一的方法就是长时间的拷机检测。针对第一种情况,我有编写了一个检测ECC纠正与错误检测的工具,通过工具分析,9000 3.0设备所有的坏块中并没有出现任何ECC纠正与错误的情况(初步认定坏块不是由ECC异常造成);针对第二种情况,解码器拷机时并没有出现任何ECC异常的现象。Yaffs2文件系统中产生坏块的原因之二:写chunk数据时,底层接口访问异常(这种异常一般与控制器出现异常有关)。
Yaffs2文件系统在写页操作过程中,如果出现底层接口访问错误,会分成两种情况处理。
第一种情况:某一个块第一次被申请的情况。(注:这里有强调是第一次申请页,而不是当前块的第一个页被申请)
当一个块第一次被申请时,yaffs2文件系统会检测当前申请的页的数据是不是全FF(包括OOB区数据);如果检查通过,则开始写数据,当写数据调用底层接口出错时,当前块就会被标记为优先回收块,同时也会标识当前系统下有要优先回收的块,此外标识当前块的其它chunk不再被分配出去,还有一个更重要的操作,就是标识当前块为坏块;回收的原则按照优先回收块的原则回收,只是最终这个块会被标记为坏块。出现这种情况会有一个很重要的特点:这个块很大机率只会在第一个页上有数据(可以作为检测的一个方向)。对于第一次申请chunk写成功的块,后续chunk出现异常按照第二种情况处理。
第二种情况:某一个块非第一次被申请的情况。
这种情况类似于ECC异常,当一个块调用底层写接口失败后(非第一次申请),当前块就会被标记为优先回收块,同时也会标识当前系统下有要优先回收的块,此外写异常次数会累加;情况同ECC异常,当前块写异常次数累加超过3次以上,垃圾回收时最终会标记为坏块。
注意:ECC异常次数与写异常次数累加的是同一个值。
针对第一种情况,在bootloader下使用nand dump命令查看9000 3.0设备中的坏块中的数据,在1400多个块中,有少部分坏块中只有第一个页上有数据,初步认定部分坏块是由写底层接口异常造成。
针对第二种情况,解码器长时间拷机,yaffs2文件系统调用底层写接口经常出现错误调用,返回值为-5,表示IO访问出错。整个拷机过程中只有3个块是因为累积写访问次数超过三次而被标记为坏块的。
关于上面的第二种情况,为什么经常出现底层写接口错误调用,但是因这种情况产生的坏块确很少?
这是因为当某一个块出现写异常后,yaffs2文件系统会将这个块标记为优先回收,优先回收的块在没有被回收之前是不会再被使用的,这一点就减少了它的访问机会;另外,在讨论ECC异常的时候有说明,yaffs2文件系统的垃圾回收机制对于优先回收的块并不是立马回收,而是要等到所有最老脏块被回收后才回收优先回收的块;这种条件更加限定了优先回收块的访问机率;两者,如果还没有回收就出现关机(强制断电关机),那么先前的异常累积参数会被清零,必须重新开始累加。综合以上三点内容就可以很好的解释上面的问题了。对于长期运行且不会被断电的设备来说,这种情况下产生大量坏块可能性比较大。(注:ECC异常出现坏块也是同样的原理)Yaffs2文件系统中产生坏块的原因之三:垃圾回收块时的擦除操作失败。(这种异常一般也与控制器出现异常相关)。
对于Yaffs2文件系统来说,只要当前Flash上有脏数据,就可以认为有垃圾回收操作;垃圾回收基本动作就是将回收块中的有效数据搬移到申请块中,再将回收块擦除;整个过程可以说是一个先写后擦除的操作,写的是新申请块,擦除的是回收块;如果擦除时出现异常,Yaffs2文件系统会立马将回收块标记为坏块(一个伪坏块产生)。
通过解码器长时间拷机,Yaffs2文件系统调用底层擦除接口经常出现错误调用,返回值为-5,表示IO访问出错。整个拷机过程中因为擦除失败而出现了大量的坏块。对于我们的系统来说,操作Flash的地方主要有以下几个方面(写与擦除):
1、设置配置参数;
2、执行同步命令sync,主要是刷新Yaffs2文件系统的checkpt机制信息;
3、升级程序运行;
4、垃圾回收程序回收脏块;垃圾回收时,将脏块中的有效数据搬移到新申请的块中,然后再擦除脏块;这个过程中同时出现了写和擦除访问。垃圾回收可以说是前三种的总和,前三种只要是执行了,那么必定会有要进行垃圾回收的脏块。