uboot移植中对NAND Flash读数据时地址移位的疑惑
移植环境: Linux系统:Fedora9 交叉编译环境:arm-linux-gcc4.4.3 目标板:华中科技大学惠世科技S3C2440实验箱,采用SAMSUNG公司型号为K9F2G08U0B的256M*8Bit?NAND?Flash?Memory 1.?NAND?Flash的组织结构 ?NAND?Flash芯片的存储空间是按照块和页的概念来组织的。现在市面上的NAND主要按大页和小页两种存储类型来进行数据管理。以NAND型号K9F2G08U0B为例,该NAND为大页结构,即芯片每块(Block)有64页(Page),每页有2K?Byte的数据存储区和64Byte的冗余数据区(用来存放ECC校验码)。2K?Byte的数据存储区作为数据缓冲单元,用来实现I/0缓冲和存储器之间的数据传输。 ?NAND?Flash的物理层驱动主要涉及到:NAND?Flash的初始化(ID以及相关属性信息的读取)、擦除(以块作为单位),数据读写(以页作为基本单位)。在这一系列的过程中,会涉及到NAND?Flash命令的发送以及?NAND?Flash地址的发送。其中地址的发送会因NAND?Flash型号的不同而有所区别。一般来说,小页的?NAND?Flash其地址周期通常为4个:1个列地址(Column?Address)和3个行地址(Row?Address),而对大页的NAND?Flash来说,列地址至少是2个周期,行地址会因芯片的容量大小而有所区别。本文采用的三星NAND?Flash芯片是2个列地址和3个行地址(行地址就是页地址,列地址为页内地址)。对于?NAND?FLASH?来讲,地址和命令只能在I/O[7:0]上并行传递。NAND?Flash以页为单位读写数据,而以块为单位擦除数据。NAND的数据传输方式有基本的I/O传输方式,即在I/O[7:0]数据线上进行的数据传输。这种操作的缺点是系统CPU要频繁参与控制数据的传输,会影响到数据传输速度。S3C2440芯片集成了?NAND?Flash控制寄存器,大大简化了对?NAND?Flash的操作。 K9F2G08U0B?Array?Organization 2.?NAND?Flash?中的坏块(Bad?Block)? ?NAND?Flash?中,一个块中含有?1?个或多个位是坏的,就称为其为坏块?Bad?Block。坏块的稳定性是无法保证的,也就是说,不能保证你写入的数据是对的,或者写入对了,读出来也不一定对的。与此对应的正常的块,肯定是写入读出都是正常的。坏块有两种: ?(1)?出厂时就有存在的坏块: ?一种是出厂的时候,也就是,你买到的新的,还没用过的?NAND?Flash,就可以包含了坏块。此类出厂时就有的坏块,被称作?factory?(masked)?bad?block?或?initial?bad/invalid?block,在出厂之前,就会做对应的标记,标为坏块。 ?(2)?使用过程中产生的坏块: ?第二类叫做在使用过程中产生的,由于使用过程时间长了,在擦块除的时候,出错了,说明此块坏了,也要在程序运行过程中,发现,并且标记成坏块的。具体标记的位置,和上面一样。这类块叫做?worn-out?bad?block。即用坏了的块。 2.1坏块的标记 ?具体标记的地方是,对于现在常见的页大小为2K的?NAND?Flash,是块中第一个页的?oob?起始位置的第1个字节(旧的小页面,pagesize是512B至256B的?NAND?Flash,坏块标记是第?6?个字节)。如果不是?0xFF,?就说明是坏块。相对应的是,所有正常的块,好的块,里面所有数据都是?0xFF?的。不过,对于现在新出的有些?Nand?Flash,很多标记方式,有些变化,有的变成该坏块的第一个页或者第二个页,也有的是,倒数最后一个或倒数第二个页,用于标记坏块的。具体的信息,请参考对应的?Nand?Flash?的数据手册,其中会有说明。对于坏块的标记,本质上,也只是对应的?flash?上的某些字节的数据是非?0xFF?而已,所以,只要是数据,就是可以读取和写入的。也就意味着,可以写入其他值,也就把这个坏块标记信息破坏了。对于出厂时的坏块,一般是不建议将标记好的信息擦除掉的。uboot?中有个命令是“nand?scrub”就可以将块中所有的内容都擦除了,包括坏块标记,不论是出厂时的,还是后来使用过程中出现而新标记的。一般来说,不建议用这个。其实最好的做法是,用“nand?erase”只擦除好的块,对于已经标记坏块的块,不要轻易擦除掉,否则就很难区分哪些是出厂时就坏的,哪些是后来使用过程中用坏的了。 2.2坏块的管理 ?对于坏块的管理,在Linux系统中,叫做坏块管理(BBM,Bad?Block?Management),对应的会有一个表去记录好块,坏块的信息,以及坏块是出厂就有的,还是后来使用产生的,这个表叫做坏块表(BBT,Bad?Block?Table)?。在?Linux?内核?MTD?架构下的Nand?Flash驱动,和?Uboot?中?NAND?Flash?驱动中,在加载完驱动之后,如果你没有加入参数主动要求跳过坏块扫描的话,那么都会去主动扫描坏块,建立必要的?BBT?的,以备后面坏块管理所使用。K9F2G08U0B建立BBT的流程图如下所示:
2.3坏块的比例 ?而关于好块和坏块,Nand?Flash?在出厂的时候,会做出保证: ?1.关于好的,可以使用的块的数目达到一定的数目,比如三星的K9F2G08U0B,整个?Flash一共有2048个块,出厂的时候,保证好的块至少大于2008个,也就是意思是,你新买到这个型号的Nand?Flash,最坏的可能,?有?2048-2008=40个坏块。不过,事实上,现在出厂时的坏块,比较少,绝大多数,都是使用时间长了,在使用过程中出现的。 2.保证第一个块是好的,并且一般相对来说比较耐用。做此保证的主要原因是,很多?NandFlash?坏块管理方法中,就是将第一个块,用来存储上面提到的?BBT,否则,都是出错几率一样的块,那么也就不太好管理了,连放?BBT?的地方,都不好找了。一般来说,不同型号的Nand?Flash的数据手册中,也会提到自己的这个NAND?Flash,最多允许多少个坏块。 3.?移植uboot?NAND?Flash代码的疑问 参考Mini2440之U-boot使用及移植详细手册.pdf,移植NAND?Flash代码重定向时,新添加了nand_read.c源文件。摘录读取NAND?Flash读取数据函数如下: 点击(此处)折叠或打开
参照K9F2G08U0B芯片手册,发送地址的时序如下图所示: 前两个周期发送A0~A11,为列地址,即页内地址。后三个周期发送A12~A28,为行地址,即页地址。但是程序中获取页地址是把地址addr右移11位,而不是12位。开始一直很困惑。经过一番探索之后才理解了其中缘由。首先需要了解NAND?Flash页内地址的结构,它分为Main?Field(2K)和Spare?Field(64Byte)两部分,而我们的数据是存放在2K当中,普通的数据读写不对后面64Byte操作,使用A0~A10地址就可实现对2K数据存储区的寻址。下图为K9F2G08U0B页内结构: 函数nand_read_page_ll传递进来的addr地址没有包含对Sapre?Field的寻址。所以只移11位,而不是移12位。NAND?Flash读取数据是以页为单位,当NAND?Flash接收到地址后,会把该页内addr&0x7F地址之后的数据依次输出包括Spare?Field。在nand_read_page_ll函数里,列地址为0,读取此页所有数据。所以for循环读数据时,只读前2K的内容后就跳出循环。 那如何只读取Sapre?Field中的内容呢?以检查K9F2G08U0B中某一块是否是坏块为例,我们需要读取该块第一页地址为2048处的数据是否为0xFF。摘录nand_read.c源文件中检查坏块函数is_bad_block如下:
点击(此处)折叠或打开
在这里只需把列地址的值设为2048,即0x80。此时就需要用到A11来寻址了。这里只需要读取第一个字节就可以了。 小结: 这里开始无法理解的原因是不知道传递进来的地址addr不包括对Spare?Feild的寻址,只有对2K数据的寻址。检查是否是坏块,是直接给列地址赋值为0x80,并没有用到传递进来的地址参数。 附nand_read.c源码(摘自Mini2440之U-boot使用及移植详细手册.pdf): 点击(此处)折叠或打开 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |