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

📄 nandflash.c

📁 S3C2410学习的基础资料 大部分实验源码及工程
💻 C
字号:
#include "def.h"
#include "2410addr.h"
#include "2410lib.h"
#include "nandflash.h"

/**************************************
 ***  初始化 K9F1208U0M nand flash  ***
 **************************************/
void InitNandCfg(void)
{
	//(1<<15)-->enable nand flash control
	//(1<<12)-->initilize ecc decoder/encoder
	//(1<<11)-->nand flash nFCE=H(inactive),chip disable
	//(7<<8) -->Duration=HCLK*(TACLS+1)
	//(7<<4) -->Duration=HCLK*(TWRPH0+1)
	//(7<<0) -->Duration=HCLK*(TWRPH1+1)
	rNFCONF = (1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7<<0);	
}


/**************************************
 ****  K9F1208U0M nand flash 的ID  ****
 **************************************/
U32 ReadChipId(void)
{
	U32 id;
	
	NFChipEn();			//bit11=0 NAND flash nFCE = L (active)
	WrNFCmd(RdIDCMD);	//rNFCMD = 0x90,Read ID Command
	WrNFAddr(0);		//rNFADDR = 0x00,
	
	//whether nand flash is busy?
	//rNFSTAT&1 = 1 ,busy
	//rNFSTAT&1 = 0 ,no busy
	NF_WAITRB();	
	
	id  = RdNFDat()<<8;	// Maker code(K9S1208V:0xec)
	id |= RdNFDat();	// Devide code(K9S1208V:0x76)		
	
	NFChipDs();	 		//bit11=1 NAND flash nFCE = H (inactive)	
	
	return id;
}


/****************************************
 ****  K9F1208U0M nand flash 的状态  ****
 ****************************************/
static U16 ReadStatus(void)
{
	U16 stat;
	
	NFChipEn();	
	WrNFCmd(NFSTATUS);//NFSTATUS = 0x70		
	stat = RdNFDat();	
	NFChipDs();
	
	return stat;
}


/**********************************************
 ****  K9F1208U0M nand flash 的块擦除操作  ****
 **********************************************/
U32 EraseBlock(U32 addr)
{
	U8 status;
	U32 i;
			
	NFChipEn();	
	WrNFCmd(ERASECMD0);	//ERASECMD0 = 0x60,Erase one block 1st command	
	
	WrNFAddr(NFBlcokAddr>>9&0xff);
	WrNFAddr((NFBlcokAddr>>17)&0xff);
	WrNFAddr((NFBlcokAddr>>25)&0xff);    
			
	WrNFCmd(ERASECMD1);	//ERASECMD1 = 0xd0,Erase one blcok 2nd command	
	
	for(i=0;i<10;i++); //wait tWB(100ns)
	NF_WAITRB();    // Wait tBERS max 3ms.
	status = ReadStatus(); // Read status command
	if (status&0x1) // Erase error
    {	
    	NFChipDs();
	    MarkBadBlk(addr);
	    return 0;
    }
    else 
    {
    	NFChipDs();;
        return 1;
    }
	NFChipDs();
}


/********************************************
 ****  K9F1208U0M nand flash 的页数据读  ****
 ********************************************/
 U32 ReadPage(U32 addr, U8 *buf)//addr = page address
{
	U16 i;
	U8 tmp[3],se[16];
	InitEcc();
	NFChipEn();
	
	WrNFCmd(READCMD0);//READCMD0 = 0//read the first half page
	WrNFAddr(0);
	WrNFAddr(addr&0xff);
	WrNFAddr((addr>>8)&0xff);
	WrNFAddr((addr>>16)&0xff);
	WrNFAddr((addr>>24)&0xff);
	
	for(i=0;i<10;i++); //wait tWB(100ns)	
	NF_WAITRB();
	
	for(i=0; i<512; i++)
		buf[i] = RdNFDat();
	
	tmp[0] = rNFECC0;
    tmp[1] = rNFECC1;
    tmp[2] = rNFECC2;
	
	for(i=0;i<16;i++)
    {
    	se[i]=RdNFDat();	// Read spare array
    }
	NFChipDs();
	
	if(tmp[0]==se[0] && tmp[1]==se[1] && tmp[2]==se[2])
    {
	    Uart_Printf("[ECC OK:%x,%x,%x]\n",se[0],se[1],se[2]);
    	return 1;
    }
    else
    {
	    Uart_Printf("[ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x]\n",
	                se[0],se[1],se[2],tmp[0],tmp[1],tmp[2]);
    	return 0;
    } 
}


/********************************************
 ****  K9F1208U0M nand flash 的页数据读  ****
 ********************************************/
U32 WritePage(U32 addr, U8 *buf)
{
	U16 i;
	U8 status;
	U32 tmp[3];
	
	InitEcc();
	
	NFChipEn();
	WrNFCmd(0x00);////write the first half page
	WrNFCmd(PROGCMD0); //PROGCMD0 = 0x80
	WrNFAddr(0);
	WrNFAddr(addr&0xff);
	WrNFAddr((addr>>8)&0xff);
	WrNFAddr((addr>>16)&0xff);
	WrNFAddr((addr>>24)&0xff);

	for(i=0; i<512; i++)
		WrNFDat(buf[i]);//Write one page to nand flash from buffer
		
	tmp[0] = rNFECC0;
    tmp[1] = rNFECC1;
    tmp[2] = rNFECC2;
    	
	WrNFDat(tmp[0]);
	WrNFDat(tmp[1]);
	WrNFDat(tmp[2]);
    	
	WrNFCmd(PROGCMD1);//PROGCMD1 = 0x10
	
	for(i=0;i<10;i++);  //tWB = 100ns. 
    NF_WAITRB();    //wait tPROG 200~500us;
	status = ReadStatus();
	for(i=0;i<3;i++);  //twhr=60ns
	
	if (status&0x1) // Page write error
      {	
    	NFChipDs();
	    Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",addr);
	    MarkBadBlk(addr);
	    return 0;
      }
    else 
      {
    	NFChipDs();
	    return 1;
      }
}


/*********************************************
 ****  屏蔽 K9F1208U0M nand flash 的坏块  ****
 *********************************************/
U32 MarkBadBlk(U32 addr)
{
	int i;
	U16 status;
	addr = addr<<5;
	NFChipEn();
	
	WrNFCmd(READCMD2);	//READCMD2=0x50
	WrNFCmd(PROGCMD0);  //PROGCMD0=0x80
	
	WrNFAddr(4);		//mark offset 4,5,6,7
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	WrNFAddr(addr>>16);
	
	WrNFDat(0);			//mark with 0
	WrNFDat(0);
	WrNFDat(0);			//mark with 0
	WrNFDat(0);
	
	WrNFCmd(PROGCMD1);  //PROGCMD1=0x10
	
	for(i=0;i<10;i++);  //tWB = 100ns.
	NF_WAITRB();		//needn't check return status
	WrNFCmd(READCMD0);	//READCMD0=0
	
	status = ReadStatus();
	for(i=0;i<3;i++);  //twhr=60ns	
	 if (status&0x1) // Spare arrray write error
    {	
    	NFChipDs();
    	Uart_Printf("[Program error is occurred but ignored]\n");
    }
    else 
    {
    	NFChipDs();
    }

    Uart_Printf("[block #%d is marked as a bad block]\n",addr);
    return 1;
	
	NFChipDs();
}


/*********************************************
 ****  检查 K9F1208U0M nand flash 的坏块  ****
 *********************************************/
static int CheckBadBlk(U32 addr)
{
	U8 data;
	int i;
	addr = addr<<5;
	
	NFChipEn();
	
	WrNFCmd(READCMD2);	//READCMD2 = 0x50
	WrNFAddr(5);		//mark offset 4,5,6,7
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	WrNFAddr(addr>>16);
	
	for(i=0;i<10;i++);	// wait tWB(100ns) //
    NF_WAITRB();	// Wait tR(max 12us)
	
	data = RdNFDat();
    NFChipDs();
    if(data!=0xff)
    {
     	Uart_Printf("[block %d has been marked as a bad block(%x)]\n",addr,data);
    	return 1;
    }
    else
    {
    	return 0;
    }
}

⌨️ 快捷键说明

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