S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A)
(3)使用CVAVR中的编程下载程序时应特别注意,由于CVAVR编程下载界面初始打开时,大部分熔丝位的初始状态定义为“1”,因此不要使用其编程菜单选项中的“all”选项。此时的“all”选项会以熔丝位的初始状态定义来配置芯片的熔丝位,而实际上其往往并不是用户所需要的配置结果。如果要使用“all”选项,应先使用“read-> for(i=5;i> for(k=150;k> for(j=4;j> 定的(比如说K9F2G08U0A的配置为NCON、GPG13和GPG14接高电平,GPG15接低电平,所以[3:0]位状态应该是1110)。 (2)NFCONT:用来使能/禁止NAND Flash控制器、使能/禁止控制引脚信号nFCE、初始化ECC。它还有其他功能,在一般的应用中用不到,比如锁定NAND Flash。 (3)NFCMMD:对于不同型号的Flash,操作命令一般不一样。参考前面介绍的K9F2G08U0A命令序列。 (4)NFADDR:当写这个寄存器时,它将对Flash发出地址信号。只用到低8位来传输,所以需要分次来写入一个完整的32位地址,K9F2G08U0A的地址序列在图4已经做了详细说明。 (5)NFDATA:只用到低8位,读、写此寄存器将启动对NAND Flash的读数据、写数据操作。 (6)NFSTAT:只用到位0,用来检测NAND是否准备好。0:busy,1:ready。 NFCONF寄存器使用TACLS、TWRPH0、TWRPH1这3个参数来控制NAND Flash信号线CLE/ALE与写控制信号nWE的时序关系,它们之间的关系如图6和图7所示: 图6 CLE/ALE时序图 图7 nWE和nRE时序图 TACLS为CLE/ALE有效到nWE有效之间的持续时间,TWRPH0为nWE的有效持续时间,TWRPH1为nWE无效到CLE/ALE无效之间的持续时间,这些时间都是以HCLK为单位的。通过查阅K9F2G08U0A的数据手册,我们可以找到并计算与S3C2440相对应的时序:K9F2G08U0A中的Twp与TWRPH0相对应,Tclh与TWRPH1相对应, TACLS应该是与Tcls相对应。K9F2G08U0A给出的都是最小时间, 2440只要满足它的最小时间即可。TACLS、TWRPH0、TWRPH1这三个变量取值大一些会更保险,在这里,这三个值分别取1,2和0。 下面就开始详细介绍K9F2G08U0A的基本操作,包括复位,读ID,页读、写数据,随意读、写数据,块擦除等。 为了更好地应用ECC和使能Nand Flash片选,我们还需要一些宏定义: #define NF_nFCE_L(){rNFCONT &= ~(1<1); } #define NF_CE_L()NF_nFCE_L()//打开nandflash片选 #define NF_nFCE_H(){rNFCONT |= (1<1); } #define NF_CE_H() NF_nFCE_H() //关闭nandflash片选 #define NF_RSTECC(){rNFCONT |= (1<4); }//复位ECC #define NF_MECC_UnLock(){rNFCONT &= ~(1<5); }//解锁main区ECC #define NF_MECC_Lock(){rNFCONT |= (1<5); }//锁定main区ECC #define NF_SECC_UnLock() {rNFCONT &= ~(1<6); }//解锁spare区ECC #define NF_SECC_Lock(){rNFCONT |= (1<6); }//锁定spare区ECC NFSTAT是另一个比较重要的寄存器,它的第0位可以用于判断nandflash是否在忙,第2位用于检测RnB引脚信号: #define NF_WAITRB(){while(!(rNFSTAT&(1<0)));} //等待Nand Flash不忙 #define NF_CLEAR_RB(){rNFSTAT |= (1<2); }//清除RnB信号 #define NF_DETECT_RB(){while(!(rNFSTAT&(1<2)));} //等待RnB信号变高,即不忙 NFCMMD,NFADDR和NFDATA分别用于传输命令,地址和数据,为了方便起见,我们可以定义一些宏定义用于完成上述操作: #define NF_CMD(data) {rNFCMD = (data); }//传输命令 #define NF_ADDR(addr){rNFADDR = (addr); }//传输地址 #define NF_RDDATA() rNFDATA) //读32位数据 #define NF_RDDATA8()(rNFDATA8)//读8位数据 #define NF_WRDATA(data){rNFDATA = (data); }//写32位数据 #define NF_WRDATA8(data) {rNFDATA8 = (data); }//写8位数据 首先,是初始化操作 void rNF_Init(void) { rNFCONF = (TACLS<12)|(TWRPH0<8)|( TWRPH1<4)|(0<0);//初始化时序参数 rNFCONT = (0<13)|(0<12)|(0<10)|(0<9)|(0<8)|(1<6)|(1<5)|(1<4)|(1<1)|(1<0); //非锁定,屏蔽nandflash中断,初始化ECC及锁定main区和spare区ECC,使能nandflash片选及控制器 rNF_Reset();//复位芯片 } 复位操作,写入复位命令 static void rNF_Reset() { NF_CE_L();//打开nandflash片选 NF_CLEAR_RB();//清除RnB信号 NF_CMD(CMD_RESET); //写入复位命令 NF_DETECT_RB();//等待RnB信号变高,即不忙 NF_CE_H();//关闭nandflash片选 } 读取K9F2G08U0A芯片ID的操作如下:时序图在datasheet的figure18。首先需要写入读ID命令(0x90),然后再写入0x00地址,并等待芯片就绪,就可以读取到一共五个周期的芯片ID,第一个周期为厂商ID,第二个周期为设备ID,第三个周期至第五个周期包括了一些具体的该芯片信息,函数如下 static char rNF_ReadID() { char pMID; char pDID; char cyc3, cyc4, cyc5; NF_nFCE_L();//打开nandflash片选 NF_CLEAR_RB();//清RnB信号 NF_CMD(CMD_READID);//读ID命令 NF_ADDR(0x0); //写0x00地址 for ( i = 0; i < 100; i++ );等一段时间 //读五个周期的ID pMID = NF_RDDATA8();//厂商ID:0xEC pDID = NF_RDDATA8();//设备ID:0xDA cyc3 = NF_RDDATA8();//0x10 cyc4 = NF_RDDATA8();//0x95 cyc5 = NF_RDDATA8();//0x44 NF_nFCE_H();//关闭nandflash片选 return (pDID); } 下面介绍Nand Flash读操作,读操作是以页为单位进行的。如果在读取数据的过程中不进行ECC校验判断,则读操作比较简单,在写入读命令的两个周期之间写入要读取的页地址,然后读取数据即可。如果为了更准确地读取数据,则在读取完数据之后还要进行E

S3C2440NandFlashK9F2G08U0 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
