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

📄 nand.c

📁 DMA-2442开发板bootloader
💻 C
📖 第 1 页 / 共 4 页
字号:
//====================================================================
// File Name : Nand.c
// Function  : S3C2442 8-bit interface Nand Test program(this program use K9F1G08.c).
// Date      : Nov xx, 2004
// Version   : 0.0
// History
//   R0.0 (200305xx): Modified for 2442 from 2410. -> DonGo
//====================================================================


/**************** K9s1208 NAND flash ********************/
// 1block=(512+16)bytes x 32pages
// 4096block
/**************** K9F1G08 NAND flash *******************/
// 1block=(2048+64)bytes x 64pages
// 1024block
/*****************************************************/

#include <string.h>

#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "Nand.h"

//suppport boot params
#define	GLOBAL_PARAMS
#include "bootpara.h"

#define	puts	Uart_Printf
#define	printf	Uart_Printf
#define	getch	Uart_Getch
#define	putch	Uart_SendByte





//#include "Nand.h"
//#include "K9F1G08.h"


#define BAD_CHECK	(1)
#define ECC_CHECK	(0)

#define C_LANG	1
#define DMA		2
#define TRANS_MODE 1

U8 NF1G08_Spare_Data[64];

extern U32 srcAddress;
extern U32 targetBlock;	    // Block number (0 ~ 4095)
extern U32 targetSize;	    // Total byte size 

extern U32 downloadAddress;
extern U32 downloadProgramSize;
volatile int NFConDone_1G08;

//*************************************************
//*************************************************
//**           H/W dependent functions           **
//************************************************* 
//*************************************************

//The code is made for bi-endian mode






// HCLK=100Mhz
#define TACLS		7	// 1-clk(0ns) 
#define TWRPH0		7	// 3-clk(25ns)
#define TWRPH1		7	// 1-clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns


/*
 * Standard NAND flash commands
 */
#define NAND_CMD_READ0		0
#define NAND_CMD_READ1		1
#define NAND_CMD_READSTART	0x30	
#define NAND_CMD_PAGEPROG	0x10
#define NAND_CMD_READOOB	0x50
#define NAND_CMD_ERASE1		0x60
#define NAND_CMD_STATUS		0x70
#define NAND_CMD_SEQIN		0x80
#define NAND_CMD_READID		0x90
#define NAND_CMD_ERASE2		0xd0
#define NAND_CMD_RESET		0xff


#define NF_SOFT_UnLock()      	 	{rNFCONT&=~(1<<12);}
#define NF_MECC_UnLock()      	 	{rNFCONT&=~(1<<5);}
#define NF_MECC_Lock()      	  	{rNFCONT|=(1<<5);}
#define NF_SECC_UnLock()  	     	{rNFCONT&=~(1<<6);}
#define NF_SECC_Lock()      		{rNFCONT|=(1<<6);}
#define NF_nFCE_L()                     {rNFCONT&=~(1<<1);}
#define NF_nFCE_H()                     {rNFCONT|=(1<<1);}
#define NF_EN()				(rNFCONT |= 1)
#define NF_DIS()				(rNFCONT &= ~1)
#define NF_RSTECC()                     {rNFCONT|=(1<<4);}
#define NF_CLEAR_RB()                   {rNFSTAT |= (1<<2);}
#define NF_DETECT_RB()                  {while(!(rNFSTAT&(1<<2)));}

#define NF_RDDATA() 		(rNFDATA)
#define NF_RDDATA8() 		((*(volatile unsigned char*)0x4E000010) )
#define NF_WRDATA(data) 	{rNFDATA=data;}
#define NF_WRDATA8(data) 	{rNFDATA8=data;}



#ifdef	WIAT_BUSY_HARD
#define	WaitNFBusy()	while(!(rNFSTAT&1))
#else
static U32 WaitNFBusy(void)	// R/B 未接好?
{
	U8 stat;
	rNFCMD = 0x70;
	do {
		stat = NF_RDDATA8();
		//printf("%x\n", stat);
	}while(!(stat&0x40));
	rNFCMD = 0;
	return stat&1;
}
#endif

static U8 se8Buf[64]={
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};


/* GSTATUS4 is scratch register and we will use it as temporary */
typedef struct  {
	U32 cpage_size:16;
	U32 cpages_in_block:8;
	U32 cpage2Kis:8;
	U32 page_offset;
	U32 block_offset;
} nandif_t;



#define GSTATUS4		(*(volatile unsigned *)0x560000BC)

#define K9F1208_ID 0x76
#define K9F1G08_ID 0xa1

/* Global variable used in cmd_nand_s3c2442.c */
int cpage2Kis;
int cpage_size;	/* Current Page Size */
int cpages_in_block;
int coob_size;
int cblock_size;
int page_offset;
int block_offset;




/*
 * NF_Init : 
 */

static void NF_Init(void)
{
	// for S3C2442

	rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);	
	// TACLS		[14:12]	CLE&ALE duration = HCLK*TACLS.
	// TWRPH0		[10:8]	TWRPH0 duration = HCLK*(TWRPH0+1)
	// TWRPH1		[6:4]	TWRPH1 duration = HCLK*(TWRPH1+1)
	// AdvFlash(R)	[3]		Advanced NAND, 0:256/512, 1:1024/2048
	// PageSize(R)	[2]		NAND memory page size
	//						when [3]==0, 0:256, 1:512 bytes/page.
	//						when [3]==1, 0:1024, 1:2048 bytes/page.
	// AddrCycle(R)	[1]		NAND flash addr size
	//						when [3]==0, 0:3-addr, 1:4-addr.
	//						when [3]==1, 0:4-addr, 1:5-addr.
	// BusWidth(R/W) [0]	NAND bus width. 0:8-bit, 1:16-bit.
	
	rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
	// Lock-tight	[13]	0:Disable lock, 1:Enable lock.
	// Soft Lock	[12]	0:Disable lock, 1:Enable lock.
	// EnablillegalAcINT[10]	Illegal access interupt control. 0:Disable, 1:Enable
	// EnbRnBINT	[9]		RnB interrupt. 0:Disable, 1:Enable
	// RnB_TrandMode[8]		RnB transition detection config. 0:Low to High, 1:High to Low
	// SpareECCLock	[6]		0:Unlock, 1:Lock
	// MainECCLock	[5]		0:Unlock, 1:Lock
	// InitECC(W)	[4]		1:Init ECC decoder/encoder.
	// Reg_nCE		[1]		0:nFCE=0, 1:nFCE=1.
	// NANDC Enable	[0]		operating mode. 0:Disable, 1:Enable.

//	rNFSTAT = 0;
    
//    Nand_Reset();
}






static int NF_MarkBadBlock(U32 block)
{
	int i;
	U32 blockPage = block * cpages_in_block;

	NF_nFCE_L();
	NF_CLEAR_RB();

	if (cpage2Kis) {
		se8Buf[0]=0x44;   // Bad blcok mark=0	
		se8Buf[0] = 0xff;
		rNFCMD = NAND_CMD_SEQIN;
		rNFADDR = cpage_size & 0xff;
		rNFADDR = (cpage_size >> 8) & 0x0f;
		rNFADDR = blockPage & 0xff;
		rNFADDR= (blockPage>>8)& 0xff;
	} 
	else {
		se8Buf[5]=0x44;   // Bad blcok mark=0	
		se8Buf[5] = 0xff;

		rNFCMD = NAND_CMD_READOOB;
		rNFCMD = NAND_CMD_SEQIN;
		rNFADDR = 0;
		rNFADDR = (blockPage)&0xff;
		rNFADDR = (blockPage>>8)&0xff;
		rNFADDR = (blockPage>>16)&0xff;
	}
	
	for(i=0 ;i < coob_size ;i++){
		NF_WRDATA(se8Buf[i]); 
	}

	rNFCMD= NAND_CMD_PAGEPROG;

	for(i=0;i<10;i++); 
	NF_DETECT_RB();

	rNFCMD=NAND_CMD_STATUS;
	for(i=0;i<3;i++); 

	if (rNFDATA8 & 0x1) {
		NF_nFCE_H();
		printf("[Program error is occurred but ignored]\n");
	}
	else {
		NF_nFCE_H();
	}

	printf("[block 0x%x is marked as a bad block]\n",block);

	return 1;
} 

/*
#define	EnNandFlash()	(rNFCONT |= 1)
#define	DsNandFlash()	(rNFCONT &= ~1)
#define	NFChipEn()		(rNFCONT &= ~(1<<1))
#define	NFChipDs()		(rNFCONT |= (1<<1))
#define	InitEcc()		(rNFCONT |= (1<<4))
#define	MEccUnlock()	(rNFCONT &= ~(1<<5))
#define	MEccLock()		(rNFCONT |= (1<<5))
#define	SEccUnlock()	(rNFCONT &= ~(1<<6))
#define	SEccLock()		(rNFCONT |= (1<<6))

#define	WrNFDat8(dat)	(rNFDATA8 = (dat))
#define	WrNFDat32(dat)	(rNFDATA = (dat))
#define	RdNFDat8()		(rNFDATA8)	//byte access
#define	RdNFDat32()		(rNFDATA)	//word access

#define	WrNFCmd(cmd)	(rNFCMD = (cmd))
#define	WrNFAddr(addr)	(rNFADDR = (addr))
#define	WrNFDat(dat)	WrNFDat8(dat)
#define	RdNFDat()		RdNFDat8()	//for 8 bit nand flash, use byte access

#define	RdNFMEcc()		(rNFMECC0)	//for 8 bit nand flash, only use NFMECC0
#define	RdNFSEcc()		(rNFSECC)	//for 8 bit nand flash, only use low 16 bits

#define	RdNFStat()		(rNFSTAT)
#define	NFIsBusy()		(!(rNFSTAT&1))
#define	NFIsReady()		(rNFSTAT&1)
#define	READCMD0	0
#define	READCMD1	1
#define	READCMD2	0x50
#define	ERASECMD0	0x60
#define	ERASECMD1	0xd0
#define	PROGCMD0	0x80
#define	PROGCMD1	0x10
#define	QUERYCMD	0x70
#define	RdIDCMD		0x90
int NandAddr =1;
#define	InitEcc()		(rNFCONT |= (1<<4))

#define	RdNFDat8()		(rNFDATA8)	//byte access

#define	RdNFDat()		RdNFDat8()	//for 8 bit nand flash, use byte access

#define	NFChipEn()		(rNFCONT &= ~(1<<1))
#define	NFChipDs()		(rNFCONT |= (1<<1))
*/
void __irq NFCon_Int_1G08(void)
{
       NFConDone_1G08=1;
	rINTMSK|=BIT_NFCON;
	ClearPending(BIT_NFCON);
	if(rNFSTAT&0x8) Uart_Printf("Illegal Access is detected!!!\n");
//	else Uart_Printf("RnB is Detected!!!\n"); 
}
#if 1
static int NF_ReadPage(U32 block,U32 page,U8 *buffer)
{
       int i;
       unsigned int blockPage;
	U32 Mecc, Secc;
	U8 *bufPt=buffer;
	    
       blockPage=(block<<6)+page;
	NF_RSTECC();    // Initialize ECC
	NF_MECC_UnLock();

		NF_nFCE_L();


	NF_CLEAR_RB();
	rNFCMD=(0x00);	// Read command
       rNFADDR=(0); 	// Column (A[7:0]) = 0
       rNFADDR=(0);		// A[11:8]
       rNFADDR=((blockPage)&0xff);	// A[19:12]
       rNFADDR=((blockPage>>8)&0xff);	// A[27:20]
      
       rNFCMD=(0x30);	// 2'nd command
       NF_DETECT_RB();
	
      
	    for(i=0;i<2048;i++) {
	    	*bufPt++=NF_RDDATA8();	// Read one page
	    }
  

  /*  
	  NF_MECC_Lock();
	  
	  rNFMECCD0=NF_RDDATA();
	  
	  NF_nFCE_H();	  
	  
	  if ((rNFESTAT0&0x3) == 0x0) 	  return OK;
	  else   return FAIL;
*/

	 NF_MECC_Lock();

//	 NF_SECC_UnLock();
        NF1G08_Spare_Data[0]=NF_RDDATA8();
	//printf("NF1G08_Spare_Data[0]=%x\n",NF1G08_Spare_Data[0]);
	 Mecc=NF_RDDATA();
	 rNFMECCD0=((Mecc&0xff00)<<8)|(Mecc&0xff);
	 rNFMECCD1=((Mecc&0xff000000)>>8)|((Mecc&0xff0000)>>16);
	
//	 NF_SECC_Lock();
	 NF1G08_Spare_Data[1]=(U8)(Mecc&0xff);
	 NF1G08_Spare_Data[2]=(U8)((Mecc>>8) & 0xff);
	 NF1G08_Spare_Data[3]=(U8)((Mecc>>16) & 0xff);
	 NF1G08_Spare_Data[4]=(U8)((Mecc>>24) & 0xff);

	 for(i=5;i<64;i++) {
    	NF1G08_Spare_Data[i]=NF_RDDATA8();	// Read spare array with 4byte width
       }
/*	 NF_RDDATA();  // read 4~7
	 Secc=NF_RDDATA();
	 rNFSECCD=((Secc&0xff00)<<8)|(Secc&0xff);
	 NF8_Spare_Data[8]=Secc&0xff;
	 NF8_Spare_Data[9]=(Secc&0xff00)>>8;
	 NF8_Spare_Data[10]=(Secc&0xff0000)>>16;
	 NF8_Spare_Data[11]=(Secc&0xff000000)>>24;
	 */
	 
	
		NF_nFCE_H();
	

	 if ((rNFESTAT0&0x3) == 0x0){
	      // Uart_Printf("ECC OK!\n");
		return OK;
	 }
	 else {
		Uart_Printf("ECC FAIL!\n");
	       return FAIL;
	 }


}
#else
static int NF_ReadPage(U32 block,U32 page,U8 *buffer)
{

#if 0
	U16 i;
	U32 addr;
	U8 *buf=buffer;

	addr =block * cpages_in_block + page;
	
	NFChipEn();
	WrNFCmd(READCMD0);
	WrNFAddr(0);
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	InitEcc();
	WaitNFBusy();
	for(i=0; i<512; i++)
		{
		buf[i] = RdNFDat();
		//printf("buf[%d]=%x",i,buf[i]);
		//if(!(i%16))
		//printf("\n");
		}
	NFChipDs();
#else
	int i;
	U32 blockPage;
	U32 mecc;
	
	blockPage =block * cpages_in_block + page;
	//printf("blockpage = %x\n",blockPage);
	NFChipEn();
	//NF_RSTECC();    // Initialize ECC
	//NF_MECC_UnLock();
	
	//NF_nFCE_L();
	//NF_CLEAR_RB();

	rNFCMD = NAND_CMD_READ0;
	//printf("cpage2Kis=%d\n",cpage2Kis);
	if (cpage2Kis) {
		rNFADDR = 0;	/* colum is 0 */ 
		rNFADDR = 0; 
		rNFADDR = (blockPage) & 0xff;
		rNFADDR = (blockPage >> 8) & 0xff;
		rNFCMD = NAND_CMD_READSTART; 
	}
	else {
		rNFADDR= 0;
		rNFADDR= blockPage & 0xff;
		rNFADDR= (blockPage>>8) & 0xff;
		rNFADDR=((blockPage>>16)&0xff);
	}
	InitEcc()	;
	WaitNFBusy();
	//InitEcc();

	//NF_CLEAR_RB();

	for(i=0; i < cpage_size  ; i++) {
		
		buffer[i] = NF_RDDATA8();
		//printf("bufPt[%d]=%x",i,buffer[i] );
		//if(!(i%16))
		//	printf("\n");
	}

#if 0
	 NF_MECC_Lock();

//	 NF_SECC_UnLock();
	if(cpage2Kis)
	{
	        NF1G08_Spare_Data[0]=NF_RDDATA8();
		 mecc=NF_RDDATA();
		 rNFMECCD0=((mecc&0xff00)<<8)|(mecc&0xff);
		 rNFMECCD1=((mecc&0xff000000)>>8)|((mecc&0xff0000)>>16);
		
	//	 NF_SECC_Lock();
		 NF1G08_Spare_Data[1]=(U8)(mecc&0xff);
		 NF1G08_Spare_Data[2]=(U8)((mecc>>8) & 0xff);
		 NF1G08_Spare_Data[3]=(U8)((mecc>>16) & 0xff);
		 NF1G08_Spare_Data[4]=(U8)((mecc>>24) & 0xff);

		 for(i=5;i<coob_size;i++) {
	    	NF1G08_Spare_Data[i]=NF_RDDATA8();	// Read spare array with 4byte width
	      	}
	}

	else
	{
		 mecc=NF_RDDATA();
		 rNFMECCD0=((mecc&0xff00)<<8)|(mecc&0xff);
		 rNFMECCD1=((mecc&0xff000000)>>8)|((mecc&0xff0000)>>16);
		 for(i=4;i<coob_size;i++){
		 	NF1G08_Spare_Data[i]=NF_RDDATA8();	// Read spare array with 4byte width
		 }
	}
	
	

⌨️ 快捷键说明

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