您好,欢迎访问三七文档
NANDFlash控制器S3C2410板的NandFlash支持由两部分组成:NandFlash控制器(集成在S3C2410CPU)和NandFlash存储芯片(K9F1208U0B)两部分组成。当要访问NandFlash中的数据时,必须通过NandFlash控制器发送命令才能完成。所以NandFlash相当于S3C2410的一个外设,而不位于它的内存地址区.为了支持NANDFlash的启动装载,S3C2410A配置了一个叫Steppingstone的内部SRAM缓冲器。当系统启动时,NANDFlash存储器的前4KB将被自动加载到Steppingstone中,然后系统自动执行这些载入的启动代码。一般情况下,这4KB的启动代码需要将NANDFlash中的内容复制到SDRAM中。使用S3C2410A内部硬件ECC功能可以对NANDFlash的数据进行有效性的检查。复制完成后,将在SDRAM中执行主程序。NANDFlash控制其具有以下特性:*NANDFlash模式:支持读/擦除/编程NANDFlash存储器。*自动启动模式:复位后,启动代码被传送到Steppingstone中。传送完毕后,启动代码在Steppingstone中执行。*具备硬件ECC(校验码:ErrorCorrectionCode)生成模块(硬件生成校验码,通过软件校验)*NANDFlash启动以后,4KB的内部SRAM缓冲器Steppingstone可以作为其他用途使用。*NANDFlash控制器不能通过DMA访问,可以使用LDM/STM指令来代替DMA操作。自启动模式的执行步骤如下:(1)完成复位(2)如果自动启动模式使能,NANDFlash存储器的前4KB自动复制到Steppingstone内部缓冲器;(3)Steppingstone映射到nGCS0;(4)CPU在Steppingstone的4KB内部缓冲器中开始执行启动代码。注意:在自动启动模式下,不进行ECC检测。因此,应确保NANDFlash的前4KB不能有位错误(一般NANDFlash厂家都能确保)。NANDFlash模式需要进行以下配置:(1)通过NFCONF寄存器设置NANDFlash配置;(2)将NANDFlash命令写入NFCONF寄存器;(3)将NANDFlash地址写入NFADDR寄存器;(4)通过NFSTAT寄存器检查NANDFlash状态,并读/写数据。在读操作之前或者编程操作之后应该检查R/nB信号。引脚配置D[7:0]数据/命令/地址的输入/输出口(与数据总线共享)CLE命令锁存使能(输出)ALE地址锁存使能(输出)nFCENANDFlash片选使能(输出)nFRENANDFlash读使能(输出)nFWENANDFlash写使能(输出)R/nBNANDFlash就绪/忙(输入)系统启动和NANDFlash所需的配置如下:(1)OM[1:0]=00b:使能NANDFlash控制器为自动启动模式;(2)NANDFlash存储器的页面大小应该为512字节;(3)NCON:NANDFlash存储器寻址步数选择。0为3步;1为4步寻址。相关寄存器NANDFlash配置寄存器NFCONF地址0x4E000000NANDFlash命令设置寄存器NFCMD地址0x4E000004NANDFlash地址设置寄存器NFADDR地址0x4E000008NANDFlash数据寄存器NFDATA地址0x4E00000CNANDFlash操作状态寄存器NFSTAT地址0x4E000010NANDFlashECC寄存器NFECC地址0x4E000014下面针对三星的K9F1208U0M为例说明nandflash的读写。NANDFlash物理组成正如硬盘的盘片被分为磁道,每个磁道又分为若干扇区,一块nandflash也分为若干block,每个block分为如干page。一般而言,block、page之间的关系随着芯片的不同而不同,典型的分配是这样的:1block=32page1page=512bytes(datafield)+16bytes(oob)需要注意的是,对于flash的读写都是以一个page开始的,但是在读写之前必须进行flash的擦写,而擦写则是以一个block为单位的。按照这种组织方式形成三类地址ColumnAddress:列地址,地址的低8位PageAddress:页地址BlockAddress:块地址8个I/O引脚充当地址、数据、命令的复用端口,所以每次传地址只能传8位,而nandfalsh的地址位位26位,因此读写一次nandflash需要传送4次(A[7:0]A[16:9]A[24:17]A[25]一页有528B,在每一页中,最后16个字节(OOB)用于nandflash执行完命令后设置状态用的,剩余512B又分为前半部(1sthalfPageRegister)和后半部(2ndhalfPageRegister)。可以通过nandflash命令对1sthalf和2ndhalf以及OOB进行定位通过nandflash内置的指针指向各自的首地址存储操作特点:1.擦除操作的最小单位是块2.NandFlash芯片每一位只能从1变为0,而不能从0变为1,所以在对其进行写入操作之前一定要将相应块擦除(擦除就是将相应块的位全部变为13OOB部分的第六字节(即517字节)标志是否坏块,如果不是坏块该值为FF,否则为坏块4除OOB第六字节外,通常至少把OOB前3字节存放NandFlash硬件ECC码NANDFlash寻址方式512byte需要9bit来表示,对于528byte系列的NAND,这512byte被分成1sthalfPageRegister和2ndhalfPageRegister,各自的访问由地址指针命令来选择,A[7:0]就是所谓的columnaddress(列地址),在进行擦除操作时不需要列地址,为什么?因为以块为单位擦除。32个page需要5bit来表示,占用A[13:9],即该page在块内的相对地址。A8这一位地址被用来设置512byte的1sthalfpage还是2ndhalfpage,0表示1st,1表示2nd。Block的地址是由A14以上的bit来表示。例如64MB(512Mb)的NANDflash(实际中由于存在sparearea,故都大于这个值),共4096block,因此,需要12个bit来表示,即A[25:14],如果是128MB(1Gbit)的528byte/page的NANDFlash,则blockaddress用A[26:14]表示。由于地址只能在I/O[7:0]上传递,因此,必须采用移位的方式进行。以NAND_ADDR为例:第1步是传递columnaddress,就是NAND_ADDR[7:0],不需移位即可传递到I/O[7:0]上,而halfpagepointer即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-stepaddressing。如果NANDFlash的容量是32MB(256Mbit)以下,那么,blockadress最高位只到bit24,因此寻址只需要3步。Nandflash主要的内设命令Nandflash命令执行是通过将命令字送到Nandflash控制寄存器的命令寄存器中来执行的,其命令是分周期执行的,每条命令都有一个或多个执行周期,每个执行周期都有相应的代码表示将要执行的动作。功能第一时钟周期第二时钟周期读取数据寄存器Read100h/01h读取数据寄存器下半区(OOB)Read250h读取芯片ID90hRESETFFh写页面(pageprogram)(首先写入00h(A区)/01h(B区)/05h(C区)表示写入区;再写入80h开始编程模式(写入模式),接下80h10h来写入地址和数据,最后写入10h表示编程结束。块擦除(blockerase)60hD0h读取状态(readstatus)70hNandFlash地址的计算ColumnAddress:列地址。ColumnAddress其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。PaageAddress:页地址。由于页地址总是以512Bytes对齐的,所以它的低9位总是0。确定读写操作是在Flash上的哪个页进行的。当我们得到一个NandFlash地址srcaddr时候,我们可以这样分解出ColumnAddress和PageAddresscolumnaddr=srcaddr%512//columnaddresspageaddr=srcaddr9//pageaddress也可以这么认为,一个NandFlash地址的A0~A7是它的column_addr,A9~A25是它的PageAddress。(注意地址位A8并没有出现,也就是A8被忽略,在下面你将了解到这是什么原因)以read1命令为例:Read1命令的操作分为4个Cycle,发送完读命令00h或01h(00h与01h的区别请见下文描述)之后将分4个Cycle发送参数,1st.Cycle是发送ColumnAddress。2nd.Cycle,3rd.Cycle和4th.Cycle则是指定PageAddress(每次向地址寄存器发送的数据只能是8位,所以17位的PageAddress必须分成3次进行发送Read1的命令里面出现了两个命令选项,分别是00h和01h。这里出现了两个读命是否令你意识到什么呢?是的,00h是用于读写1sthalf的命令,而01h是用于读取2ndhalf的命令。现在我可以结合上图给你说明为什么K9F1208U0B的DataField被分为2个half了。如上文所提及的,Read1的1st.Cycle是发送ColumnAddress,假设我现在指定的ColumnAddress是0,那么读操作将从此页的第0号Byte开始一直读取到此页的最后一个Byte(包括SpareField),如果我指定的ColumnAddress是127,情况也与前面一样,但不知道你发现没有,用于传递ColumnAddress的数据线有8条(I/O0~I/O7,对应A0~A7,这也是A8为什么不出现在我们传递的地址位中),也就是说我们能够指定的ColumnAddress范围为0~255,但不要忘了,1个Page的DataField是由512个Byte组成的,假设现在我要指定读命令从第256个字节处开始读取此页,那将会发生什么情景?我必须把ColumnAddress设置为256,但ColumnAddress最大只能是255,这就造成数据溢出。。。正是因为这个原因我们才把DataField分为两个半区,当要读取的起始地址(ColumnAddress)在0~255内时我们用00h命令,当读取的起始地址是在256~511时,则使用01h命令.假设现在我要指定从第256个byte开始读取此页,那么我将这样发送命令串column_addr=256;NF_CMD=0x01;ß从2ndhalf开始读取NF_ADDR=column_addr&0xff;1stCycleNF_ADDR=page_address&0xff;2nd.CycleNF_ADDR=(page_address8)&0xff;3rd.CycleNF_ADDR=(page_address16)&0xff;4th.Cycle其中NF_CMD和NF_ADDR分别是NandFlash的命令寄存器和地址寄存器的地址解引用,我一般这样定义它们,#definerNFCMD(*(volatileunsignedchar*)0x4e000004)//NADD
本文标题:nandflash
链接地址:https://www.777doc.com/doc-5594325 .html