第一节概论
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的状态。具体的命令字见下表。