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

📄 nand.c

📁 SMDK2416_BSP
💻 C
字号:
#include <windows.h>
#include "s2450ADDR.h"
#include "option.h"

#define NF_CMD(cmd)		{rNFCMD=cmd;}
#define NF_ADDR(addr)	  {rNFADDR=addr;}	

#define NF_FCE	0	// 0:FCE0, 1:FCE1, In steploader, NAND cs has to be FCE0.

#define CMD_READ                0x00        //  Read
#define CMD_READ1               0x01        //  Read1
#define CMD_READ2               0x50        //  Read2
#define CMD_READ3               0x30        //  Read3
#define CMD_RDO		0x05        //  Random Data Output
#define CMD_RDO2	0xE0        //  Random Data Output

#if NF_FCE==0
#define NF_nFCE_L()			{rNFCONT &= ~(1 << 1);}
#define NF_nFCE_H()			{rNFCONT |=  (1 << 1);}
#else if NF_FCE==1
#define NF_nFCE_L()			{rNFCONT &= ~(1 << 2);}
#define NF_nFCE_H()			{rNFCONT |=  (1 << 2);}
#endif

#define NF_RSTECC()			{rNFCONT |=  ((1<<5)|(1<<4));}

#define NF_MECC_UnLock()	{rNFCONT &= ~(1<<7);}
#define NF_MECC_Lock()		{rNFCONT |= (1<<7);}

#define NF_SECC_UnLock()	{rNFCONT &= ~(1<<6);}
#define NF_SECC_Lock()		{rNFCONT |= (1<<6);}

#define NF_CLEAR_RB()		{rNFSTAT |=  (1 << 4);}
//#define NF_DETECT_RB()		{while(!(rNFSTAT&(1<<4)));}
#define NF_DETECT_RB()		{ while((rNFSTAT&0x11)!=0x11);} // RnB_Transdetect & RnB
#define NF_WAITRB()		 {while (!(rNFSTAT & (1 << 0)));} 


#define NF_RDDATA() 	   (rNFDATA)
#define NF_RDDATA8() 	   (unsigned char)(rNFDATA8)
#define NF_RDDATA32() 	   (rNFDATA32)
#define NF_WRDATA(data) 	{rNFDATA=data;}

#define NF_RDMECC0()			(rNFMECC0)
#define NF_RDMECC1()			(rNFMECC1)

#define NF_RDMECCD0()			(rNFMECCD0)
#define NF_RDMECCD1()			(rNFMECCD1)

#define NF_WRMECCD0(data)			{rNFMECCD0 = (data);}
#define NF_WRMECCD1(data)			{rNFMECCD1 = (data);}


#define ID_K9S1208V0M	  0xec76

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

BOOL bLARGEBLOCK;

void Uart_SendBYTE(BYTE d, BOOL cr);
void __RdPage512(BYTE *bufPt); 


typedef enum {
    ECC_CORRECT_MAIN = 0,  // correct Main ECC
    ECC_CORRECT_SPARE1 = 1,  // correct Main ECC
    ECC_CORRECT_SPARE2 = 2,  // correct Main ECC
} ECC_CORRECT_TYPE;

BOOL ECC_CorrectData(unsigned int sectoraddr, UINT8* pData, UINT32 nRetEcc, ECC_CORRECT_TYPE nType)
{
	DWORD  nErrStatus;
	DWORD  nErrDataNo;
	DWORD  nErrBitNo;
	UINT32 nErrDataMask;
	UINT32 nErrBitMask = 0x7;
	BOOL bRet = TRUE;

	if (nType == ECC_CORRECT_MAIN ||nType == ECC_CORRECT_SPARE1 || nType == ECC_CORRECT_SPARE2)
	{
		nErrStatus   = 0;
		nErrDataNo   = 7;
		nErrBitNo    = 4;
		nErrDataMask = 0x7ff;
	}
	else
	{
		return FALSE;
	}

	switch((nRetEcc>>nErrStatus) & 0x3)
	{
		case 0:	// No Error
			bRet = TRUE;
			break;
		case 1:	// 1-bit Error(Correctable)
//			Uart_SendString("ECC 1bit error ");
			(pData)[(nRetEcc>>nErrDataNo)&nErrDataMask] ^= (1<<((nRetEcc>>nErrBitNo)&nErrBitMask));
			bRet = TRUE;		
			break;
		case 2:	// Multiple Error
//			Uart_SendString("ECC Multiple error ");
//			Uart_SendDWORD(sectoraddr,1);
			bRet = FALSE;			
			break;
		case 3:	// ECC area Error
//			Uart_SendString("ECC area error\n");
		default:
			bRet = FALSE;			
			break;
	}

	return bRet;
}

int NF_ReadPage(UINT32 block,UINT32 sector,UINT8 *buffer)
{
	register UINT8 * bufPt=buffer;
	unsigned int RowAddr, ColAddr;
	DWORD MECCBuf, rddata1, rddata2;
	UINT32 nRetEcc;
	int nRet = FALSE;
	int nSectorLoop;

	NF_nFCE_L();	

	for (nSectorLoop = 0; nSectorLoop < (bLARGEBLOCK==TRUE?4:1); nSectorLoop++)
	{
		ColAddr = nSectorLoop * 512;

		NF_CMD(CMD_READ);   // Read command

		if (bLARGEBLOCK == TRUE)
		{
			RowAddr = (block<<6) + sector;
			
			NF_ADDR((ColAddr)   &0xff);    // 1st cycle
			NF_ADDR((ColAddr>>8)&0xff);    // 2nd cycle
			NF_ADDR((RowAddr)   &0xff);    // 3rd cycle
			NF_ADDR((RowAddr>>8)&0xff);    // 4th cycle
			if (LB_NEED_EXT_ADDR)
				NF_ADDR((RowAddr>>16)&0xff);    // 5th cycle
		}
		else
		{
			RowAddr = (block<<5) + sector;
			
			NF_ADDR((ColAddr)   &0xff);    // 1st cycle
			NF_ADDR((RowAddr)   &0xff);    // 2nd cycle
			NF_ADDR((RowAddr>>8)&0xff);    // 3rd cycle
			if (SB_NEED_EXT_ADDR)
				NF_ADDR((RowAddr>>16)&0xff);    // 4th cycle
		}

		NF_CLEAR_RB();
		NF_CMD(CMD_READ3);   // Read command
		NF_DETECT_RB();
		//NF_WAITRB();

		NF_RSTECC();	// Initialize ECC

		NF_MECC_UnLock();
		
		__RdPage512(bufPt+nSectorLoop*512);		// Read 512 bytes.

		NF_MECC_Lock();

		if (bLARGEBLOCK == TRUE)
		{
			ColAddr = 2048;

			NF_CMD(CMD_RDO);		// Random Data Output In a Page, 1st Cycle
			NF_ADDR((ColAddr)   &0xff);    // 1st cycle
			NF_ADDR((ColAddr>>8)&0xff);    // 2nd cycle
			NF_CMD(CMD_RDO2);		// Random Data Output In a Page. 2nd Cycle
		}

		rddata1 = NF_RDDATA32();  // check bad block
		rddata2 = NF_RDDATA32();

		if (bLARGEBLOCK == TRUE)
		{
			if (((rddata1 & 0xff) != 0xff) && (((rddata2>>8) & 0xff) != 0x03)) return nRet;  // bad block && !(OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY)
		}
		else if ((((rddata2>>8) & 0xff) != 0xff) && ((rddata2 & 0xff) != 0x03)) return nRet;  // bad block && !(OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY)

		if (bLARGEBLOCK == TRUE)
		{
			ColAddr = 2048 + 8 + nSectorLoop*4;

			NF_CMD(CMD_RDO);		// Random Data Output In a Page, 1st Cycle
			NF_ADDR((ColAddr)   &0xff);    // 1st cycle
			NF_ADDR((ColAddr>>8)&0xff);    // 2nd cycle
			NF_CMD(CMD_RDO2);		// Random Data Output In a Page. 2nd Cycle
		}

		MECCBuf = NF_RDDATA32();

		NF_WRMECCD0( ((MECCBuf&0x0000ff00)<<8) | ((MECCBuf&0x000000ff)    ) );
		NF_WRMECCD1( ((MECCBuf&0xff000000)>>8) | ((MECCBuf&0x00ff0000)>>16) );

		nRetEcc = rNFECCERR0;

		nRet = ECC_CorrectData(RowAddr, bufPt+nSectorLoop*512, nRetEcc, ECC_CORRECT_MAIN);

		if (!nRet) return nRet;
	}

	NF_nFCE_H();	

	return nRet;
}

DWORD ReadFlashID(void)
{
	BYTE Mfg, Dev, i;
	volatile int ReadID;
	UINT32 nRet;

	bLARGEBLOCK = FALSE;
	nRet = TRUE;
	
	NF_nFCE_L();

	NF_CMD(0x90);				// Send flash ID read command.

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

	Mfg	= NF_RDDATA8();		// Maker code
	Dev	= NF_RDDATA8();		// Devide code(K9S1208V:0x76), (K9K2G16U0M:0xca)

	NF_nFCE_H();

	if (Mfg == (UINT8)0xEC)
	{
		if (Dev >= (UINT8)0xA0)
			bLARGEBLOCK = TRUE;
	}
	else if (Mfg == (UINT8)0x98)
	{
	}
	else
	{
		nRet = FALSE;
	}

	ReadID = (DWORD)((Mfg<<8)+Dev);

//	Uart_SendString("FlashID :");
//	Uart_SendDWORD(ReadID,1);

//	return ((DWORD)(Mfg<<8)+Dev);
	return nRet;
}

void NF_Reset(void)
{
	volatile int i;
   
	NF_nFCE_L();

	NF_CLEAR_RB();
	NF_CMD(0xFF);	//reset command
	for(i=0;i<10;i++);  //tWB = 100ns. //??????
	NF_DETECT_RB();

	NF_nFCE_H();						// Deselect the flash chip.
}


void NF_Init(void)
{

	rNFCONF =	(TACLS  <<  12) | /* CLE & ALE = HCLK * (TACLS  + 1)   */
				(TWRPH0 <<  8) | /* TWRPH0	= HCLK * (TWRPH0 + 1)   */
				(TWRPH1 <<  4) |
				(0<<0);

	rNFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
	
	rNFSTAT = (1<<4);
	
	NF_Reset();
}

⌨️ 快捷键说明

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