本文章讲nand flash的驱动开发,而在介绍驱动程序之前我想先介绍一下我所用的硬件。这样对程序的开发更为方便。本文所使用的nand flash芯片为K9F2G08U0C,下面是他的一些必要的特性:
•支持电压
- 3.3V device(K9F2G08U0C): 2.70V ~ 3.60V
• 组成
- Memory Cell Array : (256M + 8M) x 8bit
- Data Register : (2K + 64) x 8bit
• 自动编码和擦除
- Page Program : (2K + 64)Byte
- Block Erase : (128K + 4K)Byte
• Page Read Operation
- Page Size : (2K + 64)Byte
而他的示意图为:
从上图我们可以知道:
一页有:(2K+64)byte ,其中2KByte为页内存是数据区,而64byte位oob的数据存放的是数据校验码。
而一块有:64页,一个设备有2048块。
我们介绍完nand flash的存储结构就应该介绍nand flash的寻址方式了。我们要知道nand flash的寻址方式是和他的内存方式密切相关的,nand flash的数据以bit的方式保存在memory cell,一个cell中只能存储一个bit。而这些cell以8个或者16个为单位,连成bit line,形成byte(x8)/word(x16),这就是nand的数据宽度。
这些Line会再组成Page,就像上面所介绍的那样,一页有(2K+64)byte ,一块有:64页,一个设备有2048块。
而像上边介绍设备特征介绍的:该设备编程/读取是按照page为单位完成的,而擦除是按照block为单位完成。
所以通过上面的介绍我们就知道nand flash有2048 个块,每个块内有 64 页,每个页是 2K+64 Bytes。那么他是怎么找到对应位置上的数据的那?
其实他的 物理地址=块大小*块号+页大小*页号+页内地址
从上图可以看出,该FLASH的地址周期一共有5个,2个列地址(Column)周期,3个行地址(Row)周期
a)对应的列地址就是页内地址,该flash一个页的大小是2K即2048个字节,所以它的地址范围是0~2047,对应的上图的列地址A0-A10就是页内地址。你可能会发现多出了一个A11,从A0-A11,这样一共就有了12位,那它的地址范围就是0~2^12,即0~4096了,实际上,由于我们访问页内地址,可能会访问到 oob 的位置,即 2048-2111 这 64 个字节的范围内,所以,此处实际上只用到了 2048~2111,用于表示页内的 oob 区域,其大小是 64字节。
b)对应地,A12~A28,称作页号,页的号码,可以定位到具体是哪一个页,该FLASH一共是64页一共需要6位即A12~A17,而其中A18~A28表示对应的块号,即属于哪个块。
这里有一个很重要的地方就是我们要传入的地址的每一位,就是对应着上表中的 A0 到 A28 ,实际上上表中的 A11是比较特殊的,只有当我们访问页内地址处于 oob的位置,即属于 2048~2111 的时候,A11才会其效果,才会用 A0-A11用来表示对应的某个属于 2048~2111 的某个值,属于 oob 的某个位置,而我们此处的页内地址为 1208,还没有超过 2047 呢,所以 A11肯定是 0。
然后我们再来算上面我们要访问的地址,假设,我们要访问其中的第1000个块中的第 25 页中的1208字节处的地址,此时,我们就要先把具体的地址算出来:
第 1000个块中的第 25 页中的 1208字节处的地址它对应着的页内地址为:
页内地址 =1208Bytes=0x4B8
页 号 =块数*每块多少页 + 块内的页号=1000*64 + 25 =0xFA19
也就是我们要访问0xFA19页内的0x4B8地址,再把这个地址转换成列和行地址
A0~A10是用来表示页内地址的所以把0x4B8拆分成两列
列地址1=0xB8,列地址2=0x04;
再把页号0xFA19拆分成3行
行地址1=0x19,行地址2=0xFA,行地址3=0x0;
对应的看看linux2.6.35/driver/mtd/nand/nand_base.c中地址的发送
上面的column即对应着页内地址,通常情况是0,如果不是0则通过传入进来的地址除于页地址就可得到相应的列地址了。而 page_addr 即页号,就是通过要访问的地址,除于页大小,即可得到。
下面我们就要对nand flash芯片的引脚,以及如何收发数据做一些介绍了。
首先介绍一下nand flash的引脚:
I/O0 ~ I/O7 |
数据输入/输出口:这些IO口用于输入命令,地址和数据,当在读操作时输出数据 |
CLE |
命令锁存使能:CLE输入控制激活命令进入命令寄存器的通道。当为高电平时,同时在WE的上升沿信号时,命令可以锁存到命令寄存器中。 |
ALE |
地址锁存使能:ALE输入控制激活地址数据进入内部地址寄存器的通道,当ALE为高电平同时WE为上升沿信号时,地址值写入地址寄存器。 |
CE |
片选:CE是片选控制,当设备在忙的状态时,CE的高被忽略,同时,当设备在编程或者在擦除时,设备不会返回到待命状态 |
RE |
读使能:当RE下降沿时写入数据 |
WE |
写使能:上升沿时写入命令地址或者数据 |
WP |
写保护: |
R/B |
就绪/忙状态输出 |
Vcc |
电源正极 |
Vss |
电源地 |
N.C |
不接 |
而在电路图中nand flash的接法为:
介绍完引脚和电路图,我们就要介绍nand flash芯片的主要工作模式以及要在不同工作模式下所对应的命令:
从图中我们可以看出nand flash大致可以完成:收命令,收地址,收数据,发数据以及擦除。
而他们所对应的命令为:
下面我们以具体的实例进行说明:
写操作:当片选CE为低电平,而命令锁存使能CLE为高电平,而地址锁存使能ALE为低电平,WE为上升沿时写入第一个命令数据80h,然后命令锁存使能CLE为低电平,而地址锁存使能ALE为高电平,WE为每个上升沿时写入一个地址数据,一共写五个。而后命令锁存使能CLE为低电平,而地址锁存使能ALE为低电平,在每个WE的上升沿写一个数据,直到数据写完。而后命令锁存使能CLE为高电平,而地址锁存使能ALE为低电平,WE为上升沿时写入命令数据10h。
读操作:当片选CE为低电平,而命令锁存使能CLE为高电平,而地址锁存使能ALE为低电平,WE为上升沿时写入第一个命令数据00h,然后命令锁存使能CLE为低电平,而地址锁存使能ALE为高电平,WE为每个上升沿时写入一个地址数据,一共写五个。而后命令锁存使能CLE为高电平,而地址锁存使能ALE为低电平,WE为上升沿时写入命令数据30h。而后命令锁存使能CLE为低电平,而地址锁存使能ALE为低电平,在每个RE的下降沿读一个数据,直到数据读完。
上面我们介绍的是读操作和写操作的具体方式,我们可以注意到在上图中各个引脚电平的高低变化是由时间限制的。而这些引脚要在这些时间限制内完成特定的操作,而这些时间的特性在下表中:
而在读数据中有一些很重要的操作就是读ID,通过读取nand flash的ID我们可以知道该设备的生产厂家,线宽,大小等重要信息。下面就是读ID的操作方式以及各参数的意义:
说完nand flash设备,接下来我们就应该介绍一下S3C2440中的nand flash控制器以及一些重要的寄存器了。
S3C2440的启动代码可以在外部的nand flash上执行,为了支持nand flash的启动指引,S3C2440在其内部SRAM中装配了一个称为“Steppingstone”的缓冲。当启动时,nand flash上开始的4KBYTE 的数据被加载到Steppingstone中,而当启动码被加载到Steppingstone的同时启动码也被执行。
nand flash控制器框架图:
而在重启时,nand flash控制器将通过引脚状态(NCON(Adv flash), GPG13(页容量), GPG14(地址周期), GPG15(总线宽度) – refer to PIN CONFIGURATION),获得连接到的nand flash的信息。上电或者重启之后,nand flash控制器自动加载4Kbyte的启动码。之后再Steppingstone执行。
nand flash控制器同样有时间的限制,不过他只有三个:
*TACLS:发出ALE/CLE之后多长时间才发出nWE信号
*TWRPH0:nWE的脉冲宽度,HCLK*(TWRPH0+1)
*TWRPH1:nWE变为高电平后多长时间ALE/CLE能变为低电平,HCLK*(TWRPH1+1),
而下面是一些比较重要的寄存器
配置寄存器:
控制寄存器:
命令,地址,数据寄存器:
状态寄存器:
上面就是与nand有关的硬件方面的介绍,而下一篇文章我们将对nand flash驱动的框架以及程序进行分析。