您的位置:首页 > 其它

Nand Flash驱动程序编写指南-3

2011-06-30 16:35 183 查看
下面开始分析nand flash时序图,并以读操作为例编写nand flash驱动,先看下我们应该发什么命令读数据,下面是数据手册的命令集合:



由上可以看出,要读取数据,只需要发送一个命令周期,发00h或01h。

知道了发什么命令,再来看如何发送命令,下面是读命令的时序图:



上面图的红线处,它所在的时刻就是在发送读操作的第一个周期的命令0x00之前的那一刻。看下此时红线所穿过好几行都对应什么值,以及进一步理解,为何要那个值。

(1)穿过的第一行,是CLE,即命令锁存使能的引脚,将CLE置1,就说明将要通过I/O复用端口发送进入Nand Flash的是命令,而不是地址或者其他类型的数据。只有这样将CLE置1,使其有效,才能去通知了内部硬件逻辑,你接下来将收到的是命令,内部硬件逻辑才会将受到的命令放到命令寄存器中,才能实现后面正确的操作,否则,不将CLE置1使其有效,硬件会无所适从,不知道你传入的到底是数据还是命令了。
(2)第二行,是CE#,那一刻的值是0。要发命令,就要保证CE#为低电平,使其有效,也就是片选有效。
(3)第三行是WE#,意思是写使能。因为接下来是往nand Flash里面写命令,所以,要使得WE#有效,所以设为低电平。
(4)第四行,ALE是低电平,而ALE是高电平有效,此时意思就是使其无效。而对应地,前面介绍的,使CLE有效,因为将要数据的是命令,而不是地址。如果在其他某些场合,比如接下来的要输入地址的时候,就要使其有效,而使CLE无效了。
(5)第五行,RE#,此时是高电平无效。可以看到,一直到Busy后才变成低电平有效,因为那时候就开始读取数据了。
(6)第六行,就是我们重点要介绍的,复用的输入输出I/O端口了,此刻,还没有输入数据,接下来,在不同的阶段,会输入或输出不同的数据/地址。
(7)第七行,R/B#,高电平,表示R(Ready)/就绪,因为到了后面的Busy阶段,硬件内部在第之前接受了外界的读取命令后,把该页的数据一点点送到页寄存器中,这段时间为系统正忙,所以R/B#才变成低,表示Busy忙的状态。
介绍了红线处时刻的各个信号的值,以及为何是这个值之后,后面的各个时刻所对应的不同信号的各个值也就容易理解了。
知道了读写指令的发送方式,接下来该指定读写的地址了,nand flash的硬件地址计算很简单,无偏移量,物理地址=块号*块大小+页号*页大小+页内偏移量。(注意,此处块号和页号是非零的,即从1记起的编号)这里列出了数据手册里关于地址周期的介绍:



以K9f5608为例,一共2048块,每块32页,每页512Byte+16Byte,要访问第1500块第15页的150字节处的地址,则其物理地址=1500*16K+15*512+150=0x01771e96。将其按照地址周期分配如下:

0x01771e96=0000 0001 0111 0111 0001 1110 1001 0110,分别分配到3个地址周期即为:
第1周期,A0~A7 :1001 0110 = 0x96
第2周期,A9~A16 :1000 1111 = 0x8f
第3周期,A17~A24 :1011 1011 = 0xbb
其中的L*意思为低电平,由于未用到这些为,数据手册中强制要求为0,由上面分析,我们若要访问nand上第1500块第15页的150字节处的地址,就要分3个周期分别传递0x96、0x8f和0xbb,硬件才能识别。
现在我们再返回去看时序图,有没有清晰一些?它的几个阶段是这样的:
1、操作准备阶段:此处是读(Read)操作,所以先发一个读命令的0x00,表示让硬件先准备一下,接下来的操作是读;
2、发送一个周期的列地址,也就是页内地址。表示我要从一个页的什么位置开始读取数据。
3、接下来再传入两个行地址,对应的也就是页号。
4、然后硬件开始处理所接收的数据,若有第二个命令也是在此时发送,接下来就是硬件内部自己的事情了,而我们要做的就是等待。
5、Nand Flash内部硬件逻辑负责去按照你的要求,根据传入的地址找到哪个块中的哪个页,然后把整个这一页的数据,都一点点搬运到页缓存中去。而在此期间,你所能做的事,也就只需要去读取状态寄存器,看看对应的位的值,也就是R/B#那一位,是1还是0,0的话,就表示,系统是busy,仍在”忙“(着读取数据),如果是1,就说系统已经把整个页的数据都搬运到页缓存里去了,你可以接下来读取你要的数据了。
这里需要注意的是,nand flash是整页读写的,我们传入的字节数对硬件读写是没有意义的,只是它读取整个页的数据之后,内部数据指针会定位到你刚才所制定的偏移量150所在的那个位置。
6、接下来,就是我们自己去获取数据了,通过先去Nand Flash的控制器中的数据寄存器中写入你要读取多少个字节(byte)/字(word),然后就可以去Nand Flash的控制器的FIFO中,一点点读取你要的数据了。
至此,整个Nand Flash的读操作就完成了。
对于其他操作,可以根据我上面的分析,一点点自己去看数据手册,根据里面的时序图去分析具体的操作过程,然后对照代码,会更加清楚具体是如何实现的。
看到这里,nand flash的驱动程序的编写应该就有了几分把握了吧。至于上层软件,由于我用的是实时操作系统,接口要十分简洁,就没有使用mtd层,我采用的是yaffs的direct接口,有兴趣的可以看下我的相关文章。这里再阐述下nand flash空闲区的概念,我当时在写驱动时备受它的折磨。
Nand由于最初硬件设计时候考虑到额外的错误校验等需要空间,专门对应每个页额外设计了叫做spare area的空区域,在其他地方,比如yaffs文件系统中,也叫做spare数据,里面有块/页信息,tags即校验和。
其具体用途,总结起来如下:
1、标记是否是坏快
2、存储ECC数据
3、存储一些和文件系统相关的数据,如yaffs就会用到这些空间存储一些特定信息(即上面提到的Tags,具体介绍我的相关文章有解释)
下面贴出三星nand flash小页的Spare空间分配标准:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: