前言
最近很头疼,工作上遇到了,关于nand坏块,导致的一系列问题。还不清楚是硬件还是软件导致的,多方都在扯皮。索性,多了解了解nand flash相关的知识,nor flash的就先放放把。
什么是NAND FLASH
这个就一笔带过吧,知道的都知道,不知道的也不会闲着没事看如何进行坏块管理。
Nand-flash存储器是flash存储器的一种,其内部采用非线性宏单元模式。嗯 非线性。
简单理解就是硬盘,属于存储设备,虽然也叫flash但不是RAM那种断电就丢失数据的。
NAND中的存储单元
目前我的知识知道这三个暂时够了,cell什么的先放一边,不影响讨论坏块管理。
- Block 块
- Page 页
- Sector 扇区
以我最近使用的一个nand flash为例子好了,型号是:W25N02KW,牌子嘛是华邦(Winbond)
其page结构是:2048+128 (该结构由硬件决定,本次只做范例,原理都是通用的)
Nand存储单元示意图

从上图可以看到 一个flash由很多个block组成,而一个block由多个page组成。至于page则由data sector和 spare size组成。
block > page > sector > Byte
本次范例的结构是2048+128,这个表示的是一个page有2048个Byte,同时还有128Byte的Spare Size。本次讨论的坏块管理,其大部分操作的内容就是这多出来的128Byte。
Page结构示意图

上图中展示的是一个page的结构,可以看到数据区有2048Byte,并且被ECC保护,至于ECC是什么后续会介绍。除了数据区外还有128Byte的Spare Size。
其中数据区被分为4个扇区,每512Byte一个扇区。
Spare Size区,由User data和Parity area组成,具体结构看图可以知道,有哪几个字节存了什么,哪几个字节保留未使用。
NAND Flash坏块概述
Nand Flash 中,一个块中含有 1 个或多个位是坏的,就称为其为坏块 Bad Block。
坏块的稳定性是无法保证的,也就是说,不能保证你写入的数据是对的,或者写入对了,读出来也不一定对的。与此对应的正常的块,肯定是写入读出都是正常的。
坏块的分类
1、静态坏块(固有坏块)
这类坏块一般出厂时就有了,所以也叫出厂坏块(Factory Bad Block)。产生的原因是因为制造工艺的关系,会存在一定量的坏块。这类坏块是硬件类的损坏,不存在写入或者擦除亦或者修复的可能。
这类坏块一般会在出厂前就在坏块的第一个page的某处做了标记,具体需要查看相应的datasheet。
2、动态坏块(生长坏块)
这类坏块大多是在使用过程中产生的,所以也叫使用坏块(Grown Bad Block)。产生原因有很多,比如每个块都有有限的寿命,达到后会性能下降就会在读写过程中导致一些位发生变化被标记为坏块,或者由于flash周围的电压不稳定导致位反转之类的。
对于这类动态坏块,可以尝试scrub擦除来进行修复。当然如果使用达到寿命后导致了硬件上的块损坏,也是无法修复的。
坏块管理方式
ECC
全称Error Checking and Correction,NAND出错的时候一般不会造成整个Block或是Page不能读取或是全部出错,而是整个Page中只有一个或几个bit出错。ECC能纠正单比特错误和检测双比特错误,而且计算速度很快,但对1比特以上的错误无法纠正,对2比特以上的 错误不保证能检测。
ECC一般每256字节原始数据生成 3Byte ECC校验数据,这三字节共24比特分成两部分:6Byte的列校验和16Byte的行校验,多余的两个比特置1。若page也有512Byte,则对应生成6Byte ECC。
OOB
全称Out Of Band,即通常所说的spare area区。NAND中每个page后都有一个oob区域,用于存放硬件ecc校验码、坏块标记、和文件系统的组织信息,主要用于硬件纠错和坏块处理。一般page大小为512Byte的NAND 每页分配16Byte的oob。如果为2k的page,则每个page分配64字节的oob。
oob区中用1或2个Byte来标志一个block是否为坏块,如果这1或2个字节的内容是0xff,就说明这个block是好块,否则为坏块。
一般在uboo中识别坏块是通过oob区直接判断的,进入kernel会创建坏块表,相当于把各个block的第一page的oob区的坏块标记统一整理到一个表格里存放,下次直接查这个表格就可以知道具体的坏块信息,这个表格就是bbt。
BBT
全称Bad Block Table,BBT有很多种不同的处理方式,比如专门用nand做存储的,会把bbt放到block0,因为第0块一定是好块,但是如果nand本身是被用来boot,那么第0块就要存放程序,不能存放bbt了,有的把bbt放到最后一块,当然,这一块坚决不能为坏块。
U-Boot 的 NAND 坏块管理
既然谈到具体的Uboot坏块管理,选择一个具体切入点,那就是如何判定一个块是坏块。
直接从源码入手吧,我这里是Uboot2016,但是是高通给的SDK,也许有些魔改。参考即可。
源码查看是枯燥的,最好罗列一下之间的关系。我这里列了一下思维导图,仅供参考。
可以参考源码阅读下面的图。传送门:Uboot坏块查询核心源码
BBT作为一个查询表,若启用他,程序需要先建立好这个索引,并维护他,实现后续的快速查询。当然,如果选择不适用BBT,Flash芯片商也提供了相应的查询坏块方式。
当然坏块管理无外乎,查询、标记、擦除。但目前为止只提到了如何查询。
标记其实就在上面的思维导图中,可以看到BBT维护的过程中有一个函数是creat_bbt,这里就涉及到scan整个flash,判定坏块,以及标记的过程,随着scan的结束,在内存中存储好scan后的标记结果,然后通过write_bbt这个函数持久化到nand上。
而擦除,其实就是erase,当然这里面还有些道道,后续可以考虑写一下。