210学习日记(7)_支持NAND

来源:互联网 发布:手机自动挂机赚钱软件 编辑:程序博客网 时间:2024/06/08 08:26

210学习日记(7)

--支持NAND

其实S5PV210NAND FLASH控制器和2440的没有多大的差别,只是S5PV210ECC校验功能更家强大了而已,而我在本章将不会用到ECC,故不做关于ECC校验相关的寄存器的介绍,在给出代码之前,我先讲讲我自己对NAND FLASH的一些理解。(建议大家先看二期视频里面NAND驱动的相关章节,关于NAND的硬件原理,讲得非常详细)

物理构成

NAND Flash的数据是以bit的方式保存在memory cell,一般来说,一个cell 中只能存储一个bit(SLC类型的NAND)。这些cell 8个或者16个为单位,连成bit line,形成所谓的byte(x8)或word(x16),这就是NAND Device的位宽。这些Line会再组成Page(NAND Flash有多种结构,以NAND FlashK9F1208为例,下面内容针对三星的K9F1208U0M),每页528Bytes(512byte(Main Area)+16byte(Spare Area)),每32page形成一个Block(32*528B)。具体一片flash上有多少个Block视需要所定。使用的三星k9f1208U0M具有4096block,故总容量为4096*32*528B=66MB,但是其中的2MB是用来保存ECC校验码等额外数据的,故实际中可使用的为64MB

NAND flash以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式可以形成所谓的三类地址:Column Address(Starting Address of the Register)列地址,地址的低8;Page Address:页地址;  Block Address:块地址;对于NAND Flash来讲,地址和命令只能在I/O[7:0]上传递,数据宽度是8位。

NAND Flash地址的表示
512byte需要9bit来表示,对于512byte系列的NAND,这512byte被分成1st half Page Register2nd half Page Register,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address(列地址),在进行擦除操作时不需要用到它,为什么?因为是以块为单位擦除;32page需要5bit来表示,占用A[13:9],即该 page在块内的相对地址。A8这一位地址被用来设置512byte1st half page还是2nd half page0表示1st1表示2nd;Block的地址是由A14以上的bit来表示。
例如64MB(512Mb)的NAND flash(实际中,由于存在spare area,故都大于这个值),共4096block,因此,需要12bit来表示,即A[25:14];如果是128MB(1Gbit)528byte/pageNAND Flash,则block addressA[26:14]表示。而page address就是blcok address | page address in block。NAND Flash的地址表示为:Block Address|Page Address in block|halfpage pointer|Column Address地址传送顺序是Column Address,Page Address,Block Address
由于地址只能在I/O[7:0]上传递,因此,必须采用移位的方式进行。例如,对于512Mbit x8NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。以发NAND_ADDR 为例
1步是传递column address,就是NAND_ADDR[7:0],不需移位即可传递到I/O[7:0]上,而halfpage pointerA8,是由操作指令决定的,即指令决定在哪个halfpage 上进行读写,因此真正的A8的值是不需程序员关心的
2步就是将NAND_ADDR右移9位,将NAND_ADDR[16:9]传到I/O[7:0]

3步将NAND_ADDR[24:17]放到I/O
4步将NAND_ADDR[25]放到I/O
因此,整个地址传递过程需要4步才能完成,即4-step addressing。如果NAND Flash的容量是32MB(256Mbit)以下,那么,block adress最高位只到bit24,因此寻址只需要3。(具体参考芯片手册)
下面,就x16NAND flash器件稍微进行一下说明。由于一个pagemain area的容量为256word,仍相当于512byte。但是,这个时候没有所谓的1st halfpage2nd halfpage之分了,所以,bit8就变得没有意义了,也就是这个时候,A8完全不用管,地址传递仍然和x8器件相同。除了这一点之外,x16NAND使用方法和x8的使用方法完全相同。

以上是读完完全手册和看完相关视频的体会,但是列举的例子仿佛有点过时了,接下来再举一个例子。以210开发板上面的1GNAND FLASG芯片K9K8G08U0A为例:

从芯片手册得知:

1).每页 = 2112Bytes(2048byte(Main Area)+64byte(Spare Area));

2).每块 = 64页;

3).一共8192块;

问:既然得知了该芯片的大小,那么列地址,页内地址,块地址应该分别是多少位呢?为什么?

答:

1).A0~A11表示列地址,因为212次方等于4K,但是硬件只有2K,所以发地址的时候,要不A11给舍弃了;

2).A12-A17是页地址,因为26次方刚好等于64

3).A18A28是块地址;

问:那么地址是怎么发送出去的呢?

答:步骤如下:

1步是传递column address,就是NAND_ADDR[7:0],不需移位即可传递到I/O[7:0]

第2步任然传的是列地址,但是由于每页只有2K,故要对地址做以下操作:

(addr>>8) & 0x7 /* 右移8位,就是为了去掉第八位的地址,因为已经在第一步发出了,与上0x7 是为了只保留A8~A10,即上文所说的舍弃A11 */

第3步就是将NAND_ADDR右移11位,将NAND_ADDR[19:12]传到I/O[7:0]

第4步将是将NAND_ADDR右移19位,将NAND_ADDR[27:20]放到I/O
第5步将是将NAND_ADDR右移27位,将NAND_ADDR[28]放到I/O

大家在看到这里后,也许还有人在纠结到底是怎么落实到NAND硬件本身的具体位置的?我只能告诉你们,不要太纠正这些了,因为这是由NAND自己来完成的,你主要安装上述的地址周期和格式将地址发出,NAND会自己去找到相应的块,页,列!!!

下面我给出NAND的初始化函数,其他的程序在我共享的代码里面能够找到,而且和2440的没多大区别,相信大家能够看懂:

void nand_init(void)

{

/* 

 * 设置时间参数(HCLK_PSYS = 667MHz/5 = 133MHz)

 * TACLS[15:12]: TACLS  = 1  1/133Mhz  = 7.5ns

 * TWRPH0[11:8]: TWRPH0 = 1  7.5ns * 2 = 15ns

 * TWRPH1 [7:4]: TWRPH1 = 1 7.5ns * 2 = 15ns

 * AddrCycle[1]: 1 = 指明地址周期为5次,这个是和2440的区别,需要注意

 */

NFCONF |= 1<<12 | 1<<8 | 1<<4;

NFCONF |= 1<<1;

/* 使能NAND控制器,关闭片选信号 */

NFCONT |= (1<<0)|(1<<1); 

/* 设置相应管脚用于Nand Flash控制器 */

MP0_3CON = 0x22222222;

/* 复位NAND Flash */

nand_reset();

return;

}

添加nand read 命令:

void run_command(int argc, char * argv[])

{

......

if (strcmp(argv[0], "nand") == 0)

nand(argc, argv);

}

然后nand()函数中会进一步判断,从而调用nand_read()等函数,我就不列出代码了,大家看我共享的代码,就明白,放在了"Tiny210学习日记_代码"目录下了,名为"6_nand"

测试:

1).使用md命令:

WY_BOOT # 

WY_BOOT # 

WY_BOOT # md 0xd0030000

do_command <md> 

D0030000: 00EACEED CE4F284F 781CF81F 395E9CDE 

D0030010: 6B7DCBCF D4F870DB 9F07E61F 53BB9C51 

2).使用nand read命令:

WY_BOOT # 

WY_BOOT # nand read 0xd0030000 0x0 1024

do_command <nand> 

sdram 0xD0030000, nand 0x00000000, size 0x00000400

nand read finished!

3).再使用md命令:

WY_BOOT # 

WY_BOOT # md 0xd0030000

do_command <md> 

D0030000: 43503553  20303131 0009D37F 20205245 

D0030010: E59FD000 EA000049 D0030000 E92D4800 

数据有变化,说明读成功。。。

注意:

由于在以后的过程中没有涉及到写nand的操作,故没有具体实现nand write命令,只是给出了框架而已,需要的,请自行添加。

注:

如有问题,请到韦东山LINUX视频讨论群里面,我们一起讨论学习,或者加我QQ317312379

原创粉丝点击