eboot中NandFlash的应用.docx
《eboot中NandFlash的应用.docx》由会员分享,可在线阅读,更多相关《eboot中NandFlash的应用.docx(14页珍藏版)》请在冰点文库上搜索。
eboot中NandFlash的应用
Eboot中应用NandFlash
********************************LoongEmbedded********************************
作者:
LoongEmbedded(kandi)
时间:
2010.11.17
类别:
WINCEbootloader开发
********************************LoongEmbedded********************************
注:
本文nandflash是基于K9F1G08U0B
K9F1G08U0B的阵列结构图如下
图1
Nandflash存储操作特点:
以页为单位进行读写,以block为单位进行擦除
我们基于usb来download镜像的eboot来学习nandflash的应用,download的菜单一般如下所示:
图2
基于usb来download内核映像的步骤是:
F->9->U,那么我们先来看F对应的功能
1.格式化nandflash
1.1ECC校验
nandflash的每一页有两区:
main区和spare区,main区用于存储正常的数据,spare区用于存储其他附加信息,其中就包括ECC校验码。
当我们在写入数据的时候,我们就计算这一页数据的ECC校验码,然后把校验码存储到spare区的特定位置中,在下次读取这一页数据的时候,同样我们也计算ECC校验码,然后与spare区中的ECC校验码比较,如果一致则说明读取的数据正确,如果不一致则不正确。
ECC的算法较为复杂,好在s3c2440能够硬件产生ECC校验码,这样就省去了不少的麻烦事。
s3c2443即可以产生main区的ECC校验码,也可以产生spare区的ECC校验码。
因为K9F1G08U0B是8位IO口,因此s3c2443共产生4个字节的main区ECC码和2个字节的spare区ECC码。
在这里我们规定,在每一页的spare区的第0个地址到第3个地址存储main区ECC,第4个地址和第5个地址存储spare区ECC。
产生ECC校验码的过程为:
在读取或写入哪个区的数据之前,先解锁该区的ECC,以便产生该区的ECC。
在读取或写入完数据之后,再锁定该区的ECC,这样系统就会把产生的ECC码保存到相应的寄存器中。
main区的ECC保存到NFMECC0/1中(因为K9F1G08U0B是8位IO口,因此这里只用到了NFMECC0),spare区的ECC保存到NFSECC中。
对于读操作来说,我们还要继续读取spare区的相应地址内容,已得到上次写操作时所存储的main区和spare区的ECC,并把这些数据分别放入NFMECCD0/1和NFSECCD的相应位置中。
最后我们就可以通过读取NFESTAT0/1(因为K9F1G08U0B是8位IO口,因此这里只用到了NFESTAT0)中的低4位来判断读取的数据是否正确,其中第0位和第1位为main区指示错误,第2位和第3位为spare区指示错误。
1.2写sector的SectorInfo结构数据到sparefield中。
对应于代码的实现部分如下所示:
图3
下面我们来看看这部分是如何格式化nandflash的,先看结构体SectorInfo的定义:
typedefstruct_SectorInfo
{
DWORDdwReserved1;2//Reserved-usedbyFAL,为FAL保留的字节
BYTEbOEMReserved;3//ForusebyOEM,为OEM保留的字节
BYTEbBadBlock;1//IndicatesifblockisBAD,坏块标识
WORDwReserved2;4//Reserved-usedbyFAL,为FAL保留的字节
}SectorInfo,*PSectorInfo;
对这个结构体的初始化代码如下:
图4
我们知道nandflash主要以page(页)为单位进行读写,以block(块)为单位进行擦除。
每一页中又分为main区和spare区,main区用于正常数据的存储,spare区用于存储一些附加信息,如块好坏的标记、块的逻辑地址、页内数据的ECC校验和等。
K9F1G08U0B中关于一页中mainfield和sparefield的结构如下:
图5
下面接下来通过调用函数来把第0到第3个block标识为只读与保留的坏块,如下代码如下:
图6
这里主要是通过调用函数FMD_WriteSector来实现的,这个函数会调用FMD_LB_WriteSector()
主要部分如下所示:
图7
下面就来看看NAND_LB_WriteSectorInfo的函数体吧
图8
下面合适接着看NAND_LB_WriteSectorInfo函数的后部分
图9
下图是大页面的nandflash一页的结构图:
图10
下图是K9F1G08U0B编程和读状态的操作时序图
图11
1.3调用函数FMD_GetBlockStatus来获取存放eboot之后的所有的blcok的状态
该函数获得nandflash中某一个block的状态。
参数为nandflash的block地址。
由于nandflash中可能有坏块,所以针对nandflash,这个函数首先会检查当前块是否是坏块,这个一般通过读取当前block的第0个page和第1个page的带外数据。
对于小pagenandflash一般是读取第5个byte,对于大pagenandflash一般读取第0个byte,如果不为0xff表示该块是坏块。
当然,至于具体该读哪个byte,最好还是看一下所用nandflash的datasheet,确认一下,不同的厂家可能有所不同。
如果发现该块是坏块,应该返回BLOCK_STATUS_BAD。
如果不是坏块,需要读取这个块的起始扇区的扇区信息。
如果读该扇区信息出错,应该返回BLOCK_STATUS_UNKNOWN,否则,判断独到的信息,返回相应结果。
具体是如何实现的呢,我们先来看函数的调用关系:
FMD_GetBlockStatus()->FMD_LB_GetBlockStatus()->FMD_LB_ReadSector()->NAND_LB_ReadSectorInfo(),主要是通过NAND_LB_ReadSectorInfo函数来实现的,下面就来看看这个函数的内容:
图12
下图是读操作的时序图中的一部分:
图13
接着看NAND_LB_ReadSectorInfo函数的后半部分的实现:
图14
下面接着看ECC_CorrectData函数的实现
图15
下面我们回到FMD_LB_GetBlockStatus函数中来
图16
1.4擦除eboot之后的非坏块
图17
下图是判读K9F1G08U0B某一块为坏块的根据和流程图
图18
下面来看看是如何擦除块的,函数的调用关系是:
FMD_EraseBlock()->FMD_LB_EraseBlock(),在看FMD_LB_EraseBlock函数之前,先来看看K9F1G08U0B对擦除块的操作时序图
图19
擦除是以块为单位进行的,因此在写地址周期是,只需写两个行周期,在擦除结束前还要判断是否擦除操作成功,FMD_LB_EraseBlock函数体如下:
图20
到此在下载NK.bin之前的格式化动作已经完成。
2.在nandflash上建立BINFS分区,通过USB下载的NK.bin会保存在这个分区中。
代码入下图所示:
图21
这部分的内容见我的另一篇博文:
3.下载NK.bin
至于如何下载可以参考我的博文:
WINCE6.0+S3C2443的启动过程系列博文
一些概念说明:
FAL及FMD做基本定义的說明如下:
FMD(FLASHMediaDriver)可针对特定厂商的Flash作Driven、Read、Write、Erase等动作,实际上去对Flash做读写的操作。
FAL(FLASHAbstractionLayer):
FileSystem对Flash读写,必須透过此层操作。
而此层则再更加FMD所提供的Interface再对Flash做读写。
NFSECC:
Wheneverdataisreadorwritten,thespareareaECCmodulegeneratesECCparitycodeonregister
NFSECCDisforECCinthesparearea(Usually,theuserwillwritetheECCvaluegeneratedfrommaindataareatoSparearea,whichvaluewillbethesameasNFMECC0/1)andwhichisgeneratedfromthemaindataarea.
NFSECCD(nandflash的spare区ECC寄存器),NFMECCD0/1(nandflash的main区ECC寄存器),NFSECC(nandflash用于IO的ECC寄存器)。
参考链接:
坏块
s3c2440对nandflash的操作(转载)