nand flash 控制
? ? ? ? ? ? ? NAND?FLASH?模式配置 1.?通过NFCONF?寄存器配置NAND?Flash; 2.?写NAND?Flash?命令到NFCMMD?寄存器; 3.?写NAND?Flash?地址到NFADDR?寄存器; 4.?在读写数据时,通过NFSTAT?寄存器来获得NAND?Flash?的状态信息。应该在读操作前 或写入之后检查R/nB?信号(准备好/忙信号)。 管脚配置 D[7:0]?:?数据/命令/地址/的输入/输出口(与数据总线共享) CLE?:?命令锁存使能(输出) ALE?:?地址锁存使能(输出) nFCE?:?NAND?Flash?片选使能(输出) nFRE?:?NAND?Flash?读使能(输出) nFWE?:?NAND?Flash?写使能(输出) R/nB?:?NAND?Flash?准备好/繁忙(输入) #include"include.h" //#include"uart.c" extern?void?Uart_Printf(char?*fmt,...); extern?void?Uart_Init(int?baud); //extern?void?Uart_Select(int?ch); /* **************************************************************** *函数名称:InitNandCfg *功能描述:?配置?Nandflash *参????数:?void *返?回?值:?void **************************************************************** */ static?void?InitNandCfg(void) { ????/*命令、地址锁存持续时间HCLK,8位总线宽度*/ ????rNFCONF??=?(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0); ????/*不加锁,不加软锁,禁止非法访问中断,关闭忙信号变化中断,检测忙信号的上升沿 ????给空余的区域ecc枷锁,*/ ????rNFCONT??=?(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(0<<1); } static?U32?WaitNFBusy(void) { ????U8?stat; ???? ????WrNFCmd(QUERYCMD);//nand?flash?command?value ????do?{ ????????stat?=?RdNFDat();? ????} ????while?(!(stat&0x40)); ????WrNFCmd(READCMD0); ????return?stat&1; } static?U32?ReadChipId(void) { ????U32?id,k; ???? ????NFChipEn();//片选使能 ?? ????WrNFCmd(RdIDCMD);??//get?the?command?set?register's?value WrNFAddr(0);???????//nand?flash?address?register?=?0 while(NFIsBusy());?//如果忙,则等待 id??=?RdNFDat()<<8;//获得rNFDATA8的数据, ????id?|=?RdNFDat();???//获得rNFDATA8的数据,并得到16位数据 NFChipDs(); ???//nand?flash?controller?disable return?id;???????? } static? U16?ReadStatus(void) { ????U16?stat; ???? ????NFChipEn(); ???? ????WrNFCmd(QUERYCMD); ????stat?=?RdNFDat();?//?get?the?rNFDATA8's?value NFChipDs();???????//?nand?flash?controller?disable return?stat; } /*------------------------------------------------------------/ 函数名称: EraseBlock 功能描述: 擦除?FLASH 传????参: U32?addr 返?回?值: U32?~stat -------------------------------------------------------------*/ U32?EraseBlock(U32?addr) { U8?stat; addr?&=?~0x3f; NFChipEn(); WrNFCmd(ERASECMD0); WrNFAddr(addr); WrNFAddr(addr>>8); WrNFCmd(ERASECMD1); stat?=?WaitNFBusy(); NFChipDs(); return?~stat; } /*------------------------------------------------------------/ 函数名称: ReadPage 功能描述: 传????参: U32?addr,?U8?*buf 返?回?值: 无 -------------------------------------------------------------*/ void?ReadPage(U32?addr,?U8?*buf) { U16?i; NFChipEn(); WrNFCmd(READCMD0); WrNFAddr(0); WrNFAddr(0); WrNFAddr(addr); WrNFAddr(addr>>8); WrNFCmd(READCMD1); InitEcc(); WaitNFBusy(); for(i=0;?i<2048;?i++) buf[i]?=?RdNFDat(); NFChipDs(); } /*------------------------------------------------------------/ 函数名称: WritePage 功能描述: 传????参: U32?addr,?U8?*buf 返?回?值: U32?~stat -------------------------------------------------------------*/ U32?WritePage(U32?addr,?U8?*buf) { U32?i,?mecc; U8?stat,?tmp[7]; NFChipEn(); WrNFCmd(PROGCMD0); WrNFAddr(0); WrNFAddr(0); WrNFAddr(addr); WrNFAddr(addr>>8); InitEcc(); //reset?mecc?and?secc MEccUnlock(); for(i=0;?i<512;?i++) WrNFDat(buf[i]); MEccLock(); mecc?=?RdNFMEcc()); tmp[0]?=?mecc&0xff; ????tmp[1]?=?(mecc>>8)&0xff; ????tmp[2]?=?(mecc>>16)&0xff; ????tmp[3]?=?(mecc>>24)&0xff; ????tmp[5]?=?0xff; //mark?good?block ? WrNFDat(0xff);//2048,坏块标志 SEccUnlock(); WrNFDat(tmp[0]);//ECC校验码 WrNFDat(tmp[1]); WrNFDat(tmp[2]); WrNFDat(tmp[3]); SEccLock(); WrNFCmd(PROGCMD1); stat?=?WaitNFBusy(); NFChipDs(); return?~stat; } /*------------------------------------------------------------/ 函数名称: nandMain 功能描述: 入口函数 传????参: 无 返?回?值: 无 -------------------------------------------------------------*/ void?nand_Main(void)? {? U16?ID,i;? U8?buf[512];? U32?NFBlockNO=6;? U32?NFPagesNO?=?25;? U32?status;? U32?BlockPages; BlockPages?=(NFBlockNO<<6)+NFPagesNO;? Uart_Init(115200);? Uart_Printf("nthe?main?is?runningn");? InitNandCfg();????????????//初始化函数 ID=ReadChipId();//ID=ECf1? Uart_Printf("nnand?flash`s?ID?is:%xn",ID);? ?? ????if(EraseBlock(BlockPages)&0x1==TRUE)? ????{??? Uart_Printf("nblock?%d?is?erasedn",NFBlockNO);? ReadPage(BlockPages,buf);? Uart_Printf("n/***********************擦除之后flash中的数据?****************/n");? for(i=0;?i<512;?i++)? ???????? Uart_Printf("%4x",?buf[i]);? ???????? Uart_Printf("n/***********************应写入数据****************/n");? for(i=0;?i<512;?i++)? {? buf[i]?=?i;? Uart_Printf("%4x",?buf[i]);??? ?? ?? }? ?? ?? ?????? Uart_Printf("nWrite?data[%d?block,?%d?page].n",?NFBlockNO,NFPagesNO);? ?????? status?=?WritePage(BlockPages,buf);?? ??????? ????? if(status&0x1==TRUE?)??? ?????? Uart_Printf("nWrite?OK.n");? ?????? else??? ?????? Uart_Printf("nWrite?Error.n"); ???????? ????? for(i=0;?i<512;?i++)? ???????? buf[i]?=?1;?????????//为验证后边数组中的数据是来自flash ???????? ????????????? ????? ReadPage(BlockPages,buf);? ????? Uart_Printf("nRead?data[%d?block,NFPagesNO);? ????? ????????Uart_Printf("n/***********************?读出的数据?****************/n");? ????????for(i=0;?i<512;?i++)? ???????? Uart_Printf("%4x",?buf[i]);? ????} ???? else Uart_Printf("nblock?%4x?erased?is?badn",NFBlockNO);? while(1);? } 再给主程序命名的时候一定不能够带?"_"?不然会找不到入口的main函数,以为是语法错误,结果才是文件名不对。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |