NAND_FLASH_内存详解与读写寻址方式

1、内存详解

NAND闪存阵列分为一系列128kB的区块(block),这些区块是 NAND器件中最小的可擦除实体。擦除一个区块就是把全部的位(bit)设置为"1"(而全部字节(byte)设置为FFh)。有必要经过编程,将已擦除 的位从"1"变为"0"。最小的编程实体是字节(byte)。一些NOR闪存能同时执行读写操做(见下图1)。虽然NAND不能同时执行读写操做,它能够采用称为"映射(shadowing)"的方法,在系统级实现这一点。这种方法在我的电脑上已经沿用多年,即将BIOS从速率较低的ROM加载到速率较高 的RAM上。html

NAND的效率较高,是由于NAND串中没有金属触点。NAND闪存单元的大小比NOR要小(4F2:10F2)的缘由,是NOR的每个单元都需 要独立的金属触点。NAND与硬盘驱动器相似,基于扇区(页),适合于存储连续的数据,如图片、音频或我的电脑数据。虽然经过把数据映射到RAM上,能在 系统级实现随机存取,可是,这样作须要额外的RAM存储空间。此外,跟硬盘同样,NAND器件存在坏的扇区,须要纠错码(ECC)来维持数据的完整性。程序员

存储单元面积越小,裸片的面积也就越小。在这种状况下,NAND就可以为当今的低成本消费市场提供存储容量更大的闪存产品。NAND闪存用于几乎全部可擦除的存储卡。NAND的复用接口为全部最新的器件和密度都提供了一种类似的引脚输出。这种引脚输出使得设计工程师无须改变电路板的硬件设计,就能从更小的密度移植到更大密度的设计上。面试

NAND与NOR闪存比较算法

NAND闪存的优势在于写(编程)和擦除操做的速率快,而NOR的优势是具备随机存取和对字节执行写(编程)操做的能力(见下图图2)。NOR的随 机存取能力支持直接代码执行(XiP),而这是嵌入式应用常常须要的一个功能。NAND的缺点是随机存取的速率慢,NOR的缺点是受到读和擦除速度慢的性 能制约。NAND较适合于存储文件。现在,愈来愈多的处理器具有直接NAND接口,并能直接从NAND(没有NOR)导入数据。编程

NAND的真正好处是编程速度快、擦除时间短。NAND支持速率超过5Mbps的持续写操做,其区块擦除时间短至2ms,而NOR是750ms。显然,NAND在某些方面具备绝对优点。然而,它不太适合于直接随机存取。缓存

对于16位的器件,NOR闪存大约须要41个I/O引脚;相对而言,NAND器件仅需24个引脚。NAND器件可以复用指令、地址和数据总线,从而 节省了引脚数量。复用接口的一项好处,就在于可以利用一样的硬件设计和电路板,支持较大的NAND器件。因为普通的TSOP-1封装已经沿用多年,该功能 让客户可以把较高密度的NAND器件移植到相同的电路板上。NAND器件的另一个好处显然是其封装选项:NAND提供一种厚膜的2Gb裸片或可以支持最 多四颗堆叠裸片,允许在相同的TSOP-1封装中堆叠一个8Gb的器件。这就使得一种封装和接口可以在未来支持较高的密度。安全

clip_image001

clip_image002

clip_image003

图2 NOR闪存的随机存取时间为0.12ms,而NAND闪存的第一字节随机存取速度要慢得多 架构

NOR闪存的随机存取时间为0.12ms,而NAND闪存的第一字节随机存取速度要慢得多app

NAND基本操做less

以2Gb NAND器件为例,它由2048个区块组成,每一个区块有64个页(见下图):

clip_image004

每个页均包含一个2048字节的数据区和64字节的空闲区,总共包含2,112字节。空闲区一般被用于ECC、耗损均衡(wear leveling)和其它软件开销功能,尽管它在物理上与其它页并无区别。NAND器件具备8或16位接口。经过8或16位宽的双向数据总线,主数据被 链接到NAND存储器。在16位模式,指令和地址仅仅利用低8位,而高8位仅仅在数据传输周期使用。

擦除区块所需时间约为2ms。一旦数据被载入寄存器,对一个页的编程大约要300μs。读一个页面须要大约25μs,其中涉及到存储阵列访问页,并将页载入16,896位寄存器中。

除了I/O总线,NAND接口由6个主要控制信号构成:

1.芯片启动(Chip Enable, CE#):若是没有检测到CE信号,那么,NAND器件就保持待机模式,不对任何控制信号做出响应。

2.写使能(Write Enable, WE#): WE#负责将数据、地址或指令写入NAND之中。

3.读使能(Read Enable, RE#): RE#容许输出数据缓冲器。

4.指令锁存使能(Command Latch Enable, CLE): 当CLE为高时,在WE#信号的上升沿,指令被锁存到NAND指令寄存器中。

5.地址锁存使能(Address Latch Enable, ALE):当ALE为高时,在WE#信号的上升沿,地址被锁存到NAND地址寄存器中。

6.就绪/忙(Ready/Busy, R/B#):若是NAND器件忙,R/B#信号将变低。该信号是漏极开路,须要采用上拉电阻。

数据每次进/出NAND寄存器都是经过16位或8位接口。当进行编程操做的时候,待编程的数据进入数据寄存器,处于在WE#信号的上升沿。在寄存器内随机存取或移动数据,要采用专用指令以便于随机存取。

数据寄存器输出数据的方式与利用RE#信号的方式相似,负责输出现有的数据,并增长到下一个地址。WE#和RE#时钟运行速度极快,达到30ns的水准。当RE#或CE#不为低的时候,输出缓冲器将为三态。这种CE#和RE#的组合使能输出缓冲器,允许NAND闪存与NOR、SRAM或DRAM等其它类型存储器共享数据总线。该功能有时被称为"无需介意芯片启动(chip enable don't care)"。这种方案的初衷是适应较老的NAND器件,它们要求CE#在整个周期为低(译注:根据上下文改写)。

clip_image006
图4 输入寄存器接收到页编程(80h)指令时,内部就会所有重置为1s,使得用户能够只输入他想以0位编程的数据字节

clip_image007
图5 带有随机数据输入的编程指令。图中加亮的扇区显示,该指令只须要后面跟随着数据的2个字节的地址

全部NAND操做 开始时,都提供一个指令周期(表1)。

clip_image008

当输出一串WE#时钟时,经过在I/O位7:0上设置指令、驱动CE#变低且CLE变高,就能够实现一个指令周期。注意:在WE#信号的上升沿上, 指令、地址或数据被锁存到NAND器件之中。如表1所示,大多数指令在第二个指令周期以后要占用若干地址周期。注意:复位或读状态指令例外,若是器件忙, 就不该该发送新的指令。
以2Gb NAND器件的寻址方案为例,第一和第二地址周期指定列地址,该列地址指定页内的起始字节表:

clip_image009

注意:由于最后一列的位置是2112,该最后位置的地址就是08h(在第二字节中)和3Fh(在第一字节中)。PA5:0指定区块内的页地 址,BA16:6指定区块的地址。虽然大多编程和读操做须要完整的5字节地址,在页内随机存取数据的操做仅仅用到第一和第二字节。块擦除操做仅仅须要三个 最高字节(第3、第四和第五字节)来选择区块。

clip_image010

clip_image011

整体而言,NAND的基本操做包括:复位(Reset, FFh)操做、读ID(Read ID, 00h)操做、读状态(Read Status, 70h)操做、编程(Program)操做、随机数据输入(Random data input, 85h)操做和读(Read)操做等。

选择内置NAND接口的处理器或控制器的好处不少。若是没有这个选择,有可能在NAND和几乎任何处理器之间设计一个"无粘接逻辑(glueless)" 接口。NAND和NOR闪存的主要区别是复用地址和数据总线。该总线被用于指定指令、地址或数据。CLE信号指定指令周期,而ALE信号指定地址周期。利 用这两个控制信号,有可能选择指令、地址或数据周期。把ALE链接处处理器的第五地址位,而把CLE链接处处理器的第四地址位,就能简单地经过改变处理器 输出的地址,任意选择指令、地址或数据。这允许CLE和ALE在合适的时间自动设置为低。

为了提供指令,处理器在数据总线上输出想要的指令,并输出地址0010h;为了输出任意数量的地址周期,处理器仅仅要依次在处理器地址0020h以后输出想要的NAND地址。注意,许多处理器能在处理器的写信号周围指定若干时序参数,这对于创建合适的时序是相当重要的。利用该技术,你没必要采用任何粘接逻辑,就能够直接从处理器存取指令、地址和数据。

多级单元

多级单元(MLC)的每个单元存储两位,而传统的SLC仅仅能存储一位。MLC技术有显著的密度优越性,然而,与SLC相比(下表),其速度或可靠性稍逊。所以,SLC被用于大多数媒体卡和无线应用,而MLC器件一般被用于消费电子和其它低成本产品。

clip_image013

如上所述,NAND须要ECC以确保数据完整性。NAND闪存的每个页面上都包括额外的存储空间,它就是64个字节的空闲区(每512字节的扇区有16字节)。该区能存储ECC代码及其它像磨损评级或逻辑到物理块映射之类的信息。ECC能在硬件或软件中执行,可是,硬件执行有明显的性能优点。在编 程操做期间,ECC单元根据扇区中存储的数据来计算误码校订代码。数据区的ECC代码而后被分别写入到各自的空闲区。当数据被读出时,ECC代码也被读 出;运用反操做能够核查读出的数据是否正确。

有可能采用ECC算法来校订数据错误。能校订的错误的数量取决于所用算法的校订强度。在硬件或软件中包含ECC,就提供了强大的系统级解决方案。最简单的硬件实现方案是采用简单的汉明(Simple Hamming)码,可是,只能校订单一位错误。瑞德索罗门(Reed-Solomon)码提供更为强大的纠错,并被目前的控制器广为采用。此外,BCH 码因为比瑞德索罗门方法的效率高,应用也日益普及。

要用软件执行NAND闪存的区块管理。该软件负责磨损评级或逻辑到物理映射。该软件还提供ECC码,若是处理器不包含ECC硬件的话。

编程或擦除操做以后,重要的是读状态寄存器,由于它确认是否成功地完成了编程或擦除操做。若是操做失败,要把该区块标记为损坏且不能再使用。之前已编写进去的数据要从损坏的区块中搬出,转移到新的(好的)存储块之中。2Gb NAND的规范规定,它能够最多有40个坏的区块,这个数字在器件的生命周期(额定寿命为10万次编程/擦除周期)内都适用。一些有坏块的NAND器件能 够出厂,主要就归根于其裸片面积大。管理器件的软件负责映射坏块并由好的存储块取而代之。

利用工厂对这些区块的标记,软件经过扫描块能够肯定区块的好坏。坏块标记被固定在空闲区的第一个位置(列地址2048)。若是在0或1页的列地址 2048上的数据是"non-FF",那么,该块要标记为坏,并映射出系统。初始化软件仅仅须要扫描全部区块肯定以肯定哪一个为坏,而后建一个坏块表供未来参考。

当心不要擦除坏块标记,这一点很重要。工厂在宽温和宽电压范围内测试了NAND;一些由工厂标记为坏的区块可能在必定的温度或电压条件下仍然能工做,可是,未来可能会失效。若是坏块信息被擦除,就没法再恢复。

2、NAND FLASH读写寻址方式

NAND Flash的寻址方式和NAND Flash的memory组织方式紧密相关。NAND Flash的数据是以bit的方式保存在memory cell,通常来讲,一个cell中只能存储一个bit。这些cell以8个或者16个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device的位宽。
这些Line会再组成Page,一般是528Byte/page或者264Word/page。而后,每32个page造成一个Block,Sizeof(block)=16kByte.
     Block是NAND Flash中最大的操做单元,擦除就是按照block为单位完成的,而
编程/读取是按照page为单位完成的。
因此,按照这样的组织方式能够造成所谓的三类地址:
     -Block   Address
     -Page    Address
     -Column Address
首先,必须清楚一点,对于NAND Flash来说,地址和命令只能在I/O[7:0]上传递,数据宽度能够是8位或者16位,可是,对于x16的NAND Device,I/O[15:8]只用于传递数据。
清楚了这一点,咱们就能够开始分析NAND Flash的寻址方式了。
以528Byte/page 总容量512Mbit+512kbyte的NAND器件为例:
由于,
     1 block=16kbyte,
     512Mbit=64Mbyte,
     Numberof(block)=1024
     1block=32page,
     1page=528byte=512byte(Main Area)+16byte(Spare Area)
用户数据保存在main area中。
     512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由所谓的pointer operation命令来选择,也就是选择了bit8的高低。所以A8就是halfpage pointer,A[7:0]就是所谓的column address。
     32个page须要5bit来表示,占用A[13:9],即该page在块内的相对地址。Block的地址是由A14以上的bit来表示,例如512Mb 的NAND,共4096block,所以,须要12个bit来表示,即A[25:14],若是是1Gbit的528byte/page的NAND Flash,共8192个block,则block address用A[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 x8的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。
以NAND_ADDR为例:
第1步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上而halfpage pointer即bit8是由操做指令决定的,即指令决定在哪一个halfpage上进行读写,而真正的bit8的值是don't care的。
第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的容量是256Mbit如下,那么,block adress最高位只到bit24,所以寻址只须要3步。


Nand Flash结构与读写分析及Nand Flash寻址方式【ZZ】

看vivi代码的head.S的时候,看到copy_myself的部分,尤为nand_read_ll函数,看不太明白,不了解nand flash原理,结合nand flash的datasheet和网上的文章,对那个函数就大概了解一点了

http://www.mcuol.com/Solution/195/21883.htm

下面的内容也是别人转载的,我继续转载http://hi.baidu.com/luyun21/blog/item/e0fa82af6de3c6c87dd92a6b.html,内容好像有点乱,我只看了一点点,对其寻址明白了一点,暂时就这样了,暂时还没须要继续研究,有须要在研究

Nand Flash结构与读写分析

NAND Flash 的数据是以bit 的方式保存在memory cell,通常来讲,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再组成Page,(Nand Flash 有多种结构,我使用的Nand Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Byte,每32 个page 造成一个Block, Sizeof(block)=16kByte 。1 block=16kbyte,512Mbit=64Mbyte,Numberof(block)=1024 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

Nand flash 以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式能够造成所谓的三类地址: --Block Address -- Page Address   --Column Address(即为页内偏移地址)

对于NAND Flash 来说,地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。

512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address。32 个page 须要5bit 来表示,占用A[13:9],即该page 在块内的相对地址。Block的地址是由A14 以上的bit 来表示,例如512Mb 的NAND,共4096block,所以,须要12 个bit 来表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,则block address用A[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 x8 的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。以NAND_ADDR 为例: 第1 步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令决定的,即指令决定在哪一个halfpage 上进行读写。而真正的bit8 的值是don\'t care 的。 第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 的容量是256Mbit 如下,那么,block adress 最高位只到bit24,所以寻址 只须要3 步。

下面,就x16 的NAND flash 器件稍微进行一下说明。因为一个page 的main area 的容量为256word,仍至关于512byte。可是,这个时候没有所谓 的1st halfpage 和2nd halfpage 之分了,因此,bit8就变得没有意义了,也就是这个时候 bit8 彻底不用管,地址传递仍然和x8 器件相同。除了,这一点以外,x16 的NAND使用方法和 x8 的使用方法彻底相同。

norflash和nandflash的区别
norflash中能够运行程序,nandflash不能够
Nor flash按sector可擦除,按bit可读写。Nand Flash按Block可擦除,按Page可读写。
最主要是寻址方式不一样

*********************************************************************************************************************************

Nand Flash 寻址方式

NAND Flash的寻址方式和NAND Flash的memory组织方式紧密相关。NAND Flash的数据是以bit的方式保存在memory cell,通常来讲,一个cell中只能存储一个bit。这些cell以8个或者16个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device的位宽。
这些Line会再组成Page,一般是528Byte/page或者264Word/page。而后,每32个page造成一个Block,Sizeof(block)=16kByte.
     Block是NAND Flash中最大的操做单元,擦除就是按照block为单位完成的,而
编程/读取是按照page为单位完成的。

因此,按照这样的组织方式能够造成所谓的三类地址:
     -Block   Address
     -Page    Address
     -Column Address

首先,必须清楚一点,对于NAND Flash来说,地址和命令只能在I/O[7:0]上传递,数据宽度能够是8位或者16位,可是,对于x16的NAND Device,I/O[15:8]只用于传递数据。

清楚了这一点,咱们就能够开始分析NAND Flash的寻址方式了。

以528Byte/page 总容量512Mbit+512kbyte的NAND器件为例:
由于,
     1 block=16kbyte,
     512Mbit=64Mbyte,
     Numberof(block)=1024
     1block=32page,
     1page=528byte=512byte(Main Area)+16byte(Spare Area)
用户数据保存在main area中。

     512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由所谓的pointer operation命令来选择,也就是选择了bit8的高低。所以A8就是halfpage pointer,A[7:0]就是所谓的column address。
     32个page须要5bit来表示,占用A[13:9],即该page在块内的相对地址。Block的地址是由A14以上的bit来表示,例如512Mb 的NAND,共4096block,所以,须要12个bit来表示,即A[25:14],若是是1Gbit的528byte/page的NAND Flash,共8192个block,则block address用A[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 x8的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。

以NAND_ADDR为例:
第1步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上而halfpage pointer即bit8是由操做指令决定的,即指令决定在哪一个halfpage上进行读写,而真正的bit8的值是don't care的。
第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的容量是256Mbit如下,那么,block adress最高位只到bit24,所以寻址只须要3步。


NAND Flash Architecture

Architecture
NAND Flash是由4096個Blocks所組成的,每個Block是由128個Pages所組成的,而每個Page是由4KBytes的User Data加上128Bytes的Spare Data所構成的,故每個Block的容量為528Kbytes,每個Page的容量為4224Bytes。其中,Spare Data主要是用來存放ECC(Error Correcting Code)、Bad Block Information和File System的資料。

Figure 1.Flash Memory Geometry
NAND Flash的操做特點為:抹除(Erase)的最小單位是Block,而讀取(Read)和寫入(Write)則是以Page為單位。因NAND Flash的每個bit只能由1變為0,而不能從0變為1,因此對Flash作寫入時必定要將其對應的Block先抹除掉,才能作寫入的動做,也所以同樣 一個page只能夠寫入一次。

Constraints and Functionalities

Constraints

Sequential Page program
在一個Block裡,Page必須從LSB(least significant bit) Page依序寫到MSB(most significant bit) Page,隨意不照Page address來寫入是禁止的。另外,LSB是寫入的Pages中最小的位址,不必定是Page 0。

Figure 2.Sequential Page program [1]

Partial Page program
在NAND Flash中,存取資料的最小單位是Page。在SLC Flash中,若想修改Page中的Data時能够更改部分的Bit而不须要將整個Page抹除後才更改。例如Page中的Data為1001011101,若想將Data改为1001010001,只需將其中的2個Bit更改為0便可,不用抹除後寫入。但之後的MLC Flash,已經不允許此功能了。

Performance-Improving Commands

Copy Back Program
Copy Back Program能够快速地將1頁的資料複製(Copy)到另1個指定的頁中,也對於垃圾收集(Garbage Collection)很是的有用。例如當1頁裡的資料壞掉形成整個區塊(Block)為損壞區塊(Bad Block, or Worn-Out Block)時,Copy Back Program能够有效率地將全部有效頁(Valid Page)的資料複製到指定的區塊中。

Copy Back Program是將1整頁的資料(來源Page)讀取且複製到內部頁緩衝器(Internal Page Buffer)中,再將它寫到另1整頁中(目標Page)。因為它不像通常的讀取、寫入指令將資料存取到外部記憶體(Memory),而是將資料存在內部頁緩衝器中,因此會比通常的讀取加上寫入少了將資料讀寫到外部記憶體的時間,執行上也更快且更有效率。

Figure 3.Copy Back Program [1]

Random data input/output
當對Page的資料作讀寫時,必須將1整頁的全部資料都存在於外部記憶體中,當外部的RAM不夠大時,無法一次存放整個頁的資料,故利用NAND Flash的Internal Page Buffer來存放整個頁的資料,並使用Random Data Input/Output就能够對頁中任意位址的資料作存取。

對1頁裡的資料作通常的讀寫時,資料都是Sequential的,但若想要隨意存取1頁裡的資料,如想要存取ECC的資料,即可使用Random data input/output跳至User Data的尾端去存取ECC的資料。

-Plane program
NAND Flash Vendor將Memory Array分红2個Plane,能够同時對2個不一样Block addresses作Read/Write/Erase的操做。

Figure 4.2-Plane Program [6]

NAND-flash Management Issues

Address Translation
NAND Flash Memory的同1個page不能作重覆寫入的行為。再者,在寫入1個sector資料以前,必須要有抹除1個Block的資料才能作寫入的動做,但抹除 1個Block的動做须要耗費相當多的時間,此舉形成了NAND Flash效能降低的最大缘由。為了改善效能,最有效的方法就是減少Erase的次數,所以有了Mapping Table。

Mapping Table的管理分為Block level、Sector level以及改良的Hybrid level。

Block level的address mapping是指1個Logical Block對應到1個Physical Block,它的mapping table相對於sector-level的mapping table來的小,能夠節省mapping table所占RAM的使用量。但當Logical Block的個數少於Physical Block個數時,會發生Logical Block時常被overwrite的狀況,選定要overwrite的Logical block和它mapping的Physical Block都要將資料更新到新的Physical Block上,且作erase-before-write的動做,而形成效能的降低,此外轉換單位大,每次寫入的單位也大,所以會帶來額外的資料寫入成本。

而Sector-Level的address mapping是1個Logical Sector能够對應到任1個Physical Block裡的Sector,雖然這種mapping的方式彈性佳,能够減少因轉換單位大而帶來額外的資料寫入成本,可是mapping table的Size過大,例如1GB的Flash,1個sector的大小為512byte的話,RAM就要維護二百萬筆的sector資訊。

Figure 5. 資料區塊,紀錄區塊,以及備用區塊的使用。

(a)完整的資料區塊(b)資料依序寫入紀錄區塊的可寫頁中(c)區塊鏈的Merge

改良的Hybrid level,擷取Block level和Sector level的優點,採用Block level的方式,再加上有限數量的Block作為Sector level的mapping,除了讓mapping table的size限制住不至於龐大,也減少了erase-before-write的動做。Hybrid level中,將Physical Block取名為資料區塊(Data Block),因為資料不能直接更新於資料區塊裡,我們找了一段可寫的Block來紀錄更新的資料,並將它取名為紀錄區塊(Log Block)。經過一段時間的寫入,一個LBA(Logical Block Address)對應會對應一個資料區塊,而此資料區塊會跟著數個紀錄區塊,整個造成一個區塊鏈(Block Chain),如圖5(b)所示。

Figure 6.Hybrid Level mapping table [7]

Hybrid Level在作write的時候,在寫第一、2筆資料時(sector 4,5),會由block level的mapping table找出Data Block 10,因為對應sector裡內容是空的,所以就直接寫入Data Block 10裡。而寫第3筆資料時(sector 4),由Block level的mapping table找到Data Block 10,但裡面已有寫入的資料,故改由sector level的mapping table找尋空的Log Block,寫入第3筆資料。在寫第4筆資料時(sector 4),因為sector level的mapping table裡已有mapped的Log Block,故將第4筆資料依序寫入對映的Log Block裡。

而在讀取時,會先由Sector level的mapping table裡,找出最新的資料,而Log Block裡沒有的資料,則由Block Level mapping table裡找到的Data Block裡。

Garbage Collection
主要是用於將没必要要存在且浪費空間的Block作回收,來增长可用的Block數。當须要新 的Log Block時,會從已經使用的Log Block裡選取符合回收條件的Block來作Garbage Collection,如free sector低於threshold值。

被選定要回收的Log Block,會和它的Data Block作merge的動做,意即選取新的Data Block,將Log Block中sector資料copy到此新的Data Block中,再將原先Data Block中剩餘的sector資料複製到此新的Data Block中。

更新block-level table對應到新的Data Block,並將sector-level table裡將剛才回收的Log Block移除。原先的Log Block和Data Block作抹除的動做,即完成Garbage Collection了。

例如Figure 4中,要將Log block(pbn=20)作回收時,會將此log block中最新的資料(sector 4)複製到新的Data Block中(假設為pbn=12),再將它的Data block(pbn=10)中,其餘的資料(sector 5)複製到新的Data Block(pbn=12)中。並將block level table中對應到pbn=20的資料改為對應到pbn=12,即新的data block,再將sector level table中pbn=20(回收的log block)這筆資料刪除。最後將pbn=20,pbn=10舊的block作抹除的動做便可。

Merge在一種特殊情況下,能够作switch的動做,例如像Figure 4中,Log Block(pbn=30)裡是照sector的順序寫入,所以它的Data Block(pbn=11)裡的資料都是不须要使用的舊資料,要作Garbage Collection,只须要將Log Block和Data Block對調便可,即block-level table裡對應到pbn=11這筆資料改為對應到pbn=30,而sector-level table裡對應到pbn=30這筆刪除,然後將舊的Data Block(pbn=11)抹除就達到Garbage Collection了。

Figure 7.Garbage Collection Operation [3]

當在作Garbage Collection時,會但愿用最少的cleaning work來獲得最多的free space,所以會選擇最多garbage的segment來作回收。另外,將資料的型態分為靜態和動態的資料。其中,Read-only data屬於靜態資料,即一旦創造就不會去修改它,而動態資料是會被修改的。動態資料依其資料修改頻率分為cold data(較少修改的資料)和hot data(修改頻繁的資料)。

依不一样的資料型態,作資料搬移時的方式也分為三種:

Read-only Data mix with dynamic data
當要被回收的segment中有read-only data時,會先將全部的read-only data搬到新的segment裡。若此新的segment又會被回收時,以前搬移過的read-only data仍然會再被搬移一次。另外,當一個segment中的資料都為read-only data時,則此segment永遠不會被回收的。

Figure 8.Repeatedly migrating read-only data when they are mixed with dynamic data [9]

Cold data mix with hot data
當要被回收的segment中有cold data和hot data時,因cold data更改的頻率較少,在cleaning的期間cold data有較高的可能性為valid的,所以會將cold data搬移到新的segment裡。

Figure 9.Migrating cold data when they are mixed with hot data [9]

Data have high locality of reference
當要被回收segment中的data是有高度被參考性的,這些hot data在cleaning的過程中仍多是valid,但在被搬移到新的segment時,hot data又被更新一次而成為garbage,這類的搬移即稱為useless migration。

Figure 10.Useless migration when hot data are updated soon after being migrated [9]

Wear-Leveling
當在使用Flash時,常會對某個檔案作修改的動做,當此時檔案變動而要用到更多的Page且 Flash中仍有空的Block時,會將空的 Block配置給此檔案來使用,若Flash中已經沒有空的Block時,則會執行Garbage Collection來清出空的Block以供使用。在挑選空的Block或執行Garbage Collection清出空的Block時,可能會形成部分的Block時常被挑選,這些Block可能因為被過度使用而形成損毀。為了避免這種情況發生,會使用Wear-Leveling,讓大部分Block的存取次數平均,而不會经常挑選到某些固定的Block上,形成Block的過度存取而損毀。

再者,NAND Flash抹除和寫入的reliability有使用的次數(100,000次),使用wear-leveling能够紀錄並平均每個block被使用的次數。

Wear-Leveling有兩種方式來實現,一種是在FileSystem和NAND Flash中間的FTL(Flash Translation Layer)裡實現的。FTL能够讓上層的OS透過FTL以disk的方式去讀寫下層的NAND Flash,另外也提供了virtual address和physical address的轉換。

Figure 11. Wear Leveling in the FTL [4]

另外一種的實現方法為Wear Leveling直接在FileSystem裡實現,OS直接透過HAL和NAND Flash溝通。

Figure 12.Wear Leveling in the File System [4]

Flow Chart

Read
Figure 13 Read Operation Flow Chart

Erase
Figure 14 Erase Operation Flow Chart

Write
Figure 15 Write Operation Flow Chart

Timing/Power

Timing

Read Operation
BandWidth:39.82MB/s

Write Operation
BandWidth:4.66MB/s~1.36MB/s

Erase Operation

Power
P(typ)=3.3V*15mA=49.5mW
P(max)=3.6V*30mA=108mW

Read Operation
E(typ)=49.5mW*(195+180+4224*25+100)ns=49.5mW*106075ns

=

J

E(max)=108mW*(195+180+4224*25+100)ns=108mW*106075ns

=

J

Write Operation
E(typ)=49.5mW*(295+4224*25+100+

+200)ns

=49.5mW*906195ns

=

J

      E(max)=108mW*(295+4224*25+100+
+200)ns

=108mW*3106195ns

=

J

Erase Operation
E(typ)=49.5mW*(245+

+200)ns=49.5mW*1500445ns

=

J

E(max)=108mW*(245+

+200)ns=108mW*10000445ns

=

J

Reference
Samsung Electronics, "K9GAG08UXM Specification"
Alex Kuo, "Application Note: Partial Page Program MirrorBit ORNAND with NAND interface", Spansion
STMicroelectronics, "AN1821 Garbage Collection in Single Level Cell NAND Flash memories"
STMicroelectronics, "AN1822 Wear Leveling in Single Level Cell NAND Flash memories"
STMicroelectronics, "AN1728 How to use the Copy Back feature of ST Small Page NAND Flash memories"
Amber Huffman, ONFI Technical Chair, "Flash Performance Enhancements through ONFI", Intel Corporation
S.-W. Lee, D.-J. Park, T.-S. Chung, D.-H. Lee, S.-W. Park, H.-J. Song, "A Log Buffer-Based Flash Translation Layer Using Fully-Associative Sector Translation", ACM Transactions on Embedded Computing Systems, Vol.6,No.3,Article 18,Publication date: July 2007
STMicroelectronics, "AN1820 How to use the FTL and HAL Software Modules to Manage Data in Single Level Cell NAND Flash Memories"
Mei-Ling Chiang, Paul C. H. Lee, Ruei-Chuan Chang, "Cleaning Policies in Mobile Computers Using Flash Memory", Journal of Systems and Software, v.48 n.3, p.213-231, Nov. 1, 1999

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/renpine/archive/2009/09/19/4570538.aspx


为何Micron的NAND Flash能达到200MB/s的读取速度

今天看到新闻Intel, Micron claim world’s fastest NAND flash,就直接到Micron的网站上浏览了一下。Micron的新产品分类为High Speed NAND Flash Products,用“High Speed”与原有NAND产品系列区分(估计ONFI 3.0兼容的产品出来后,还要加上“Ultra”,才能再分出一个类别来)。 riple
      Micron的High Speed系列目前按照容量分为8Gb、16Gb、32Gb三种,按照接口个数分为单端口(8Gb)和双端口(1六、32Gb)两种。在Micron的网站上还看不到详细的datasheet,只能看到一个Product BriefFlyerriple
经过Product Brief能够获得8Gb芯片的以下信息:采用了50nm而不是72nm工艺生产;是SLC而不是MLC结构;BGA封装取代了TSOP封 装;4096Byte/Page,128Page/Block,512Block x 1/Plane,4Planes;I/O分为异步和同步(DDR)两种模式;速度最高的同步传输模式,读写I/O时间都是6ns/Toggle;读 Array 30us/Page,写Array 160us/Page,擦Array 3ms/Block。 riple
从上面的信息能够看出,High Speed特性要归功于6ns/Toggle的I/O时间,对于8bit的接口来讲,至关于166MB/s的传输速度。 riple
可是,NAND Flash的访问速度不只仅取决于I/O速度,还和Array传输时间、芯片内部缓冲结构和Plane数量有关。 riple

clip_image014

〇、NAND Flash访问时间分析 riple

访问操做 =  命令输入 + I/O操做 + Array传输操做,第一项的操做时间所占比例很小,在性能估算中能够忽略。 riple
访问时间 = I/O时间 + Array传输时间,在上一代NAND Flash中,第一项占的比例最大,是第二项的4-5倍。 riple

      Micron主要采用了以下的4种技术缩短了平均的访问时间。其中第一种技术是第一次在NAND Flash上应用,也是此次“大提速”的核心技术。正是这项技术的采用,使上述公式中的第一项缩小到上一代的1/5,才使得其余3项技术发挥了最佳的效果。 riple

1、接口传输模式对I/O速度的影响 riple

采用ONFi 2.0提出的DDR接口,提升了I/O数据传输速率:源同步(缩小了创建保持时间要求)、双边沿触发(加倍了数据传输速率)。 riple

2、Block结构和生产工艺对Array传输速度的影响 riple

与上一代NAND Flash相比,Page容量加倍,在Array传输时间基本不变的状况下,等效地加倍了Array传输速度。 riple
      72nm到50nm的工艺改进,缩小了芯片面积,提升了芯片速度(读Array速度提高不明显,写Array速度提高了1倍),下降了功耗。 riple

3、缓冲与缓存对速度的影响 riple

      Micron的NAND Flash的一大特色是:每个Plane对应一个Page大小的缓冲(data register)和一个Page大小的缓存(cache register)。数据写入的顺序是:I/O -> cache register -> data register -> Plane,数据读出的顺序恰好相反。缓冲(data register)与缓存(cache register)之间的数据传输速度很快,data register能够把I/O操做和Array操做分隔开,造成I/O操做和Array操做的“两级流水线”。这种结构与上一代NAND Flash同样。(其实,4个Plane对应4个data register和1个cache register便可) riple

4、多Plane操做对速度的影响 riple

      4个Plane对应4组缓冲与缓存,每一组能够分别操做。2个Plane交替操做,能够实现“乒乓操做”,达到2倍的Array访问带宽。4个Plane 交替操做,能够实现“乒乒乓乓操做”,达到4倍的Array访问带宽。在上一代的NAND Flash芯片中,采用2Plane结构是比较常见的。 riple

clip_image001[1]

5、200MB/s的读速度和100MB/s的写速度是怎样获得的 riple

读I/O时间:1Toggle/Byte x 6ns/Toggle x 4096Byte/Page = 24.6us/Page,与读Array时间30us/Page近似。在采用cache模式的读操做下,两级流水线的速度取决于“I/O速度”和“读 Array速度”中较慢的一个,不采用多Plane操做,平均速度只能达到读Array速度,即4096Byte/30us =136MB/s;在2Plane模式下,读Array时间缩短至15us/Page,小于读I/O时间24.6us/Page,两级流水线的速度取决于 “I/O速度”,平均速度达到I/O速度4096Byte/24.6us = 166MB/s,这与宣传中200MB/s的速度还有些差距。咱们采用的I/O周期值是数据手册给出的,芯片实际可以运行的I/O速度每每要略高一些:在上面的分析中,只要I/O周期缩短至5ns/Toggle,“超频”后的读I/O时间就缩短至20us/Page,大于读Array时间15us /Page,两级流水线的速度仍然取决于“I/O速度”,这样一来平均读取速度就能达到4096Byte/20us =200MB/s。(从上面的分析看,若是不对I/O速度进行“超频”,平均读取速度是达不到200MB/s的,看来宣传仍是略有夸张的) riple
写I/O时间:1Toggle/Byte x 6ns/Toggle x 4096Byte/Page = 24.6us/Page,与写Array时间160us/Page相差不少,单独采用cache模式不够,还要采用4Plane的“乒乒乓乓操做”,缩短 写Array时间,尽可能均衡流水线的两级操做时间。4Plane模式平均Array写操做时间为一次Array写操做时间的1/4,40us/Page。因此在cache模式配合4Plane模式的写操做下,流水线的速度等于流水线两级中最慢的“平均Array写速度”,能够近似为:4096Byte/40us = 102MB/s。 riple

从上面的分析能够看出,I/O速度限制了读取速度的最大值,在ONFi 3.0预计的400MB/s的I/O速度实现后,NAND Flash的平均读取速度也可以达到400MB/s(这回就要采用4Plane模式了);Array传输速度限制了写入速度的最大值,若是不对芯片的内部 结构和生产工艺进行改进的话,NAND Flash的平均写入速度很难进一步提升。 riple


nand flash 总结

flash 2009-12-09 13:21:37 阅读118 评论0 字号:大中小 订阅

NAND Flash产品能够分为三大架构,分别是Single Level Cell;SLC,包括三星电子、Hynix、Micron以及东芝都是此技术使用者,第二种则是Multi Level Cell;MLC,目前有东芝、Renesas使用,不过三星电子将在2005第四季推出相关产品,最后则是Infineon与Saifun Semiconductors合资利用NROM技术所共同开发的Multi Bit Cell;MBC。

MLC是Intel在1997年9月最早开发成功的,其做用是将两个位的信息存入一个 Floating Gate(NADA Flash存储单元中存放电荷的部分),而后利用不一样Level的电荷,透过内存储存格的电压控制精准读写,假设以4种电压控制、1个晶体管可存取2 bits 的数据,如果控制8种电压就能够存取3 bits 的数据,使Flash 的容量大幅提高,相似Rambus的QRSL技术,经过精确控制浮动栅上的电荷数量,使其呈现出4种不一样的存储状态,每种状态表明两个二进制数值(从00 到11)。

固然不光是NOR型NAND Flash在使用,东芝在2003年2月推出第一款MLC型的NAND Flash,并接续2004年4月推出采用MLC技术的4Gbit与8Gbit NAND Flash,显然这对于原本就以容量见长的NAND Flash更是如虎添翼。根据Semiconductor Insights研究,东芝利用90nm MLC技术所开发出来的4Gb,其die面积为144 mm2。

至于SLC技术与EEPROM相同,但在Floating gate与Source gate之中的氧化薄膜更薄,其数据的写入是透过对浮置闸极的电荷加电压,而后能够透过源极,便可将所储存的电荷消除,藉由这样的方式,即可储存1个个信 息位,这种技术的单一位细胞方式能提供快速的程序编程与读取,不过此技术受限于Silicon efficiency的问题,必需要藉由较先进的流程强化技术Process enhancements,才能向上提高SLC制程技术。

将上述所言,作一个比较,SLC架构是0和1两个充电值,而MLC架构能够一次储存4个以上的充电值,所以MLC架构能够有比较好的储存密度,再加上可利用比较老旧的生产设备来提升产品的容量,而无须额外投资生产设备,能够享有成本与良率的优点。

不过MLC架构有着让使用者很难容忍的缺点,就是使用寿命较短,其次MLC架构只能承受约1 万次的存取,远低于SLC架构的10万次。至于存取速度,SLC架构比MLC架构要快速三倍以上,加上MLC架构对于电力的消耗较多,所以使用者如果考虑长久使用、安全储存数据以及高速的存取速度等要求,恐怕会改采用SLC架构。

其实在NAND Flash市场中,若以理论数据比较,Renesas的AG-AND技术或是Infineon的MBC技术,其实并不逊于三星电子、东芝或是其它业者,甚 至于有过之而无不及,不过这两家业者由于产能、技术开发等问题形成延迟扩大市场占有率时机,这也印证商场中的一句话,任何东西都必需要可以适时适地推出,不然只是将市场拱手让给对方。

Nand Flash结构与读写分析

NAND Flash 的数据是以bit 的方式保存在memory cell,通常来讲,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再组成Page,(Nand Flash 有多种结构,我使用的Nand Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Byte,每32 个page 造成一个Block, Sizeof(block)=16kByte 。1 block=16kbyte,512Mbit=64Mbyte,Numberof(block)=1024 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

Nand flash 以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式能够造成所谓的三类地址: --Block Address -- Page Address   --Column Address(即为页内偏移地址)

对于NAND Flash 来说,地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。

512byte须要9bit来表示,对于528byte系列的NAND,这512byte被 分红1st half和2nd half,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address。32 个page 须要5bit 来表示,占用A[13:9],即该page 在块内的相对地址。Block的地址是由A14 以上的bit 来表示,例如512Mb 的NAND,共4096block,所以,须要12 个bit 来表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,则block address用A[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 x8 的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。以NAND_ADDR 为例: 第1 步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令决定的,即指令决定在哪一个halfpage 上进行读写。而真正的bit8 的值是don\'t care 的。 第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 的容量是256Mbit 如下,那么,block adress 最高位只到bit24,所以寻址 只须要3 步。

下面,就x16 的NAND flash 器件稍微进行一下说明。 因为一个page 的main area 的容量为256word,仍至关于512byte。可是,这个时候没有所谓 的1st halfpage 和2nd halfpage 之分了,因此,bit8就变得没有意义了,也就是这个时候 bit8 彻底不用管,地址传递仍然和x8 器件相同。除了,这一点以外,x16 的NAND使用方法和 x8 的使用方法彻底相同。

norflash和nandflash的区别

norflash中能够运行程序,nandflash不能够

Nor flash按sector可擦除,按bit可读写。Nand Flash按Block可擦除,按Page可读写。

最主要是寻址方式不一样

*********************************************************************************************************************************

Nand Flash 寻址方式

NAND Flash的寻址方式和NAND Flash的memory组织方式紧密相关。NAND Flash的数据是以bit的方式保存在memory cell,通常来讲,一个cell中只能存储一个bit。这些cell以8个或者16个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device的位宽。

这些Line会再组成Page,一般是528Byte/page或者264Word/page。而后,每32个page造成一个Block,Sizeof(block)=16kByte.

     Block是NAND Flash中最大的操做单元,擦除就是按照block为单位完成的,而

编程/读取是按照page为单位完成的。

因此,按照这样的组织方式能够造成所谓的三类地址:

     -Block   Address

     -Page    Address

     -Column Address

首先,必须清楚一点,对于NAND Flash来说,地址和命令只能在I/O[7:0]上传递,数据宽度能够是8位或者16位,可是,对于x16的NAND Device,I/O[15:8]只用于传递数据。

清楚了这一点,咱们就能够开始分析NAND Flash的寻址方式了。

以528Byte/page 总容量512Mbit+512kbyte的NAND器件为例:

由于,

     1 block=16kbyte,

     512Mbit=64Mbyte,

     Numberof(block)=1024

     1block=32page,

     1page=528byte=512byte(Main Area)+16byte(Spare Area)

用户数据保存在main area中。

     512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由所谓的pointer operation命令来选择,也就是选择了bit8的高低。所以A8就是halfpage pointer,A[7:0]就是所谓的column address。

     32个page须要5bit来表示,占用A[13:9],即该page在块内的相对地址。Block的地址是由A14以上的bit来表示,例如512Mb 的NAND,共4096block,所以,须要12个bit来表示,即A[25:14],若是是1Gbit的528byte/page的NAND Flash,共8192个block,则block address用A[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 x8的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。

以NAND_ADDR为例:

第1步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上而halfpage pointer即bit8是由操做指令决定的,即指令决定在哪一个halfpage上进行读写,而真正的bit8的值是don't care的。

第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的容量是256Mbit如下,那么,block adress最高位只到bit24,所以寻址只须要3步。

NAND Flash 的数据是以bit 的方式保存在memory cell,通常来讲,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再组成Page.

(Nand Flash 有多种结构,下面内容针对三星的K9F1208U0M),每页528Byte,每32 个page 造成一个Block, Sizeof(block)=16kByte 。

1 block="16kbyte",

512Mbit=64Mbyte,

Numberof(block)=4096 1block=32page,

1page=528byte=512byte(Main Area)+16byte(Spare Area) ;

Nand flash 以页为单位读写数据,而以块为单位擦除数据。

按照这样的组织方式能够造成所谓的三类地址:

--Block Address

-- Page Address

--Column Address

对于NAND Flash 来说,地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。

512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address。

32 个page 须要5bit 来表示,占用A[13:9],即该page 在块内的相对地址。Block的地址是由A14 以上的bit 来表示,例如512Mb 的NAND,共4096block,所以,须要12 个bit 来表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,则block address用A[26:24]表示。而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 x8 的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。

以NAND_ADDR 为例:

第1 步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令决定的,即指令决定在哪一个halfpage 上进行读写。而真正的bit8 的值是don't care 的。

第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 的容量是256Mbit 如下,那么,block adress 最高位只到bit24,所以寻址 只须要3 步。 下面,就x16 的NAND flash 器件稍微进行一下说明。 因为一个page 的main area 的容量为256word,仍至关于512byte。可是,这个时候没有所谓 的1st halfpage 和2nd halfpage 之分了,因此,bit8就变得没有意义了,也就是这个时候 bit8 彻底不用管,地址传递仍然和x8 器件相同。除了,这一点以外,x16 的NAND使用方法和 x8 的使用方法彻底相同。

正如硬盘的盘片被分为磁道,每一个磁道又分为若干扇区,一块nand flash也分为若干block,每一个block分为如干page。通常而言,block、page之间的关系随着芯片的不一样而不一样,典型的分配是这样的:

1block = 32page

1page = 512bytes(datafield) + 16bytes(oob)

须要注意的是,对于flash的读写都是以一个page开始的,可是在读写以前必须进行flash的擦写,而擦写则是以一个block为单位的。同时必须提醒的是,512bytes理论上被分为1st half 和2sd half,每一个half各占256个字节。

咱们讨论的K9F1208U0B总共有4096 个Blocks,故咱们能够知道这块flash的容量为4096 *(32 *528)= 69206016 Bytes = 66 MB 但事实上每一个Page上的最后16Bytes是用于存贮检验码和其余信息用的,并不能存放实际的数据,因此实际上咱们能够操做的芯片容量为4096 *(32 *512) = 67108864 Bytes = 64 MB由 上图所示,1个Page总共由528 Bytes组成,这528个字节按顺序由上而下以列为单位进行排列(1列表明一个Byte。第0行为第0 Byte ,第1行为第1 Byte,以此类推,每一个行又由8个位组成,每一个位表示1个Byte里面的1bit)。这528Bytes按功能分为两大部分,分别是Data Field和Spare Field,其中Spare Field占528Bytes里的16Bytes,这16Bytes是用于在读写操做的时候存放校验码用的,通常不用作普通数据的存储区,除去这 16Bytes,剩下的512Bytes即是咱们用于存放数据用的Data Field,因此一个Page上虽然有528个Bytes,但咱们只按512Bytes进行容量的计算。

读 命令有两个,分别是 Read1,Read2其中Read1用于读取Data Field的数据,而Read2则是用于读取Spare Field的数据。对于Nand Flash来讲,读操做的最小操做单位为Page,也就是说当咱们给定了读取的起始位置后,读操做将从该位置开始,连续读取到本Page的最后一个 Byte为止(能够包括Spare Field)

Nand Flash的寻址

    Nand Flash的地址寄存器把一个完整的Nand Flash地址分解成Column Address与Page Address.进行寻址。

Column Address: 列地址。Column Address其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。

Paage Address:页地址。因为页地址老是以512Bytes对齐的,因此它的低9位老是0。肯定读写操做是在Flash上的哪一个页进行的。

Read1命令

当咱们获得一个Nand Flash地址src_addr时咱们能够这样分解出Column Address和Page Address

column_addr=src_addr%512;                      // column address

page_address=(src_addr>>9);                       // page address

也能够这么认为,一个Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8并无出现,也就是A8被忽略,在下面你将了解到这是什么缘由)

Read1 命令的操做分为4个Cycle,发送完读命令00h或01h(00h与01h的区别请见下文描述)以后将分4个Cycle发送参数,1st.Cycle是发送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle则是指定Page Address(每次向地址寄存器发送的数据只能是8位,因此17位的Page Address必须分红3次进行发送

Read1的 命令里面出现了两个命令选项,分别是00h和01h。这里出现了两个读命是否令你意识到什么呢?是的,00h是用于读写1st half的命令,而01h是用于读取2nd half的命令。如今我能够结合上图给你说明为何K9F1208U0B的DataField被分为2个half了。

如上文我所说起的,Read1的1st.Cycle是发送Column Address,假设我如今指定的Column Address是0,那么读操做将今后页的第0号Byte开始一直读取到此页的最后一个Byte(包括Spare Field),若是我指定的Column Address是127,状况也与前面同样,但不知道你发现没有,用于传递Column Address的数据线有8条(I/O0~I/O7,对应A0~A7,这也是A8为何不出如今咱们传递的地址位中),也就是说咱们可以指定的 Column Address范围为0~255,但不要忘了,1个Page的DataField是由512个Byte组成的,假设如今我要指定读命令从第256个字节处 开始读取此页,那将会发生什么情景?我必须把Column Address设置为256,但Column Address最大只能是255,这就形成数据溢出。。。正是由于这个缘由咱们才把Data Field分为两个半区,当要读取的起始地址(Column Address)在0~255内时咱们用00h命令,当读取的起始地址是在256~511时,则使用01h命令.假设如今我要指定从第256个byte开 始读取此页,那么我将这样发送命令串

column_addr=256;

NF_CMD=0x01; ?                                     从2nd half开始读取

NF_ADDR=column_addr&0xff;                       1st Cycle

NF_ADDR=page_address&0xff;                   2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;          3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;           4th.Cycle

其中NF_CMD和NF_ADDR分别是NandFlash的命令寄存器和地址寄存器的地址解引用,我通常这样定义它们,

#define rNFCMD        (*(volatile unsigned char *)0x4e000004)        //NADD Flash command

#define rNFADDR        (*(volatile unsigned char *)0x4e000008)        //NAND Flash address

事实上,当NF_CMD=0x01时,地址寄存器中的第8位(A8)将被设置为1(如上文分析,A8位不在咱们传递的地址中,这个位其实就是硬件电路根据 01h或是00h这两个命令来置高位或是置低位),这样咱们传递column_addr的值256随然因为数据溢出变为1,但A8位已经因为NF_CMD =0x01的关系被置为1了,因此咱们传到地址寄存器里的值变成了

A0   A1   A2   A3   A4   A5   A6   A7   A8

1     0    0    0 0     0 0 0    1

这8个位所表示的正好是256,这样读操做将今后页的第256号byte(2nd half的第0号byte)开始读取数据。 nand_flash.c中包含3个函数

void nf_reset(void);

void nf_init(void);

void nf_read(unsigned int src_addr,unsigned   char *desc_addr,int size);

nf_reset()将被nf_init()调用。nf_init()是nand_flash的初始化函数,在对nand flash进行任何操做以前,nf_init()必须被调用。

nf_read(unsigned int src_addr,unsigned   char *desc_addr,int size);为读函数,src_addr是nand flash上的地址,desc_addr是内存地址,size是读取文件的长度。

在nf_reset和nf_read函数中存在两个宏

NF_nFCE_L();

NF_nFCE_H();

你能够看到当每次对Nand Flash进行操做以前NF_nFCE_L()一定被调用,操做结束之时NF_nFCE_H()一定被调用。这两个宏用于启动和关闭Flash芯片的工做(片选/取消片选)。至于nf_reset()中的

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

这一行代码是对NandFlash的控制寄存器进行初始化配置,rNFCONF是Nand Flash的配置寄存器,各个位的具体功能请参阅s3c2410数据手册。

如今举一个例子,假设我要从Nand Flash中的第5000字节处开始读取1024个字节到内存的0x30000000处,咱们这样调用read函数

nf_read(5000, 0x30000000,1024);

咱们来分析5000这个src_addr.

根据

column_addr=src_addr%512;      

page_address=(src_addr>>9);   

咱们可得出column_addr=5000%512=392

page_address=(5000>>9)=9

因而咱们能够知道5000这个地址是在第9页的第392个字节处,因而咱们的nf_read函数将这样发送命令和参数

column_addr=5000%512;

>page_address=(5000>>9);

NF_CMD=0x01;                                        从2nd half开始读取

NF_ADDR= column_addr &0xff;                   1st Cycle

NF_ADDR=page_address&0xff;                   2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;          3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;           4th.Cycle

向NandFlash的命令寄存器和地址寄存器发送完以上命令和参数以后,咱们就能够从rNFDATA寄存器(NandFlash数据寄存器)读取数据了.

我用下面的代码进行数据的读取.

for(i=column_addr;i<512;i++)

{

       *buf++=NF_RDDATA();

}

每当读取完一个Page以后,数据指针会落在下一个Page的0号Column(0号Byte).

下面是源代码:

/*

http://www.another-prj.com/

    author: caiyuqing   

本代码只属于交流学习,不得用于商业开发

*/

#include "s3c2410.h"

#include "nand_flash.h"

static unsigned char seBuf[16]={0xff};

//--------------------------------------------------------------------------------------

unsigned short nf_checkId(void)

{

    int i;

    unsigned short id;

    NF_nFCE_L();        //chip enable

    NF_CMD(0x90);        //Read ID

    NF_ADDR(0x0);

    for(i=0;i<10;i++);    //wait tWB(100ns)

    id="NF"_RDDATA()<<8;    // Maker code(K9S1208V:0xec)

    id|=NF_RDDATA();    // Devide code(K9S1208V:0x76)

    NF_nFCE_H();        //chip enable

    return id;

}

//--------------------------------------------------------------------------------------

static void nf_reset(void)

{

    int i;

    NF_nFCE_L();        //chip enable

    NF_CMD(0xFF);        //reset command

    for(i=0;i<10;i++);     //tWB = 100ns.

    NF_WAITRB();         //wait 200~500us;

    NF_nFCE_H();        //chip disable

}

//--------------------------------------------------------------------------------------

void nf_init(void)

{

    rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);   

    //         1     1        1         1       1      xxx     r xxx,      r xxx       

    //         En     r    r       ECCR    nFCE="H" tACLS   tWRPH0      tWRPH1

    nf_reset();

}

//--------------------------------------------------------------------------------------

void nf_read(unsigned int src_addr,unsigned char *desc_addr,int size)

{

    int i;

    unsigned int column_addr = src_addr % 512;            // column address

    unsigned int page_address = (src_addr >> 9);        // page addrress

    unsigned char *buf = desc_addr;

    while((unsigned int)buf < (unsigned int)(desc_addr) + size)

    {

        NF_nFCE_L();                    // enable chip

        /*NF_ADDR和NF_CMD为nand_flash的地址和命令寄存器的解引用*/

        if(column_addr > 255)                // 2end halft   

            NF_CMD(0x01);                // Read2 command.   cmd 0x01: Read command(start from 2end half page)       

        else

            NF_CMD(0x00);                // 1st halft?

        NF_ADDR(column_addr & 0xff);                // Column Address

        NF_ADDR(page_address & 0xff);            // Page Address

        NF_ADDR((page_address >> 8) & 0xff);        // ...

        NF_ADDR((page_address >> 16) & 0xff);        // ..

        for(i = 0; i < 10; i++);                // wait tWB(100ns)/////??????

            NF_WAITRB();                    // Wait tR(max 12us)

        // Read from main area

        for(i = column_addr; i < 512; i++)

        {

            *buf++= NF_RDDATA();

        }

        NF_nFCE_H();                    // disable chip

        column_addr = 0;

        page_address++;

    }

    return ;

}

今天在利用ARM7上的nandflash控制器驱动,ID已读取成功,擦写,读取等还没有完成,晚上就在网上查查相关的知识,以为有一个不错,转贴以下:

NAND Flash 的数据是以bit 的方式保存在memory cell,通常来讲,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再组成Page.

(Nand Flash 有多种结构,我使用的Nand Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Byte,每32 个page 造成一个Block, Sizeof(block)=16kByte 。

1 block="16kbyte",512Mbit=64Mbyte,Numberof(block)=4096 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

Nand flash 以页为单位读写数据,而以块为单位擦除数据。

按照这样的组织方式能够造成所谓的三类地址:

--Block Address -- Page Address --Column Address

对于NAND Flash 来说,地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。

512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address。

32 个page 须要5bit 来表示,占用A[13:9],即该page 在块内的相对地址。Block的地址是由A14 以上的bit 来表示,例如512Mb 的NAND,共4096block,所以,须要12 个bit 来表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,则block address用A[26:24]表示。而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 x8 的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。以NAND_ADDR 为例: 第1 步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令决定的,即指令决定在哪一个halfpage 上进行读写。而真正的bit8 的值是don't care 的。 第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 的容量是256Mbit 如下,那么,block adress 最高位只到bit24,所以寻址 只须要3 步。 下面,就x16 的NAND flash 器件稍微进行一下说明。 因为一个page 的main area 的容量为256word,仍至关于512byte。可是,这个时候没有所谓 的1st halfpage 和2nd halfpage 之分了,因此,bit8就变得没有意义了,也就是这个时候 bit8 彻底不用管,地址传递仍然和x8 器件相同。除了,这一点以外,x16 的NAND使用方法和 x8 的使用方法彻底相同。

正如硬盘的盘片被分为磁道,每一个磁道又分为若干扇区,一块nand flash也分为若干block,每一个block分为如干page。通常而言,block、page之间的关系随着芯片的不一样而不一样,典型的分配是这样的:

1block = 32page

1page = 512bytes(datafield) + 16bytes(oob)

须要注意的是,对于flash的读写都是以一个page开始的,可是在读写以前必须进行flash的擦写,而擦写则是以一个block为单位的。同时必须提醒的是,512bytes理论上被分为1st half 和2sd half,每一个half各占256个字节。

咱们讨论的K9F1208U0B总共有4096 个Blocks,故咱们能够知道这块flash的容量为4096 *(32 *528)= 69206016 Bytes = 66 MB 但事实上每一个Page上的最后16Bytes是用于存贮检验码和其余信息用的,并不能存放实际的数据,因此实际上咱们能够操做的芯片容量为4096 *(32 *512) = 67108864 Bytes = 64 MB由 上图所示,1个Page总共由528 Bytes组成,这528个字节按顺序由上而下以列为单位进行排列(1列表明一个Byte。第0行为第0 Byte ,第1行为第1 Byte,以此类推,每一个行又由8个位组成,每一个位表示1个Byte里面的1bit)。这528Bytes按功能分为两大部分,分别是Data Field和Spare Field,其中Spare Field占528Bytes里的16Bytes,这16Bytes是用于在读写操做的时候存放校验码用的,通常不用作普通数据的存储区,除去这 16Bytes,剩下的512Bytes即是咱们用于存放数据用的Data Field,因此一个Page上虽然有528个Bytes,但咱们只按512Bytes进行容量的计算。

读 命令有两个,分别是 Read1,Read2其中Read1用于读取Data Field的数据,而Read2则是用于读取Spare Field的数据。对于Nand Flash来讲,读操做的最小操做单位为Page,也就是说当咱们给定了读取的起始位置后,读操做将从该位置开始,连续读取到本Page的最后一个 Byte为止(能够包括Spare Field)

Nand Flash的寻址

    Nand Flash的地址寄存器把一个完整的Nand Flash地址分解成Column Address与Page Address.进行寻址。

Column Address: 列地址。Column Address其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。

Paage Address:页地址。因为页地址老是以512Bytes对齐的,因此它的低9位老是0。肯定读写操做是在Flash上的哪一个页进行的。

Read1命令

当咱们获得一个Nand Flash地址src_addr时咱们能够这样分解出Column Address和Page Address

column_addr=src_addr%512;                      // column address

page_address=(src_addr>>9);                       // page address

也能够这么认为,一个Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8并无出现,也就是A8被忽略,在下面你将了解到这是什么缘由)

Read1 命令的操做分为4个Cycle,发送完读命令00h或01h(00h与01h的区别请见下文描述)以后将分4个Cycle发送参数,1st.Cycle是发送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle则是指定Page Address(每次向地址寄存器发送的数据只能是8位,因此17位的Page Address必须分红3次进行发送

Read1的 命令里面出现了两个命令选项,分别是00h和01h。这里出现了两个读命是否令你意识到什么呢?是的,00h是用于读写1st half的命令,而01h是用于读取2nd half的命令。如今我能够结合上图给你说明为何K9F1208U0B的DataField被分为2个half了。

如上文我所说起的,Read1的1st.Cycle是发送Column Address,假设我如今指定的Column Address是0,那么读操做将今后页的第0号Byte开始一直读取到此页的最后一个Byte(包括Spare Field),若是我指定的Column Address是127,状况也与前面同样,但不知道你发现没有,用于传递Column Address的数据线有8条(I/O0~I/O7,对应A0~A7,这也是A8为何不出如今咱们传递的地址位中),也就是说咱们可以指定的 Column Address范围为0~255,但不要忘了,1个Page的DataField是由512个Byte组成的,假设如今我要指定读命令从第256个字节处 开始读取此页,那将会发生什么情景?我必须把Column Address设置为256,但Column Address最大只能是255,这就形成数据溢出。。。正是由于这个缘由咱们才把Data Field分为两个半区,当要读取的起始地址(Column Address)在0~255内时咱们用00h命令,当读取的起始地址是在256~511时,则使用01h命令.假设如今我要指定从第256个byte开 始读取此页,那么我将这样发送命令串

column_addr=256;

NF_CMD=0x01; ?                                     从2nd half开始读取

NF_ADDR=column_addr&0xff;                       1st Cycle

NF_ADDR=page_address&0xff;                   2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;          3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;           4th.Cycle

其中NF_CMD和NF_ADDR分别是NandFlash的命令寄存器和地址寄存器的地址解引用,我通常这样定义它们,

#define rNFCMD        (*(volatile unsigned char *)0x4e000004)        //NADD Flash command

#define rNFADDR        (*(volatile unsigned char *)0x4e000008)        //NAND Flash address

事实上,当NF_CMD=0x01时,地址寄存器中的第8位(A8)将被设置为1(如上文分析,A8位不在咱们传递的地址中,这个位其实就是硬件电路根据 01h或是00h这两个命令来置高位或是置低位),这样咱们传递column_addr的值256随然因为数据溢出变为1,但A8位已经因为NF_CMD =0x01的关系被置为1了,因此咱们传到地址寄存器里的值变成了

A0   A1   A2   A3   A4   A5   A6   A7   A8

1     0    0    0 0     0 0 0    1

这8个位所表示的正好是256,这样读操做将今后页的第256号byte(2nd half的第0号byte)开始读取数据。 nand_flash.c中包含3个函数

void nf_reset(void);

void nf_init(void);

void nf_read(unsigned int src_addr,unsigned   char *desc_addr,int size);

nf_reset()将被nf_init()调用。nf_init()是nand_flash的初始化函数,在对nand flash进行任何操做以前,nf_init()必须被调用。

nf_read(unsigned int src_addr,unsigned   char *desc_addr,int size);为读函数,src_addr是nand flash上的地址,desc_addr是内存地址,size是读取文件的长度。

在nf_reset和nf_read函数中存在两个宏

NF_nFCE_L();

NF_nFCE_H();

你能够看到当每次对Nand Flash进行操做以前NF_nFCE_L()一定被调用,操做结束之时NF_nFCE_H()一定被调用。这两个宏用于启动和关闭Flash芯片的工做(片选/取消片选)。至于nf_reset()中的

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

这一行代码是对NandFlash的控制寄存器进行初始化配置,rNFCONF是Nand Flash的配置寄存器,各个位的具体功能请参阅s3c2410数据手册。

如今举一个例子,假设我要从Nand Flash中的第5000字节处开始读取1024个字节到内存的0x30000000处,咱们这样调用read函数

nf_read(5000, 0x30000000,1024);

咱们来分析5000这个src_addr.

根据

column_addr=src_addr%512;      

page_address=(src_addr>>9);   

咱们可得出column_addr=5000%512=392

page_address=(5000>>9)=9

因而咱们能够知道5000这个地址是在第9页的第392个字节处,因而咱们的nf_read函数将这样发送命令和参数

column_addr=5000%512;

>page_address=(5000>>9);

NF_CMD=0x01;                                        从2nd half开始读取

NF_ADDR= column_addr &0xff;                   1st Cycle

NF_ADDR=page_address&0xff;                   2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;          3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;           4th.Cycle

向NandFlash的命令寄存器和地址寄存器发送完以上命令和参数以后,咱们就能够从rNFDATA寄存器(NandFlash数据寄存器)读取数据了.

我用下面的代码进行数据的读取.

for(i=column_addr;i<512;i++)

{

       *buf++=NF_RDDATA();

}

每当读取完一个Page以后,数据指针会落在下一个Page的0号Column(0号Byte).

下面是源代码:

/*

http://www.another-prj.com/

    author: caiyuqing   

本代码只属于交流学习,不得用于商业开发

*/

#include "s3c2410.h"

#include "nand_flash.h"

static unsigned char seBuf[16]={0xff};

//--------------------------------------------------------------------------------------

unsigned short nf_checkId(void)

{

    int i;

    unsigned short id;

    NF_nFCE_L();        //chip enable

    NF_CMD(0x90);        //Read ID

    NF_ADDR(0x0);

    for(i=0;i<10;i++);    //wait tWB(100ns)

    id="NF"_RDDATA()<<8;    // Maker code(K9S1208V:0xec)

    id|=NF_RDDATA();    // Devide code(K9S1208V:0x76)

    NF_nFCE_H();        //chip enable

    return id;

}

//--------------------------------------------------------------------------------------

static void nf_reset(void)

{

    int i;

    NF_nFCE_L();        //chip enable

    NF_CMD(0xFF);        //reset command

    for(i=0;i<10;i++);     //tWB = 100ns.

    NF_WAITRB();         //wait 200~500us;

    NF_nFCE_H();        //chip disable

}

//--------------------------------------------------------------------------------------

void nf_init(void)

{

    rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);   

    //         1     1        1         1       1      xxx     r xxx,      r xxx       

    //         En     r    r       ECCR    nFCE="H" tACLS   tWRPH0      tWRPH1

    nf_reset();

}

//--------------------------------------------------------------------------------------

void nf_read(unsigned int src_addr,unsigned char *desc_addr,int size)

{

    int i;

    unsigned int column_addr = src_addr % 512;            // column address

    unsigned int page_address = (src_addr >> 9);        // page addrress

    unsigned char *buf = desc_addr;

    while((unsigned int)buf < (unsigned int)(desc_addr) + size)

    {

        NF_nFCE_L();                    // enable chip

        /*NF_ADDR和NF_CMD为nand_flash的地址和命令寄存器的解引用*/

        if(column_addr > 255)                // 2end halft   

            NF_CMD(0x01);                // Read2 command.   cmd 0x01: Read command(start from 2end half page)       

        else

            NF_CMD(0x00);                // 1st halft?

        NF_ADDR(column_addr & 0xff);                // Column Address

        NF_ADDR(page_address & 0xff);            // Page Address

        NF_ADDR((page_address >> 8) & 0xff);        // ...

        NF_ADDR((page_address >> 16) & 0xff);        // ..

        for(i = 0; i < 10; i++);                // wait tWB(100ns)/////??????

            NF_WAITRB();                    // Wait tR(max 12us)

        // Read from main area

        for(i = column_addr; i < 512; i++)

        {

            *buf++= NF_RDDATA();

        }

        NF_nFCE_H();                    // disable chip

        column_addr = 0;

        page_address++;

    }

    return ;

}


Nand Flash结构与读写分析

今天在利用ARM7上的nandflash控制器驱动,ID已读取成功,擦写,读取等还没有完成,晚上就在网上查查相关的知识,以为有一个不错,转贴以下:
NAND Flash 的数据是以bit 的方式保存在memory cell,通常来讲,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再组成Page.
(Nand Flash 有多种结构,我使用的Nand Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Byte,每32 个page 造成一个Block, Sizeof(block)=16kByte 。
1 block="16kbyte",512Mbit=64Mbyte,Numberof(block)=4096 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)
Nand flash 以页为单位读写数据,而以块为单位擦除数据。
按照这样的组织方式能够造成所谓的三类地址:
--Block Address -- Page Address --Column Address
对于NAND Flash 来说,地址和命令只能在I/O【7:0】上传递,数据宽度是8 位。
512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half和2nd half,各自的访问由地址指针命令来选择,A【7:0】就是所谓的column address。
32 个page 须要5bit 来表示,占用A【13:9】,即该page 在块内的相对地址。Block的地址是由A14 以上的bit 来表示,例如512Mb 的NAND,共4096block,所以,须要12 个bit 来表示,即A【25:14】,若是是1Gbit 的528byte/page的NAND Flash,则block address用A【26:24】表示。而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 x8 的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。以NAND_ADDR 为例: 第1 步是传递column address,就是NAND_ADDR【7:0】,不需移位便可传递到I/O【7:0】上,而halfpage pointer 即bit8 是由操做指令决定的,即指令决定在哪一个halfpage 上进行读写。而真正的bit8 的值是don‘t care 的。 第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 的容量是256Mbit 如下,那么,block adress 最高位只到bit24,所以寻址只须要3 步。 下面,就x16 的NAND flash 器件稍微进行一下说明。 因为一个page 的main area 的容量为256word,仍至关于512byte。可是,这个时候没有所谓 的1st halfpage 和2nd halfpage 之分了,因此,bit8就变得没有意义了,也就是这个时候 bit8 彻底不用管,地址传递仍然和x8 器件相同。除了,这一点以外,x16 的NAND使用方法和 x8 的使用方法彻底相同。
正如硬盘的盘片被分为磁道,每一个磁道又分为若干扇区,一块nand flash也分为若干block,每一个block分为如干page。通常而言,block、page之间的关系随着芯片的不一样而不一样,典型的分配是这样的:
1block = 32page
1page = 512bytes(datafield) + 16bytes(oob)

clip_image015

须要注意的是,对于flash的读写都是以一个page开始的,可是在读写以前必须进行flash的擦写,而擦写则是以一个block为单位的。同时必须提醒的是,512bytes理论上被分为1st half 和2sd half,每一个half各占256个字节。
咱们讨论的K9F1208U0B总共有4096 个Blocks,故咱们能够知道这块flash的容量为4096 *(32 *528)= 69206016 Bytes = 66 MB 但事实上每一个Page上的最后16Bytes是用于存贮检验码和其余信息用的,并不能存放实际的数据,因此实际上咱们能够操做的芯片容量为4096 *(32 *512) = 67108864 Bytes = 64 MB由 上图所示,1个Page总共由528 Bytes组成,这528个字节按顺序由上而下以列为单位进行排列(1列表明一个Byte。第0行为第0 Byte ,第1行为第1 Byte,以此类推,每一个行又由8个位组成,每一个位表示1个Byte里面的1bit)。这528Bytes按功能分为两大部分,分别是Data Field和Spare Field,其中Spare Field占528Bytes里的16Bytes,这16Bytes是用于在读写操做的时候存放校验码用的,通常不用作普通数据的存储区,除去这 16Bytes,剩下的512Bytes即是咱们用于存放数据用的Data Field,因此一个Page上虽然有528个Bytes,但咱们只按512Bytes进行容量的计算。
读 命令有两个,分别是 Read1,Read2其中Read1用于读取Data Field的数据,而Read2则是用于读取Spare Field的数据。对于Nand Flash来讲,读操做的最小操做单位为Page,也就是说当咱们给定了读取的起始位置后,读操做将从该位置开始,连续读取到本Page的最后一个 Byte为止(能够包括Spare Field)
Nand Flash的寻址
Nand Flash的地址寄存器把一个完整的Nand Flash地址分解成Column Address与Page Address.进行寻址。
Column Address: 列地址。Column Address其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。
Paage Address:页地址。因为页地址老是以512Bytes对齐的,因此它的低9位老是0。肯定读写操做是在Flash上的哪一个页进行的。
Read1命令
当咱们获得一个Nand Flash地址src_addr时咱们能够这样分解出Column Address和Page Address
column_addr=src_addr%512; // column address
page_address=(src_addr>>9); // page address
也能够这么认为,一个Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8并无出现,也就是A8被忽略,在下面你将了解到这是什么缘由)
Read1 命令的操做分为4个Cycle,发送完读命令00h或01h(00h与01h的区别请见下文描述)以后将分4个Cycle发送参数,1st.Cycle是 发送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle则是指定Page Address(每次向地址寄存器发送的数据只能是8位,因此17位的Page Address必须分红3次进行发送
Read1的 命令里面出现了两个命令选项,分别是00h和01h。这里出现了两个读命是否令你意识到什么呢?是的,00h是用于读写1st half的命令,而01h是用于读取2nd half的命令。如今我能够结合上图给你说明为何K9F1208U0B的DataField被分为2个half了。
如上文我所说起的,Read1的1st.Cycle是发送Column Address,假设我如今指定的Column Address是0,那么读操做将今后页的第0号Byte开始一直读取到此页的最后一个Byte(包括Spare Field),若是我指定的Column Address是127,状况也与前面同样,但不知道你发现没有,用于传递Column Address的数据线有8条(I/O0~I/O7,对应A0~A7,这也是A8为何不出如今咱们传递的地址位中),也就是说咱们可以指定的 Column Address范围为0~255,但不要忘了,1个Page的DataField是由512个Byte组成的,假设如今我要指定读命令从第256个字节处 开始读取此页,那将会发生什么情景?我必须把Column Address设置为256,但Column Address最大只能是255,这就形成数据溢出。。。正是由于这个缘由咱们才把Data Field分为两个半区,当要读取的起始地址(Column Address)在0~255内时咱们用00h命令,当读取的起始地址是在256~511时,则使用01h命令.假设如今我要指定从第256个byte开 始读取此页,那么我将这样发送命令串
column_addr=256;
NF_CMD=0x01; ? 从2nd half开始读取
NF_ADDR=column_addr&0xff; 1st Cycle
NF_ADDR=page_address&0xff; 2nd.Cycle
NF_ADDR=(page_address>>8)&0xff; 3rd.Cycle
NF_ADDR=(page_address>>16)&0xff; 4th.Cycle
其中NF_CMD和NF_ADDR分别是NandFlash的命令寄存器和地址寄存器的地址解引用,我通常这样定义它们,
#define rNFCMD (*(volatile unsigned ch ar *)0x4e000004) //NADD Flash command
#define rNFADDR (*(volatile unsigned ch ar *)0x4e000008) //NAND Flash address
事实上,当NF_CMD=0x01时,地址寄存器中的第8位(A8)将被设置为1(如上文分析,A8位不在咱们传递的地址中,这个位其实就是硬件电路根据 01h或是00h这两个命令来置高位或是置低位),这样咱们传递column_addr的值256随然因为数据溢出变为1,但A8位已经因为NF_CMD =0x01的关系被置为1了,因此咱们传到地址寄存器里的值变成了
A0 A1 A2 A3 A4 A5 A6 A7 A8
1 0 0 0 0 0 0 0 1
这8个位所表示的正好是256,这样读操做将今后页的第256号byte(2nd half的第0号byte)开始读取数据。 nand_flash.c中包含3个函数
void nf_reset(void);
void nf_init(void);
void nf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size);
nf_reset()将被nf_init()调用。nf_init()是nand_flash的初始化函数,在对nand flash进行任何操做以前,nf_init()必须被调用。
nf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size);为读函数,src_addr是nand flash上的地址,desc_addr是内存地址,size是读取文件的长度。
在nf_reset和nf_read函数中存在两个宏
NF_nFCE_L();
NF_nFCE_H();
你能够看到当每次对Nand Flash进行操做以前NF_nFCE_L()一定被调用,操做结束之时NF_nFCE_H()一定被调用。这两个宏用于启动和关闭Flash芯片的工做(片选/取消片选)。至于nf_reset()中的
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
这一行代码是对NandFlash的控制寄存器进行初始化配置,rNFCONF是Nand Flash的配置寄存器,各个位的具体功能请参阅s3c2410数据手册。
如今举一个例子,假设我要从Nand Flash中的第5000字节处开始读取1024个字节到内存的0x30000000处,咱们这样调用read函数
nf_read(5000, 0x30000000,1024);
咱们来分析5000这个src_addr.
根据
column_addr=src_addr%512;
page_address=(src_addr>>9);
咱们可得出column_addr=5000%512=392
page_address=(5000>>9)=9
因而咱们能够知道5000这个地址是在第9页的第392个字节处,因而咱们的nf_read函数将这样发送命令和参数
column_addr=5000%512;
>page_address=(5000>>9);
NF_CMD=0x01; 从2nd half开始读取
NF_ADDR= column_addr &0xff; 1st Cycle
NF_ADDR=page_address&0xff; 2nd.Cycle
NF_ADDR=(page_address>>8)&0xff; 3rd.Cycle
NF_ADDR=(page_address>>16)&0xff; 4th.Cycle
向NandFlash的命令寄存器和地址寄存器发送完以上命令和参数以后,咱们就能够从rNFDATA寄存器(NandFlash数据寄存器)读取数据了.
我用下面的代码进行数据的读取.
for(i=column_addr;i<512;i++)
{
*buf++=NF_RDDATA();
}
每当读取完一个Page以后,数据指针会落在下一个Page的0号Column(0号Byte).
下面是源代码:
/*
www.another-prj.com
author: caiyuqing
本代码只属于交流学习,不得用于商业开发
*/
#include "s3c2410.h"
#include "nand_flash.h"
static unsigned ch ar seBuf【16】={0xff};
//--------------------------------------------------------------------------------------
unsigned short nf_checkId(void)
{
int i;
unsigned short id;
NF_nFCE_L(); //chip enable
NF_CMD(0x90); //Read ID
NF_ADDR(0x0);
for(i=0;i<10;i++); //wait tWB(100ns)
id="NF"_RDDATA()<<8; // Maker code(K9S1208V:0xec)
id|=NF_RDDATA(); // Devide code(K9S1208V:0x76)
NF_nFCE_H(); //chip enable
return id;
}
//--------------------------------------------------------------------------------------
static void nf_reset(void)
{
int i;
NF_nFCE_L(); //chip enable
NF_CMD(0xFF); //reset command
for(i=0;i<10;i++); //tWB = 100ns.
NF_WAITRB(); //wait 200~500us;
NF_nFCE_H(); //chip disable
}
//--------------------------------------------------------------------------------------
void nf_init(void)
{
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
// 1 1 1 1 1 xxx r xxx, r xxx
// En r r ECCR nFCE="H" tACLS tWRPH0 tWRPH1
nf_reset();
}
//--------------------------------------------------------------------------------------
void nf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size)
{
int i;
unsigned int column_addr = src_addr % 512; // column address
unsigned int page_address = (src_addr >> 9); // page addrress
unsigned ch ar *buf = desc_addr;
while((unsigned int)buf < (unsigned int)(desc_addr) + size)
{
NF_nFCE_L(); // enable chip
/*NF_ADDR和NF_CMD为nand_flash的地址和命令寄存器的解引用*/
if(column_addr > 255) // 2end halft
NF_CMD(0x01); // Read2 command. cmd 0x01: Read command(start from 2end half page)
else
NF_CMD(0x00); // 1st halft?
NF_ADDR(column_addr & 0xff); // Column Address
NF_ADDR(page_address & 0xff); // Page Address
NF_ADDR((page_address >> 8) & 0xff); // ...
NF_ADDR((page_address >> 16) & 0xff); // ..
for(i = 0; i < 10; i++); // wait tWB(100ns)/////??????
NF_WAITRB(); // Wait tR(max 12us)
// Read from main area
for(i = column_addr; i < 512; i++)
{
*buf++= NF_RDDATA();
}
NF_nFCE_H(); // disable chip
column_addr = 0;
page_address++;
}
return ;
}

NAND Flash结构与驱动分析

1、NAND flash的物理组成
NAND Flash 的数据是以bit的方式保存在memory cell,通常来讲,一个cell 中只能存储一个bit。这些cell 以8个或者16个为单位,连成bit line,造成所谓的byte(x8)/word(x16),这就是NAND Device的位宽。这些Line会再组成Page,(NAND Flash 有多种结构,我使用的NAND Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Bytes(512byte(Main Area)+16byte(Spare Area)),每32个page造成一个Block(32*528B)。具体一片flash上有多少个Block视须要所定。我所使用的三星 k9f1208U0M具备4096个block,故总容量为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位。

2、NAND Flash地址的表示
512byte须要9bit来表示,对于528byte系列的NAND,这512byte被分红1st half Page Register和2nd half Page Register,各自的访问由地址指针命令来选择,A[7:0]就是所谓的column address(列地址),在进行擦除操做时不须要它,why?由于以块为单位擦除。32个page须要5bit来表示,占用A[13:9],即该page在块内的相对地址。A8这一位地址被用来设置512byte的1st half page仍是2nd half page,0表示1st,1表示2nd。Block的地址是由A14以上的bit来表示。
例 如64MB(512Mb)的NAND flash(实际中因为存在spare area,故都大于这个值),共4096block,所以,须要12个bit来表示,即A[25:14],若是是128MB(1Gbit) 的528byte/page的NAND Flash,则block address用A[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 x8的NAND flash,地址范围是0~0x3FF_FFFF,只要是这个范围内的数值表示的地址都是有效的。 以NAND_ADDR 为例:
第1 步是传递column address,就是NAND_ADDR[7:0],不需移位便可传递到I/O[7:0]上,而halfpage pointer即A8 是由操做指令决定的,即指令决定在哪一个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步。
下面,就x16 的NAND flash 器件稍微进行一下说明。 因为一个page 的main area 的容量为256word,仍至关于512byte。可是,这个时候没有所谓的1st halfpage 和2nd halfpage 之分了,因此,bit8就变得没有意义了,也就是这个时候 A8 彻底不用管,地址传递仍然和x8 器件相同。除了,这一点以外,x16 的NAND使用方法和 x8 的使用方法彻底相同。

3、NAND flash驱动解读
之前因为作移植多一些,那些工做 很简单(如今看来),历来都不用去关心驱动里面到底怎么实现的,这几回面试才发现真的是学的太浅了,彷佛我还在学习仰泳而那些牛人基本都属于潜水级的了, 潜的不知有多深。我对照着开发板所带的NAND flash驱动和k9f1208的芯片资料把这些代码通读了一遍,终于明白了NAND flash的读写过程是如何实现的了。我所参考的驱动是mizi公司为三星芯片所写的,我看看了,大概和官方2.4.18内核的nand.c差很少。
在 s3c2410处理器中有专门的NAND flash控制器,他们位于SFR区,具体能够参看s3c2410用户手册。如下的这些代码都可以在vivi或者kernel里面找到,文中会标明程序出 自何处。在vivi中,有关NAND flash的驱动都在driver/mtd/nand/下,该目录中包含的源文件:smc_core.c是NAND flash的主要驱动。
NAND flash 芯片定义了一个很长的结构,这个结构中包含了操做NAND flash的函数和一些必要的变量(include/mtd/nand.h)。
struct nand_chip {
#ifdef CONFIG_MTD_NANDY     /* =y */
    void (*hwcontrol)(int cmd);
    void (*write_cmd)(u_char val);
    void (*write_addr)(u_char val);
    u_char (*read_data)(void);
    void (*write_data)(u_char val);
    void (*wait_for_ready)(void);
    int page_shift;
    u_char *data_buf;
    u_char *data_cache;
    int    cache_page;
    struct nand_smc_dev *dev;
    u_char spare[SMC_OOB_SIZE];
#else    /* CONFIG_MTD_NANDY */
    ……
#ifdef CONFIG_MTD_NAND_ECC
    u_char ecc_code_buf[6];
    u_char reserved[2];
#endif
#endif    /* CONFIG_MTD_NANDY */
};
纵观对NAND flash的各类操做(read、write、erase),无外乎以下几种操做:
1.选择flash    nand_select()
2.发送命令     nand_command()
3.进行相应操做 read,write……
4.反选NAND flash   nand_deselect()

下面是以上四步的实现代码:
一、选择NAND flash
#define nand_select()   this->hwcontrol(NAND_CTL_SETNCE); \
                nand_command(mtd, NAND_CMD_RESET, -1, -1); \
                udelay (10);
hwcontrol(NAND_CTL_SETNCE) 的做用是设置2410的NAND FLASH CONFIGURATION (NFCONF) REGISTER的NAND Flash Memory chip enable位为0,这位寄存器在自动重启后就被系统自动清零。若是要访问NAND flash的内存,这位必须置1。
nand_command(mtd, NAND_CMD_RESET, -1, -1);向flash发送命令,此命令为reset,即为重置NAND flash。
而后是10us的延迟,给flash个反应时间。
二、发送命令
Nand_command()一样在smc_core.c中实现。NAND flash的命令有以下几种:

命令 命令值 描述
NAND_CMD_READ0                    0                读操做
NAND_CMD_READ1                    1                读操做
NAND_CMD_PAGEPROG                0x10            页编程操做
NAND_CMD_READOOB                0x50            读写OOB
NAND_CMD_ERASE1                 0x60            读写操做
NAND_CMD_STATUS                    0x70            读取状态
NAND_CMD_STATUS_MULTI            0x71            读取状态
NAND_CMD_SEQIN                    0x80            写操做
NAND_CMD_READID                    0x90            读Flash ID号
NAND_CMD_ERASE2                 0xd0            擦写操做
NAND_CMD_RESET                    oxff                复位操做

按照程序的注释,能够将该函数的实现分为以下几步:
一、Begin command latch cycle
实现代码:
this->hwcontrol(NAND_CTL_SETCLE);
this->hwcontrol(NAND_CTL_DAT_OUT);
找到第二条语句的定义,发现什么都么作,不解!!但愿达人解答。我猜测多是一个数据读出的使能操做,容许数据读出。
Command Latch Enable(CLE) and Address Latch Enable(ALE) are used to multiplex command and address respectively, via the I/O pins. The CLE input controls the path activation for commands sent to the command register. When active high, commands are latched into the command register through the I/O ports on the rising edge of the nWE signal. 看了这段英文相信对第一条语句的做用已经十分清楚了,他就是用来控制向命令寄存(COMMAND SET (NFCMD) REGISTER)发送命令的。
二、 Write out the command to the device
这部分对于不一样的命令来讲,操做的步骤也不太相同,若是为写操做,那么还有根据flash不一样的容量决定操做步骤,具体能够参看代码。若是为其余命令,那么就是简单的一行:
this->write_cmd (command);
将命令直接想到命令寄存器(NFCMD[7:0])中。
三、 Set ALE and clear CLE to start address cycle & Serially input address
1中已经提到了ALE和CLE的做用,如今开始发送地址。
实现代码:
this->hwcontrol(NAND_CTL_CLRCLE); // clear the command latch enable
this->hwcontrol(NAND_CTL_SETALE); // set the address latch enable
而后按位操做,是用函数write_addr()将地址写到NAND FLASH ADDRESS SET (NFADDR) REGISTER中。
四、 Latch in address
实现代码:
this->hwcontrol(NAND_CTL_CLRALE);
this->hwcontrol(NAND_CTL_DAT_IN);
地址发送完毕,清楚ALE。
五、 Pause for 15us
我使用的VIVI中,使用udelay (15)延时15us,但这个时间会因NAND Flash的不一样而不一样。
3、Operation
根 据函数的不一样,操做部分会不同,可是主要的是对NAND FLASH DATA (NFDATA) REGISTER的操做,或写(编程)或者读。经过读或写函数的参数来返回或传递读出的值或写入的值。写得操做一般比较麻烦,他要将写到flash的内容 从新读出后进行ECC校验,若是数据正确则在从新真正的写(编程),若是错误,则将数据写入flash的另外一个块。读和写都是以页为单位进行操做。而擦除 则以块为单位,三个周期发送完地址。擦除完毕后一样须要进行检察以肯定是否擦除成功。
4、De-select the NAND device
实现代码:
#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE);
反 选flash吧,不知这样叫正确与否,跟select the NAND device相反,亦即便用完后将使能flash位清0,代码是NFCONF位于0x4e00_0000的位置(NFCONF |= NFCONF_nFCE_HIGH;),有兴趣的能够读读代码,看看这是怎么实现的,个人感受就是关于寄存器的清置读起来都比较晕。

NAND闪存技术深刻解析 类别:存储器 阅读:1057   对于许多消费类音视频产品而言,NAND闪存是一种比硬盘驱动器更好的存储方案,这在不超过4GB的低容量应用中表现得犹为明显。随着人们持续追求功耗更低、重量更轻和性能更佳的产品,NAND正被证实极具吸引力。

NAND闪存阵列分为一系列128kB的区块(block),这些区块是NAND器件中 最小的可擦除实体。擦除一个区块就是把全部的位(bit)设置为“1”(而全部字节(byte)设置为FFh)。有必要经过编程,将已擦除的位从“1”变 为“0”。最小的编程实体是字节(byte)。一些NOR闪存能同时执行读写操做(见下图1)。虽然NAND不能同时执行读写操做,它能够采用称为“映射 (shadowing)”的方法,在系统级实现这一点。这种方法在我的电脑上已经沿用多年,即将BIOS从速率较低的ROM加载到速率较高的RAM上。

NAND的效率较高,是由于NAND串中没有金属触点。NAND闪存单元的大小 比NOR要小(4F2:10F2)的缘由,是NOR的每个单元都须要独立的金属触点。NAND与硬盘驱动器相似,基于扇区(页),适合于存储连续的数据,如图片、音频或我的电脑数据。虽然经过把数据映射到RAM上,能在系统级实现随机存取,可是,这样作须要额外的RAM存储空间。此外,跟硬盘一 样,NAND器件存在坏的扇区,须要纠错码(ECC)来维持数据的完整性。

存储单元面积越小,裸片的面积也就越小。在这种状况下,NAND就可以为当今的 低成本消费市场提供存储容量更大的闪存产品。NAND闪存用于几乎全部可擦除的存储卡。NAND的复用接口为全部最新的器件和密度都提供了一种类似的引脚输出。这种引脚输出使得设计工程师无须改变电路板的硬件设计,就能从更小的密度移植到更大密度的设计上。

NAND与NOR闪存比较

NAND闪存的优势在于写(编程)和擦除操做的速率快,而NOR的优势是具备随 机存取和对字节执行写(编程)操做的能力(见下图图2)。NOR的随机存取能力支持直接代码执行(XiP),而这是嵌入式应用常常须要的一个功能。NAND的缺点是随机存取的速率慢,NOR的缺点是受到读和擦除速度慢的性能制约。NAND较适合于存储文件。现在,愈来愈多的处理器具有直接NAND接 口,并能直接从NAND(没有NOR)导入数据。

NAND的真正好处是编程速度快、擦除时间短。NAND支持速率超过5Mbps的持续写操做,其区块擦除时间短至2ms,而NOR是750ms。显然,NAND在某些方面具备绝对优点。然而,它不太适合于直接随机存取。

对于16位的器件,NOR闪存大约须要41个I/O引脚;相对而言,NAND器 件仅需24个引脚。NAND器件可以复用指令、地址和数据总线,从而节省了引脚数量。复用接口的一项好处,就在于可以利用一样的硬件设计和电路板,支持较大的NAND器件。因为普通的TSOP-1封装已经沿用多年,该功能让客户可以把较高密度的NAND器件移植到相同的电路板上。NAND器件的另一个好 处显然是其封装选项:NAND提供一种厚膜的2Gb裸片或可以支持最多四颗堆叠裸片,允许在相同的TSOP-1封装中堆叠一个8Gb的器件。这就使得一种封装和接口可以在未来支持较高的密度。 图1 不一样闪存单元的对比 图2 NOR闪存的随机存取时间为0.12ms,而NAND闪存的第一字节随机存取速度要慢得多

NAND基本操做

以2Gb NAND器件为例,它由2048个区块组成,每一个区块有64个页(见图3)。 图3 2GB NAND闪存包含2,048个区块

每个页均包含一个2048字节的数据区和64字节的空闲区,总共包含 2,112字节。空闲区一般被用于ECC、耗损均衡(wear leveling)和其它软件开销功能,尽管它在物理上与其它页并无区别。NAND器件具备8或16位接口。经过8或16位宽的双向数据总线,主数据被链接到NAND存储器。在16位模式,指令和地址仅仅利用低8位,而高8位仅仅在数据传输 周期使用。

擦除区块所需时间约为2ms。一旦数据被载入寄存器,对一个页的编程大约要300μs。读一个页面须要大约25μs,其中涉及到存储阵列访问页,并将页载入16,896位寄存器中。

除了I/O总线,NAND接口由6个主要控制信号构成:

1.芯片启动(Chip Enable, CE#):若是没有检测到CE信号,那么,NAND器件就保持待机模式,不对任何控制信号做出响应。

2.写使能(Write Enable, WE#): WE#负责将数据、地址或指令写入NAND之中。

3.读使能(Read Enable, RE#): RE#容许输出数据缓冲器。

4.指令锁存使能(Command Latch Enable, CLE): 当CLE为高时,在WE#信号的上升沿,指令被锁存到NAND指令寄存器中。

5.地址锁存使能(Address Latch Enable, ALE):当ALE为高时,在WE#信号的上升沿,地址被锁存到NAND地址寄存器中。

6.就绪/忙(Ready/Busy, R/B#):若是NAND器件忙,R/B#信号将变低。该信号是漏极开路,须要采用上拉电阻。

数据每次进/出NAND寄存器都是经过16位或8位接口。当进行编程操做的时候,待编程的数据进入数据寄存器,处于在WE#信号的上升沿。在寄存器内随机存取或移动数据,要采用专用指令以便于随机存取。

数据寄存器输出数据的方式与利用RE#信号的方式相似,负责输出现有的数据,并 增长到下一个地址。WE#和RE#时钟运行速度极快,达到30ns的水准。当RE#或CE#不为低的时候,输出缓冲器将为三态。这种CE#和RE#的组合使能输出缓冲器,允许NAND闪存与NOR、SRAM或DRAM等其它类型存储器共享数据总线。该功能有时被称为“无需介意芯片启动(chip enable don't care)”。这种方案的初衷是适应较老的NAND器件,它们要求CE#在整个周期为低(译注:根据上下文改写)。 图4 输入寄存器接收到页编程(80h)指令时,内部就会所有重置为1s,使得用户能够只输入他想以0位编程的数据字节 图5 带有随机数据输入的编程指令。图中加亮的扇区显示,该指令只须要后面跟随着数据的2个字节的地址

全部NAND操做开始时,都提供一个指令周期(表1)。

当输出一串WE#时钟时,经过在I/O位7:0上设置指令、驱动CE#变低且 CLE变高,就能够实现一个指令周期。注意:在WE#信号的上升沿上,指令、地址或数据被锁存到NAND器件之中。如表1所示,大多数指令在第二个指令周期以后要占用若干地址周期。注意:复位或读状态指令例外,若是器件忙,就不该该发送新的指令。

以2Gb NAND器件的寻址方案为例,第一和第二地址周期指定列地址,该列地址指定页内的起始字节(表2)。

注意:由于最后一列的位置是2112,该最后位置的地址就是08h(在第二字节 中)和3Fh(在第一字节中)。PA5:0指定区块内的页地址,BA16:6指定区块的地址。虽然大多编程和读操做须要完整的5字节地址,在页内随机存取数据的操做仅仅用到第一和第二字节。块擦除操做仅仅须要三个最高字节(第3、第四和第五字节)来选择区块。 图6 典型的存储方法 图7 页读缓存模式

整体而言,NAND的基本操做包括:复位(Reset, FFh)操做、读 ID(Read ID, 00h)操做、读状态(Read Status, 70h)操做、编程(Program)操做、随机数据输入(Random data input, 85h)操做和读(Read)操做等。

将NAND链接处处理器

选择内置NAND接口的处理器或控制器的好处不少。若是没有这个选择,有可能在 NAND和几乎任何处理器之间设计一个“无粘接逻辑(glueless)”接口。NAND和NOR闪存的主要区别是复用地址和数据总线。该总线被用于指定指令、地址或数据。CLE信号指定指令周期,而ALE信号指定地址周期。利用这两个控制信号,有可能选择指令、地址或数据周期。把ALE链接处处理器的第 五地址位,而把CLE链接处处理器的第四地址位,就能简单地经过改变处理器输出的地址,任意选择指令、地址或数据。这允许CLE和ALE在合适的时间自动设置为低。

为了提供指令,处理器在数据总线上输出想要的指令,并输出地址0010h;为了 输出任意数量的地址周期,处理器仅仅要依次在处理器地址0020h以后输出想要的NAND地址。注意,许多处理器能在处理器的写信号周围指定若干时序参数,这对于创建合适的时序是相当重要的。利用该技术,你没必要采用任何粘接逻辑,就能够直接从处理器存取指令、地址和数据。

多层单元

多层单元(MLC)的每个单元存储两位,而传统的SLC仅仅能存储一位。MLC技术有显著的密度优越性,然而,与SLC相比(表3),其速度或可靠性稍逊。所以,SLC被用于大多数媒体卡和无线应用,而MLC器件一般被用于消费电子和其它低成本产品。

如上所述,NAND须要ECC以确保数据完整性。NAND闪存的每个页面上都 包括额外的存储空间,它就是64个字节的空闲区(每512字节的扇区有16字节)。该区能存储ECC代码及其它像磨损评级或逻辑到物理块映射之类的信息。ECC能在硬件或软件中执行,可是,硬件执行有明显的性能优点。在编程操做期间,ECC单元根据扇区中存储的数据来计算误码校订代码。数据区的ECC代码 而后被分别写入到各自的空闲区。当数据被读出时,ECC代码也被读出;运用反操做能够核查读出的数据是否正确。

有可能采用ECC算法来校订数据错误。能校订的错误的数量取决于所用算法的校订 强度。在硬件或软件中包含ECC,就提供了强大的系统级解决方案。最简单的硬件实现方案是采用简单的汉明(Simple Hamming)码,可是,只能校订单一位错误。瑞德索罗门(Reed-Solomon)码提供更为强大的纠错,并被目前的控制器广为采用。此外,BCH码因为比瑞德索罗门方法的效率 高,应用也日益普及。

要用软件执行NAND闪存的区块管理。该软件负责磨损评级或逻辑到物理映射。该软件还提供ECC码,若是处理器不包含ECC硬件的话。

编程或擦除操做以后,重要的是读状态寄存器,由于它确认是否成功地完成了编程或 擦除操做。若是操做失败,要把该区块标记为损坏且不能再使用。之前已编写进去的数据要从损坏的区块中搬出,转移到新的(好的)存储块之中。2Gb NAND的规范规定,它能够最多有40个坏的区块,这个数字在器件的生命周期(额定寿命为10万次编程/擦除周期)内都适用。一些有坏块的NAND器件能 够出厂,主要就归根于其裸片面积大。管理器件的软件负责映射坏块并由好的存储块取而代之。

利用工厂对这些区块的标记,软件经过扫描块能够肯定区块的好坏。坏块标记被固定 在空闲区的第一个位置(列地址2048)。若是在0或1页的列地址2048上的数据是“non-FF”,那么,该块要标记为坏,并映射出系统。初始化软件 仅仅须要扫描全部区块肯定以肯定哪一个为坏,而后建一个坏块表供未来参考。

当心不要擦除坏块标记,这一点很重要。工厂在宽温和宽电压范围内测试了NAND;一些由工厂标记为坏的区块可能在必定的温度或电压条件下仍然能工做,可是,未来可能会失效。若是坏块信息被擦除,就没法再恢复。


nand flash坏块管理OOB,BBT,ECC

0.NAND的操做管理方式

NAND FLASH的管理方式:以三星FLAHS为例,一片Nand flash为一个设备(device),1 (Device) = xxxx (Blocks),1 (Block) = xxxx (Pages),1(Page) =528 (Bytes) = 数据块大小(512Bytes) + OOB 块大小(16Bytes,除OOB第六字节外,一般至少把OOB的前3个字节存放Nand Flash硬件ECC码)。

1.为何会出现坏块
因为NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,所以,在NAND的生产中及使用过程当中会产生坏块。坏块的特性是:当编程/擦除这个块时,会形成Page Program和Block Erase操做时的错误,相应地反映到Status Register的相应位。

2.坏块的分类
整体上,坏块能够分为两大类:(1)固有坏块:这是生产过程当中产生的坏块,通常芯片原厂都会在出厂时都会将每一个坏块第一个page的spare area的第6个byte标记为不等于0xff的值。(2)使用坏块:这是在NAND Flash使用过程当中,若是Block Erase或者Page Program错误,就能够简单地将这个块做为坏块来处理,这个时候须要把坏块标记起来。为了和固有坏块信息保持一致,将新发现的坏块的第一个page的 spare area的第6个Byte标记为非0xff的值。

3.坏块管理
根据上面的这些叙述,能够了解NAND Flash出厂时在spare area中已经反映出了坏块信息,所以,若是在擦除一个块以前,必定要先check一下第一页的spare area的第6个byte是不是0xff,若是是就证实这是一个好块,能够擦除;若是是非0xff,那么就不能擦除,以避免将坏块标记擦掉。固然,这样处理可能会犯一个错误―――“错杀伪坏块”,由于在芯片操做过程当中可能因为电压不稳定等偶然因素会形成NAND操做的错误。可是,为了数据的可靠性及软件设计的简单化,仍是须要遵守这个标准。

能够用BBT:bad block table,即坏块表来进行管理。各家对nand的坏块管理方法都有差别。好比专门用nand作存储的,会把bbt放到block0,由于第0块必定是好 的块。可是若是nand自己被用来boot,那么第0块就要存放程序,不能放bbt了。有的把bbt放到最后一块,固然,这一块坚定不能为坏块。bbt的大小跟nand大小有关,nand越大,须要的bbt也就越大。
4.坏块纠正

     ECC:NAND Flash出错的时候通常不会形成整个Block或是Page不能读取或是所有出错,而是整个Page(例如512Bytes)中只有一个或几个bit出 错。通常使用一种比较专用的校验——ECC。ECC能纠正单比特错误和检测双比特错误,并且计算速度很快,但对1比特以上的错误没法纠正,对2比特以上的 错误不保证能检测。
      ECC通常每256字节原始数据生成3字节ECC校验数据,这三字节共24比特分红两部分:6比特的列校验和16比特的行校验,多余的两个比特置1。(512生成两组ECC?)
当往NAND Flash的page中写入数据的时候,每256字节咱们生成一个ECC校验和,称之为原ECC校验和,保存到PAGE的OOB(out- of-band)数据区中。其位置就是eccpos[]。校验的时候,根据上述ECC生成原理不难推断:将从OOB区中读出的原ECC校验和新ECC校验和按位异或,若结果为0,则表示不存在错(或是出现了ECC没法检测的错误);若3个字节异或结果中存在11个比特位为1,表示存在一个比特错误,且可纠正;若3个字节异或结果中只存在1个比特位为1,表示OOB区出错;其余状况均表示出现了没法纠正的错误。
5.补充

(1)须要对前面因为Page Program错误发现的坏块进行一下特别说明。若是在对一个块的某个page进行编程的时候发生了错误就要把这个块标记为坏块,首先就要把块里其余好的 面的内容备份到另一个空的好块里面,而后,把这个块标记为坏块。固然,这可能会犯“错杀”之误,一个补救的办法,就是在进行完块备份以后,再将这个坏块 擦除一遍,若是Block Erase发生错误,那就证实这个块是个真正的坏块,那就绝不犹豫地将它打个“戳”吧!
(2)可能有人会问,为何要使用每一个块第一页的spare area的第六个byte做为坏块标记。这是NAND Flash生产商的默认约定,你能够看到Samsung,Toshiba,STMicroelectronics都是使用这个Byte做为坏块标记的。

(3)为何好块用0xff来标记?由于Nand Flash的擦除便是将相应块的位所有变为1,写操做时只能把芯片每一位(bit)只能从1变为0,而不能从0变为1。0XFF这个值就是标识擦除成功,是好块。

相关文章
相关标签/搜索