第一节概论 nandflash在对大容量的数据存储中发挥着重要的作用。相对于norflash,它具有一些优势,但它的一个劣势是很容易产生坏块,因此在使用nandflash时,往往要利用校验算法发现坏块并标注出来,以便以后不再使用该坏块。nandflash没有地址或数据总线,如果是8位nandflash,那么它只有8个IO口,这8个IO口用于传输命令、地址和数据。nandflash主要以page(页)为单位进行读写,以block(块)为单位进行擦除。每一页中又分为main区和spare区,main区用于正常数据的存储,spare区用于存储一些附加信息,如块好坏的标记、块的逻辑地址、页内数据的ECC校验和等。 s3c2440内部集成有内部sram(steppingstone),当选择从nand flash启动的时候,nand flash的前4k代码将会自动copy到内部sram中后运行。 (一)nand flash控制器的特性: 1、支持读/写/编程 NAND FLASH内存 2、系统复位后nand flash的前4k代码自动copy到内部sram,copy完 成后从sram启动,此时内部sram被映射为nGCS0。(当OM[1:0]= 00时使能NAND FLASH 启动模式) 3、支持硬件ECC校验 4、系统启动后内部ram可以用做其他的用途。 (二)操作nand flash方法 1、设置nand flash配置寄存器NFCONF 2、向命令寄存器NFCMD写入操作命令 3、向地址寄存器NFADDR写入地址 4、读/写数据前要读取状态寄存器NFSTAT来判断nand flash是否处于忙状态。 (三)ECC奇偶检验 S3C2440在读/写操作时,自动生成2048字节的奇偶校验码。 nand flash的页为2048B。在读写的时候每页会产生4个bit大小的ECC校验码。 28bit ECC校验码=22bit 线校验码+6bit列校验码 ECC产生模块执行以下步骤: 1:当MCU写数据到NAND时,ECC产生模块生成ECC码。 2:当MCU从NAND读数据时,ECC产生模块生成ECC码同时用户程序将它与先前写入时产生的ECC码作比较。 在自动引导模式下,不进行ECC检测。因此,NAND FLASH的前4KB应确保不能有位错误(一般NAND FLASH厂家都确保)。 (四)坏块管理 由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块。坏块的特性是:当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program和Block Erase操作时的错误,相应地反映到Status Register的相应位。 (1) 固有坏块,这是生产过程中产生的坏块,一般芯片原厂都会在出厂时都会将坏块第一个page的spare area的第6个bit标记为不等于0xff的值。 (2) 使用坏块,这是在NAND Flash使用过程中,如果Block Erase或者Page Program错误,就可以简单地将这个块作为坏块来处理,这个时候需要把坏块标记起来。为了和固有坏块信息保持一致,将新发现的坏块的第一个page的 spare area的第6个Bit标记为非0xff的值。 (3)坏块管理 根据上面的这些叙述,可以了解NAND Flash出厂时在spare area中已经反映出了坏块信息,因此,如果在擦除一个块之前,一定要先check一下spare area的第6个bit是否是0xff,如果是就证明这是一个好块,可以擦除;如果是非0xff,那么就不能擦除。 当然,这样处理可能会犯一个错误―――“错杀伪坏块”,因为在芯片操作过程中可能由于电压不稳定等偶然因素会造成NAND操作的错误。但是,为了数据的可靠性及软件设计的简单化,我们就要奉行“蒋委员长”的“宁可错杀一千,也决不放过一个”的宗旨。 (4)需要对前面由于Page Program错误发现的坏块进行一下特别说明。如果在对一个块的某个page进行编程的时候发生了错误就要把这个块标记为坏块,首先就要把其他好的page里面的内容备份到另外一个空的好块里面,然后,把这个块标记为坏块。 当然,这可能会犯“错杀”之误,一个补救的办法,就是在进行完页备份之后,再将这个块擦除一遍,如果Block Erase发生错误,那就证明这个块是个真正的坏块,那就毫不犹豫地将它打个“戳”吧! (2)可能有人会问,为什么要使用spare area的第六个bit作为坏块标记。这是NAND Flash生产商的默认约定。 第二节 NAND寄存器设置说明 对NAND数据的读写主要通过NAND寄存器来实现,下面介绍其主要的寄存器 一、NFCONF寄存器 TACLS [13:12] TACLS持续时间设置, 取值范围0~3,hclk*tacls twrph0 [10:8] twrph0持续时间设置,取值范围0~7 ,hclk*(twrph0+1) twrph1 [6:4] twrph1持续时间设置,取值范围0~7 ,hclk*(twrph1+1) Advflash(只读) [3] CPU自动加载NAND前4K内容时 此位在系统复位或唤醒期间被NCON0引脚决定 0:256/512页大小 1:1024/2048页大小 Pagesize(只读) [2] CPU自动加载NAND前4K内容时 当Advflash=0 0:256 1:512 当Advflash=1 0:1024 1:2048 此位在系统复位或唤醒期间被GPG13引脚决定启用后GPG13可以作为常规端口或外部中断输入使用 addrCycle(只读) [1] CPU自动加载NAND前4K内容时 当Advflash=0 0:3个周期 1:4个周期 当Advflash=1 0:4个周期 1:5个周期 此位在系统复位或唤醒期间被GPG14引脚决定 启用后GPG14可以作为常规端口或外部中断输入使用 Buswidth(读/写) [0] CPU自动加载NAND前4K内容时和常规读取时总线宽度 0:8bit 1:16bit 此位在系统复位或唤醒期间被GPG15引脚决定 启用后GPG15可以作为常规端口或外部中断输入使用 查看该寄存器定义,我们主要对NAND时序参数TACLS、TWRPH0、TWRPH1进行设置,这三个参数见下面时序图 TA CL S:表示CLE/ALE命令地址锁定信号建立后到nWE信号建立时间(setup time)。 TWRPH0:表示nWE的持续时间。 TWRPH1:表示nWE锁存结束后CLE/ALE维持时间(hold time)。 下面,我们看看K9F2G08时序时间,因为HCLK为100MHZ,所以一个clock为10ns 根据上面时序时间,我们可以保守取值TACLS=1,TWRPH1=0,TWRPH0=twp=4 ldr r0,=NFCONF ldr r1,=(1<<12)|(4<<8)|(0<<4)|(0<<0);表8位I/O端口 strh r1,[r0] 二、NFCONT寄存器 Lock-tight [13] Lock-tight配置 0:禁止1:启用 以前,此位设置为1,不能清除,唯一在复位和唤醒时能够使此位无效(软件不能清除) 当设置为1时,范围为NFSBLK(0X4E000038)到NFEBLK(0X4E00003C)-1不被锁定,在这范围之外,写和擦除命令是无效,只有读命令是允许的。 当你试图写或擦除锁定区域,违规存取将发生,NFSTAT[3]被设置 NFSBLK和NFEBLK相同,全部区域将被锁定 Soft-lock [12] Soft-lock配置 0:禁止1:启用 软件锁定能在任何时间被软件修改 当设置为1时,范围为NFSBLK(0X4E000038)到NFEBLK(0X4E00003C)-1不被锁定,在这范围之外,写和擦除命令是无效,只有读命令是允许的。 当你试图写或擦除锁定区域,违规存取将发生,NFSTAT[3]被设置 NFSBLK和NFEBLK相同,全部区域将被锁定 EnblllegalAccInt [10] 0:禁止1:允许中断 当CPU试图编程或擦除锁定区域时(NFSBLK(0X4E000038)到NFEBLK(0X4E00003C)-1) EnbRnBINT [9] RnB状态输入信号转换成中断信号 0:禁止1:允许 RnB_TransMode [8] RnB转换检测信号设置 0:上升沿 1:下除沿 Reserved [7] 保留 SpareECCLock [6] 锁定SPARE纠码区域 0:不锁定1:锁定 备用纠码区域状态在NFSECC(0x4e000034)同下 ManiECCLock [5] 锁定MAIN纠码区域 0:不锁定 1:锁定 主纠码区域状态在NFMECC0/1(0X4E00002C/30)(即当启用ECC功能及锁定ECC时,数据产生的ECC奇偶码存放在NFMECC0/1寄存器中) InitECC [4](只写) 初始化ECC编码器 1:初始化ECC编码器 Reserved [3:2] 保留 Reg_nCE [1] NAND Flash nFCE信号控制 0:强制nFCE信号为低:(允许片选信号) 1:强制nFCE信号为高:(禁止片选信号) 在启动期间,其值自动控制 其值在MODE位为1时有效 MODE [0] NAND Flash操作模式 0:不使用 1:使用 ldr r0,=NFCONT ldr r1,=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0) strh r1,[r0] 锁定MAIN及SPACE区域ECC,初始化ECC,启用NAND功能,禁止片选信号 三、NFCMD寄存器 NAND命令设置寄存器 Reserved [15:8] 保留 NFCMMD [7:0] NAND控制命令值 四、NFADDR寄存器 NAND地址设置寄存器 Reserved [15:8] 保留 NFADDR [7:0] NAND地址设置值 五、NFDATA寄存器 NAND数据读写寄存器 NFDATA [31:0] NAND读或编程数据 六、NFSTAT寄存器 NAND操作状态寄存器 Reserved [7:4] 保留, IIIegalAccess [3] 一旦软件锁定或LOCK-tight使能? RnB_TransDetect [2] 当RnB由低向高电平转变是,该位被设置并发出中断,如果中断允许,要清除该位向该位写1 0:电平转换未检测 1:电平转换检测 Nce(只读) [1] NCE输出信号状态 RNB(只读) [0] Rnb输入信号状态 0:NAND状态正忙 1:NAND状态准备好操作 第三节K9F2G08NAND编程 TQ2440是三星生产的K9F2G08,容量为256MB。下观就以它为例进行介绍。 该芯片为48引脚,有三种封装,其外围引脚较少,这样就方便和S3C2440的硬件连接,即方便设计电路,又可以减少占用总线资源。具体的引脚见手册的第8页, X-Buffers Latches & Decoders:用于产生行地址; ? Y-Buffers Latches & Decoders:用于产生列地址; ? Command Register:用于命令字的操作; ? Control Logic & High Voltage Generator:控制逻辑及产生Flash所需的高压; ? Nand Flash Array:存储部件; ? Page Register & S/A :页寄存器,当读、写页时,会将数据先读入或写入此寄存器,大小为2048+64 B。 下图为NAND FLASH的存储单元组织结构图: K9F2G08容量为256MB,分为131072行(页),2112 x 8列。每页大小为2048字节,另外有64字节的额外空间,这64字节的空间的列地址为2048—2111。 命令、地址、数据都通过8个I/O口输入/输出,这种形式减少了芯片的引脚个数,并使得系统很容易升级到更大的容量,写入命令、地址或数据时,都需要将WE#、CE#信号同时拉低。数据在WE#信号的上升沿被锁存,其中CLE为命令锁存信号、ALE为地址锁存信号。整个芯片为(256+8)MB,因此,需要29根地址线来寻址,这样,如果我们以字节为单位发出寻址信号,总共需要5个周期,其中2周期列地址信号,3周期的行地址信号。见下图。 地址疑惑:我们知道,K9F2G08容量为256M,故其需要28位地址进行寻址,每一页容量为2K,需11位地址,共有131072行,需要地址17位,页和行地址相加为28位正好寻址256M,,而上表中用的地址为29位,再看看页地址[A0~A11]12位,可寻址空间为4K,行地址[A12~A28]17位,可寻址空间为131072行,显然页地址多出一位,其寻址空间扩大了一倍。当我们考虑地址[0x800=2048=1000 0000 0000]寻址时,由于一页大小为2048,其地址范围为[0~2047],0x800应为第一页第一个字节。其列地址为0,行地址为1(A11为行地址第一个位)。但当我们按上表分析该地址时,其列地址为0x800(2048)行地址为0,那么该地址读取的数据为第0页第2048个字节(即SPACE区域的第一个字节),显然问题的关键在A11上,也就是说当A11为1时,我们寻址空间为页2048~2111(共64字节)。通过实际检验,可以断定,我们地址addr[11]应为行地址第一位,读取Main页地址(0~2047)范围内时,A11必须置0,访问space区域时,A11必须置1,由我们根据需要决定,不从地址中取值,故行地址应从a[11]位开始。 2、操作命令字介绍 操作NAND FLASH时,先传输命令,接着输出地址,最后读/写数据,期间还要检查FLASH的状态。具体的命令字见下表。