/**********************按键实验*********************************/
/***************************************************************/
/* ? ? ? ? 本实验接口说明 */ #include?"include.h"
/*-----------------------函数声明----------------------------*/ void InitNandFlash(int info); void cpy_bpage(void); void add_bpage(unsigned int seq);
extern void Uart_Printf(char *fmt,...); extern void Uart_Init(int baud); extern void Uart_Select(int ch);
/*------------------------------------------------------------/ 函数名称:? ? ? ? InitNandCfg 功能描述:? ? ? ? 配置flash 传? ? 参:? ? ? ? 无 返 回 值:? ? ? ? 无 -------------------------------------------------------------*/ static void InitNandCfg(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); ? ? ? ? // }
/*------------------------------------------------------------/ 函数名称:? ? ? ? WaitNFBusy 功能描述:? ? ? ?? 传? ? 参:? ? ? ? 无 返 回 值:? ? ? ? static U32 stat&1 -------------------------------------------------------------*/ static U32 WaitNFBusy(void)? ? ? ? // 等待nand flash 的操作结束 { ? ? ? ? U8 stat;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //因为nansh flash数据通道只有8bit ? ? ? ?? ? ? ? ? WrNFCmd(QUERYCMD);? ? ? ? ? ? ? ? //QUERYCMD=0X70,将0x70写入NFCMD ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //查看nand flash芯片的资料中的Command Sets ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //0x70表示读nand flash的状态 ? ? ? ? do? ? ? ? ? { ? ? ? ? ? ? ? ? stat = RdNFDat();? ? ? ? //上面命令是读nandflash的状态,因此RdNFDat获得的是nandflash的状态。 ? ? ? ? } ? ? ? ? while (!(stat&0x40));? ? ? ? //[6] busy:0??ready:1 ? ? ? ? WrNFCmd(READCMD0);? ? ? ? ? ? ? ? //READCMD0=0 ? ? ? ? return stat&1;? ? //注意0为操作成功.见datasheet34页表。 }
/*------------------------------------------------------------/ 函数名称:? ? ? ? ReadChipId 功能描述:? ? ? ? 读flash ID 传? ? 参:? ? ? ? 无 返 回 值:? ? ? ? static U32 id -------------------------------------------------------------*/ // 读ID过程的时序图在K9F1G08U0A的datasheet中,第28和35页// static U32 ReadChipId(void) {? ? ? ?? ? ? ? ? U32 id,k; ? ? ? ?? ? ? ? ? NFChipEn();? ? ? ? //选中nandflash ? ? ? ? WrNFCmd(RdIDCMD);//读ID命令 ? ? ? ? WrNFAddr(0);? ? ? ? //写入00h(根据datasheet) ? ? ? ? while(NFIsBusy());? ? ? ? //等待前一步完成 ? ? ? ? id??= RdNFDat()<<8;? ? ? ? //define中规定:RdNFDat8(); for 8 bit nand flash,use byt access ? ? ? ? for(k=0;k<500;k++);? ? ? ? // ? ? ? ? id |= RdNFDat();? ? ? ? //从运行结果ID:ecda来看,可能是这边程序有点问题(ID指什么不明确) ? ? ? ? NFChipDs();? ? ? ? ? ? ? ?? ? ? ? ?? ? ? ? ? return id; }
/*------------------------------------------------------------/ 函数名称:? ? ? ? ReadStatus 功能描述:? ? ? ? 读FLASH状态 传? ? 参:? ? ? ? 无 返 回 值:? ? ? ? static U16 stat -------------------------------------------------------------*/ static U16 ReadStatus(void) { ? ? ? ? U16 stat; ? ? ? ?? ? ? ? ? NFChipEn();? ? ? ?? ? ? ? ? WrNFCmd(QUERYCMD);? ? ? ? ? ? ? ?? ? ? ? ? stat = RdNFDat();? ? ? ?? ? ? ? ? NFChipDs(); ? ? ? ?? ? ? ? ? return stat; }
/*------------------------------------------------------------/ 函数名称:? ? ? ? EraseBlock 功能描述:? ? ? ? 擦除 FLASH 传? ? 参:? ? ? ? U32 addr 返 回 值:? ? ? ? U32 ~stat -------------------------------------------------------------*/ //? ?? ?? ?地址输入(两个周期) datasheet第27页? ?? ? // U32 EraseBlock(U32 addr) { ? ? ? ? U8 stat;
? ? ? ? addr &= ~0x3f;? ? ? ? ? ? ? ? ? ? ? ? //addr=0000 0001 1000 0000 ? ? ? ? ? ? ? ?? ? ? ? ? NFChipEn();? ? ? ?? ? ? ? ? WrNFCmd(ERASECMD0);? ? ? ? ? ? ? ? //ERASECMD0=0X60 ? ? ? ? WrNFAddr(addr);? ? ? ? ? ? ? ? ? ? ? ? //cycle1:8bit?address=1000 0000 ? ? ? ? WrNFAddr(addr>>8);? ? ? ? ? ? ? ? //cycle2:8bit address=0000 0001 ? ? ? ? WrNFCmd(ERASECMD1);? ? ? ? ? ? ? ? //ERASE confirm cmd ? ? ? ? stat = WaitNFBusy();? ? ? ? //等待擦除完成 ? ? ? ? NFChipDs(); ? ? ? ?? ? ? ? ? return ~stat; }
/*------------------------------------------------------------/ 函数名称:? ? ? ? ReadPage 功能描述:? ? ? ?? 传? ? 参:? ? ? ? U32 addr,U8 *buf 返 回 值:? ? ? ? 无 -------------------------------------------------------------*/ //? ? ? ? ? ? ? ? 读取block6中的page25? ?参考datasheet30页? ? ? ???? ? ? ? // void ReadPage(U32 addr,U8 *buf) { ? ? ? ? U16 i; ? ? ? ?? ? ? ? ? NFChipEn(); ? ? ? ? WrNFCmd(READCMD0);? ? ? ? ? ? ? ? //READCMD0=0 ? ? ? ? WrNFAddr(0);? ? ? ? ? ? ? ? ? ? ? ? // ? ? ? ? WrNFAddr(0);? ? ? ? ? ? ? ? ? ? ? ? //因为读的是一个page,所以col addr=0 ? ? ? ? WrNFAddr(addr);? ? ? ? ? ? ? ? ? ? ? ? // ? ? ? ? WrNFAddr(addr>>8);? ? ? ? ? ? ? ? //block6,page25的地址 ? ? ? ? WrNFCmd(READCMD1);? ? ? ? ? ? ? ? //READCMD1=0X30 ? ? ? ? InitEcc();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //初始化ECC ? ? ? ? WaitNFBusy();? ? ? ? ? ? ? ? ? ? ? ? // ? ? ? ? for(i=0; i<2048; i++) ? ? ? ? ? ? ? ? buf?= RdNFDat();? ? ? ? //将2k的内容读出 ? ? ? ? NFChipDs(); }
/*------------------------------------------------------------/ 函数名称:? ? ? ? WritePage 功能描述:? ? ? ?? 传? ? 参:? ? ? ? U32 addr,U8 *buf 返 回 值:? ? ? ? U32 ~stat -------------------------------------------------------------*/ /*【Nand Flash中的特殊硬件结构】 1.页寄存器(Page Register):由于Nand Flash读取和编程操作 来说,一般最小单位是页,所以,nand flash在硬件设计时候,就考虑到 这一特性,对于每一片,都有一个对应的区域,专门用于存放,将要写入 到物理存储单元中去的或者刚从存储单元中读取出来的,一页的数据,这 个数据缓存区,本质上就是一个buffer,但是只是名字叫法不同,datasheet 里面叫做data Register,实际理解为页缓存,大小应该是等于1个page 恰当些。而正是因为有些人不了解此内部结构,才容易产生之前遇到的某人 的误解,以为内存里面的数据,通过Nand Flash的FIFO,写入到Nand Flash 里面去,就以为立刻实现了实际数据写入到物理存储单元中了。而实际上, 只是写到了这个页缓存中,只有等你发了对应的编程第二阶段的确认命令0x10 之后,实际的编程动作才开始,才开始把页缓存中的数据,一点点写到物理存 储单元中去。*/ //? ? ? ? ? ? ? ? ? ? ? ? 参考datasheet的第23页? ? ? ? ? ? ? ? ? ? ? ? // U32 WritePage(U32 addr,U8 *buf) { ? ? ? ? U32 i,mecc; ? ? ? ? U8 stat,tmp[7]; ? ? ? ?? ? ? ? ?? ? ? ? ? NFChipEn();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // ? ? ? ? WrNFCmd(PROGCMD0);? ? ? ? ? ? ? ? //page program 命令? ? ? ?? ? ? ? ? WrNFAddr(0);? ? ? ? ? ? ? ? ? ? ? ? //? ? ? ?? ? ? ? ? WrNFAddr(0);? ? ? ? ? ? ? ? ? ? ? ? //? ? ? ?? ? ? ? ? WrNFAddr(addr);? ? ? ? ? ? ? ? ? ? ? ? // ? ? ? ? WrNFAddr(addr>>8);? ? ? ? ? ? ? ? //要写入的page地址? ? ? ??
? ? ? ? InitEcc();? ? ? ? //reset mecc and secc ? ? ? ? MEccUnlock();? ? ? ? ? ? ? ? ? ? ? ? //unlock main data area ecc generation ? ? ? ? for(i=0; i<512; i++)? ? ? ? //具体要写入页的数据写入main data area ? ? ? ? ? ? ? ? WrNFDat(buf);? ? ? ? //将数据输入NAND FLASH的data register中 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //或者可以理解为写入page的缓冲区 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //只有在发送确认命令0x10之后,该内容才被写入物理存储单元。 ? ? ? ? MEccLock();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //unlock it ? ? ? ? mecc = RdNFMEcc();? ? ? ? ? ? ? ? //mecc赋值等于MAIN DATA AREA ECC0 STATUS ERGISTER的内容? ? ? ?? ? ? ? ? ? ? ? ?? ? ? ? ? tmp[0] = mecc&0xff;? ? ? ? ? ? ? ? //[7:0] ? ? tmp[1] = (mecc>>8)&0xff;//[15:8] ? ? tmp[2] = (mecc>>16)&0xff;//[23:16] ? ? tmp[3] = (mecc>>24)&0xff;//[31:24] ? ? tmp[5] = 0xff;? ? ? ? //mark good block
? ? ? ?? ? ? ? ???? ? ? ?? ? ? ? ? ? ? ? ? //WrNFDat(0xff);? ? ? ? //2048,坏块标志//此时主数据区已经lock了。如果不等于0xff就说明是坏块 ? ? ? ?? ???? ? ? ? ? ? ? ? ? ? ? ?? ?? ? ? ? //sumsung规定在block第一和第二个page的spare area的第一个字节,如果不等于0xff就说明是坏块。 ? ? ? ?? ???SEccUnlock();? ? ? ? //校验码写入spare data area ? ? ? ? ? ? ? ? WrNFDat(0xff);? ? ? ? //改到这里来运行也一样,应该是没做坏块的判断吧? ? ? ? ? ? ? ? ? WrNFDat(tmp[0]);//ECC校验码 ? ? ? ? ? ? ? ? WrNFDat(tmp[1]); ? ? ? ? ? ? ? ? WrNFDat(tmp[2]); ? ? ? ? ? ? ? ? WrNFDat(tmp[3]);//同上,也在页缓冲区 ? ? ? ? ? ? ? ? SEccLock();
? ? ? ? WrNFCmd(PROGCMD1);? ? ? ? //确认命令,将以上数据写入物理存储器 ? ? ? ? stat = WaitNFBusy(); ? ? ? ? NFChipDs(); ? ? ? ?? ? ? ? ? return ~stat; ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ?? }
/*------------------------------------------------------------/ 函数名称:? ? ? ? nandMain 功能描述:? ? ? ? 入口函数 传? ? 参:? ? ? ? 无 返 回 值:? ? ? ? 无 -------------------------------------------------------------*/ void nandMain(void)? {? ? ? ? ? U16 ID,i;? ? ? ? ? U8 buf[512];? ? ? ? ? U32 NFBlockNO=6;? ? ? ? ? U32 NFPagesNO = 25; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //block6,page25 ? ? ? ? U32 status;? ? ? ? ? U32 BlockPages;
? ? ? ? BlockPages =(NFBlockNO<<6)+NFPagesNO; ? ? ? ? //BlockPages=000110011001 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //左移6位是因为1Block=64Page ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //因此block6的起始地址位:6*64=6<<6
? ? ? ? Uart_Init(115200);? ? ? ? ? Uart_Printf("nthe main is runningn");?
? ? ? ? InitNandCfg();? ?? ?? ?? ?? ? ? ? //初始化函数 ? ? ? ? ID=ReadChipId();? ? ? ? ? ? ? ? ? ? ? ? //ID=ECf1 ;;ID=ecda ? ? ? ? Uart_Printf("nnand flash`s ID is:%xn",ID);? ??
? ? if(EraseBlock(BlockPages)&0x1==TRUE)? ? ? {? ? ? ? ? ? ? ? ? ? Uart_Printf("nblock %d is erasedn",NFBlockNO);?
? ? ? ? ? ? ? ? ReadPage(BlockPages,buf); //读page中的内容
? ? ? ? ? ? ? ? Uart_Printf("n/***********************擦除之后flash中的数据****************/n");? ? ? ? ? ? ? ? ? for(i=0; i<512; i++)? ? ?? ???? ? ? ? Uart_Printf("%4x",buf);? ? ?? ??? ? ? ? ? ? ? ? ? Uart_Printf("n/***********************应写入数据****************/n");?
|
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|