/**********************按键实验*********************************/ /***************************************************************/ /* 本实验接口说明 */ #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 running\n"); InitNandCfg(); //初始化函数 ID=ReadChipId(); //ID=ECf1 ;;ID=ecda Uart_Printf("\nnand flash`s ID is:%x\n",ID); if(EraseBlock(BlockPages)&0x1==TRUE) { Uart_Printf("\nblock %d is erased\n",NFBlockNO); ReadPage(BlockPages,buf); //读page中的内容 Uart_Printf("\n/***********************擦除之后flash中的数据****************/\n"); for(i=0; i<512; i++) Uart_Printf("%4x", buf); Uart_Printf("\n/***********************应写入数据****************/\n"); |
2440nandflash小实验
最新推荐文章于 2019-08-28 19:38:55 发布