页编程(写操作) Nand flash的写操作叫做编程Program,编程,一般情况下,是以页为单位的。 有的Nand Flash,比如AFND1G08U3,支持部分页编程,但是有一些限制:在同一个页内的,连续的部分页的编程,不能超过4次。一般情况下,很少使用到部分页编程,都是以页为单位进行编程操作的。 一个操作,用两个命令去实现,看起来是多余,效率不高,但是实际上,有其特殊考虑, 至少对于块擦除来说,开始的命令0x60是擦除设置命令(erase setup comman),然后传入要擦除的块地址,然后再传入擦除确认命令(erase confirm command)0xD0,以开始擦除的操作。 这种,分两步:开始设置,最后确认的命令方式,是为了避免由于外部由于无意的/未预料而产生的噪音,即使被nand flash误认为是擦除操作,但是没有之后的确认操作0xD0,nand flash就不会去擦除数据,这样使得数据更安全,不会由于噪音而误操作。 读(read)操作过程详解 以最简单的read操作为例,解释如何理解时序图,以及将时序图中的要求,转化为代码。 解释时序图之前,让我们先要搞清楚,我们要做的事情:那就是,要从nand flash的某个页里面,读取我们要的数据。 要实现此功能,会涉及到几部分的知识,至少很容易想到的就是:需要用到哪些命令,怎么发这些命令,怎么计算所需要的地址,怎么读取我们要的数据等等。 下面,就一步步的解释,需要做什么,以及如何去做: 1.需要使用何种命令 首先,是要了解,对于读取数据,要用什么命令。 下面是datasheet中的命令集合: 图5.Nand Flash AFND1G08U3的命令集合 很容易看出,我们要读取数据,要用到Read命令,该命令需要2个周期,第一个周期发0x00,第二个周期发0x30。 2.发送命令前的准备工作以及时序图各个信号的具体含义 知道了用何命令后,再去了解如何发送这些命令。 图6.Nand Flash数据读取操作的时序图 注:此图来自ATO的型号AFND1G08U3的nand flash的数据手册(datasheet)。 我们来一起看看,我在图6中的特意标注的①边上的黄色竖线。 黄色竖线所处的时刻,是在发送读操作的第一个周期的命令0x00之前的那一刻。 让我们看看,在那一刻,其所穿过好几行都对应什么值,以及进一步理解,为何要那个值。 (1)黄色竖线穿过的第一行,是CLE。还记得前面介绍命令所存使能(CLE)那个引脚吧?CLE,将CLE置1,就说明你将要通过I/O复用端口发送进入Nand Flash的,是命令,而不是地址或者其他类型的数据。只有这样将CLE置1,使其有效,才能去通知了内部硬件逻辑,你接下来将收到的是命令,内部硬件逻辑,才会将受到的命令,放到命令寄存器中,才能实现后面正确的操作,否则,不去将CLE置1使其有效,硬件会无所适从,不知道你传入的到底是数据还是命令了。 (2)而第二行,是CE#,那一刻的值是0。这个道理很简单,你既然要向Nand Flash发命令,那么先要选中它,所以,要保证CE#为低电平,使其有效,也就是片选有效。 (3)第三行是WE#,意思是写使能。因为接下来是往nand Flash里面写命令,所以,要使得WE#有效,所以设为低电平。 (4)第四行,是ALE是低电平,而ALE是高电平有效,此时意思就是使其无效。而对应地,前面介绍的,使CLE有效,因为将要数据的是命令,而不是地址。如果在其他某些场合,比如接下来的要输入地址的时候,就要使其有效,而使CLE无效了。 (5)第五行,RE#,此时是高电平,无效。可以看到,知道后面低6阶段,才变成低电平,才有效,因为那时候,要发生读取命令,去读取数据。 (6)第六行,就是我们重点要介绍的,复用的输入输出I/O端口了,此刻,还没有输入数据,接下来,在不同的阶段,会输入或输出不同的数据/地址。 (7)第七行,R/B#,高电平,表示R(Ready)/就绪,因为到了后面的第5阶段,硬件内部,在第四阶段,接受了外界的读取命令后,把该页的数据一点点送到页寄存器中,这段时间,属于系统在忙着干活,属于忙的阶段,所以,R/B#才变成低,表示Busy忙的状态的。 介绍了时刻①的各个信号的值,以及为何是这个值之后,相信,后面的各个时刻,对应的不同信号的各个值,大家就会自己慢慢分析了,也就容易理解具体的操作顺序和原理了。 3.如何计算出,我们要传入的地址 在介绍具体读取数据的详细流程之前,还要做一件事,那就是,先要搞懂我们要访问的地址,以及这些地址,如何分解后,一点点传入进去,使得硬件能识别才行。 此处还是以AFND1G08U3为例,此nand flash,一共有1024个块,每个块内有64页,每个页是2K+64 Bytes,假设,我们要访问其中的第1000个块中的第25页中的1208字节处的地址,此时,我们就要先把具体的地址算出来: 物理地址=块大小×块号+页大小×页号+页内地址=1000×(64×(2K+64))+25×(2K+64)+1208=0x80F52F8,接下来,我们就看看,怎么才能把这个实际的物理地址,转化为nand Flash所要求的格式。 在解释地址组成之前,先要来看看其datasheet中关于地址周期的介绍: 图7 Nand Flash的地址周期组成 结合图7和图5中的2,3阶段,我们可以看出,此nand flash地址周期共有5个,2个列(Column)周期,2个行(Row)周期。 而对于对应地,我们可以看出,实际上, 列地址A0~A10,就是页内地址,地址范围是从0到2047,而多出的A11,理论上可以表示2048~4095,但是实际上,我们最多也只用到了2048~2112,用于表示页内的oob区域,其大小是64字节。 A12~A27,称作页号,页的号码,可以定位到具体是哪一个页。 而其中,A18~A27,表示对应的块号,即属于哪个块。 // 可见:地址的传输顺序是是 页内地址,页号,块号。 从小到大。 简单解释完了地址组成,那么就很容易分析上面例子中的地址了: 0x80F52F8 = 1000 0000 1111 0101 0010 1111 1000,分别分配到4个地址周期就是: 1st 周期,A7~A0 :1111 1000 = 0xF8 2nd周期,A11~A8 :0000 0010 = 0x02 3rd周期,A19~A12 :1111 0101 = 0xF5 4th周期,A27~A20 :1000 0000 = 0x80 注意,与图7中对应的,*L,意思是低电平,由于未用到那些位,datasheet中强制要求设为0,所以,才有上面的2nd周期中的高4位是0000。 因此,接下来要介绍的,我们要访问第1000个块中的第25页中的1208字节处的话,所要传入的地址就是分4个周期,分别传入两个列地址的:0xF8,0x02,然后再传2个行地址的:0xF5,0x80,这样硬件才能识别。 4.读操作过程的解释 准备工作终于完了,下面就可以开始解释说明,对于读操作的,上面图中标出来的,1-6个阶段,具体是什么含义。 (1) 操作准备阶段:此处是读(Read)操作,所以,先发一个图5中读命令的第一个阶段的0x00,表示,让硬件先准备一下,接下来的操作是读。 (2) 发送两个周期的列地址。也就是页内地址,表示,我要从一个页的什么位置开始读取数据。 (3) 接下来再传入两个行地址。对应的也就是页号。 (4) 然后再发一个读操作的第二个周期的命令0x30。接下来,就是硬件内部自己的事情了。 (5) Nand Flash内部硬件逻辑,负责去按照你的要求,根据传入的地址,找到哪个块中的哪个页,然后把整个这一页的数据,都一点点搬运到页缓存中去。而在此期间,你所能做的事,也就只需要去读取状态寄存器,看看对应的位的值,也就是R/B#那一位,是1还是0,0的话就表示,系统是busy,仍在”忙“(着读取数据),如果是1,就说系统活干完了,忙清了,已经把整个页的数据都搬运到页缓存里去了,你可以接下来读取你要的数据了。 对于这里。估计有人会问了,这一个页一共2048+64字节,如果我传入的页内地址,就像上面给的1028一类的值,只是想读取1028到2011这部分数据,而不是页开始的0地址整个页的数据,那么内部硬件却读取整个页的数据出来,岂不是很浪费吗?答案是,的确很浪费,效率看起来不高,但是实际就是这么做的,而且本身读取整个页的数据,相对时间并不长,而且读出来之后,内部数据指针会定位到你刚才所制定的1208的那个位置。 (6) 接下来,就是你“窃取“系统忙了半天之后的劳动成果的时候了,呵呵。通过先去Nand Flash的控制器中的数据寄存器中写入你要读取多少个字节(byte)/字(word),然后就可以去Nand Flash的控制器的FIFO中,一点点读取你要的数据了。 至此,整个Nand Flash的读操作就完成了。 对于其他操作,可以根据我上面的分析,一点点自己去看datasheet,根据里面的时序图去分析具体的操作过程,然后对照代码,会更加清楚具体是如何实现的。 |