⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand_flash_write.c

📁 裸板的tftp客户端
💻 C
字号:
#include "./include/nand_flash_write.h"
#include "./include/led.h"
#include "./include/myout.h"
///////// flag bad block
static U32 NF_MarkBadBlock(U32 block)
{
      int i;
      char seBuf[6]={0};
      U32 blockPage=(block<<5);
      seBuf[0]=0xff;
      seBuf[1]=0xff;
      seBuf[2]=0xff;
      seBuf[5]=0x44;   // set bad block flag
      NF_EN();    //nand chip select enable
      NF_CMD(0x50);      //from C feild start write
      NF_CMD(0x80);	//send program CMD 
      NF_ADDR(0x0); 	// A0~A7 (column address)
      NF_ADDR(blockPage&0xff);    // A9~A16 (page address and block address)
      NF_ADDR((blockPage>>8)&0xff);  // A17~a24 (block address)
      NF_ADDR((blockPage>>16)&0xff);  //A25 (block address)
	// write OOB data block
      for(i=0;i<16;i++)
      {
           NF_WRDATA(seBuf[i]);
      }
      NF_CMD(0x10);			//end write CMD
      // wait NandFlash ready ok
      for(i=0;i<10;i++);	// wait tWB=100ns
      NF_WAITRB();		// busy wait
      //  read  NandFlash's wtite status
      NF_CMD(0x70);
      for(i=0;i<3;i++);		//twhr=60ns
      if(NF_RDDATA()&0x1)
      {
            NF_DI();		//  Nand Flash disable
            return 0;
      }else{
            NF_DI();		//  Nand Flash   disable
      }
      return 1;
}


//////////check if bad block, if bad return 1, else return 0
U32 NF_IsBadBlock(U32 block)
{
      int i;
      U32 blockPage;
      U8 data;
      blockPage=(block<<5);
      NF_EN();    					//nand chip select enable
      NF_CMD(0x50);      				// read OOB data block
      NF_ADDR(517&0xf);   				// A0~A7 (column adrress)
      NF_ADDR(blockPage&0xff);    		// A9~A16 (page address and block address)
      NF_ADDR((blockPage>>8)&0xff); 	 // A17~a24 (block address)
      NF_ADDR((blockPage>>16)&0xff); 	 //A25 (block address)
      // wait nandflash readyok
      for(i=0;i<10;i++);			//wait tWB(100ns)
      NF_WAITRB();
      // get already read value
      data=NF_RDDATA();
      NF_DI();         			//  Nand Flash disable
      // if data no 0xff , confirmation is bad block
      if(data!=0xff)
           return 1;
      else
           return 0;
}
/////////////// erase block return 0: erase error, flag 0 and return 0////
U32 NF_EraseBlock(U32 block)
{
      U32 blockPage=(block<<5);
      int i;
      // if is bad block return 0
      if(NF_IsBadBlock(block))
             return 0;
      NF_EN();				// Nand Flash enable
      NF_CMD(0x60);				// set erase mode
      NF_ADDR(blockPage&0xff);			//A9~A16, (Page Address), is erase block
      NF_ADDR((blockPage>>8)&0xff);		//A17~A24, (Page Address)
      NF_ADDR((blockPage>>16)&0xff);		//A25, (Page Address)
      NF_CMD(0xd0);				//send erase CMD ,start erase
      /// wait NandFlash ready ok
      for(i=0;i<10;i++);			//tWB(100ns)
      NF_WAITRB();
      // read operat status
      NF_CMD(0x70);
      if (NF_RDDATA()&0x1)
      {
          NF_DI();				// Nand Flash disable
	MyOut("\n\r erase error");
          NF_MarkBadBlock(block);		// flag bad block
          return 0;
      }else{
            NF_DI();				// Nand Flash disable
            return 1;
      }
}

////////////////////////////  nandflash write/////////
U32 NF_WritePage(U32 block, U32 page, U8 *buffer)
{
      int i;
      U8 seBuf[6]={0};
      U32 blockPage = (block<<5)+page, status;
      U8 *bufPt = buffer;
      NF_RSTECC();				// init ECC
      //////////////// I modified here/////////////////////////
      NFCONF |= 0x8000;
      NF_EN();
      NFCONF |=(NFCONF & ~0x777) | 0x33;	
      ///////////////////////////////////////////////////////////
      NF_CMD(0x0);				// from A feild start write
      NF_CMD(0x80);				// write first CMD
      NF_ADDR(0);				// A0~A7 bit(Column Address)
      NF_ADDR(blockPage&0xff);			// A9~A16, (Page Address)
      NF_ADDR((blockPage>>8)&0xff);		//A17~A24, (Page Address)
      NF_ADDR((blockPage>>16)&0xff);		//A25,(Page Address)
      NF_WAITRB();
      for(i=0;i<512;i++)
      {
           NF_WRDATA(*bufPt++);        	// write one page(512 bytes) to  Nand Flash
       }
 
      // OOB 一共 16 Bytes, 每一个字节存放什么由程序员自己定义, 通常,
      // 我们在 Byte0­Byte2 存 ECC 检验码. Byte6 存放坏块标志.
      
      seBuf[0]=NFECC0;				// get ECC check code 0
      seBuf[1]=NFECC1;				// get ECC check code 1
      seBuf[2]=NFECC2;				// get ECC check code 2
      seBuf[5]=0xff;				// negation bad block flag
      for(i=0;i<16;i++)
      {
           NF_WRDATA(seBuf[i]);			// write the page OOB data block
      }
      NF_CMD(0x10);				// end write CMD
	  // wait Nand Flash, busy status
      for(i=0;i<10;i++);
      NF_WAITRB();
	  // send read status CMD to Nand Flash
      NF_CMD(0x70);
      for(i=0;i<3;i++);
      if ((status=NF_RDDATA())&0x1)
      {  					// if write error ,flag bad block
           NF_DI();				// Nand Flash disable
           NF_MarkBadBlock(block);
           return 0;
       }else{					// exit
           NF_DI();				// Nand Flash disable
           return 1;
      }
}

/////////////////////////////

void nand_write(U32 block, U32 fileSize, U8 *srcAddress)
{
      int i;
      int programError=0;
      U32 blockIndex;
      U8 *srcPt, *saveSrcPt;
      srcPt=srcAddress;     		// file start address
      blockIndex = block; 
      InitLed();
      LedPlay(0x18);
      while(1)
      {
          saveSrcPt=srcPt;
           // if current block is bad block, jump current block
          if(NF_IsBadBlock(blockIndex))
          {
                blockIndex++;		// to next block
                continue;
       	   }
           // before write, have to erase, if erase failed to jump current block
           if(!NF_EraseBlock(blockIndex))
  	   {
                blockIndex++;		// to next block
		continue;
	    }

            // write one block(totall 32 pages)
	    for(i=0;i<32;i++)
	    {	
            // write one page, if error to stop write current block
                  if(!NF_WritePage(blockIndex,i,srcPt))
		  {
                         programError=1;
                         break;
                   }
		   srcPt += 512;
                   if(srcPt>=(srcAddress+fileSize))
                       break;
              }
             // 如果写一个块时, 其中某一页写失败, 则把写地址恢复写该块之前, 并跳过当前块 
            if(programError==1)
	    {
                   blockIndex++;
                   srcPt=saveSrcPt;
                   programError=0;
                   continue;
            }
            // if write address smaller than file len, continue; or, stop write
            if(srcPt >= (srcAddress + fileSize))
                  break;
             // if write success , continue next block
            blockIndex++;
      }
      while(1)
      {
            LedPlay(i++);
	    Delay(10);
      }
}
//////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -