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

📄 nand.c

📁 6410BSP3
💻 C
字号:
#include <windows.h>
#include "s3c6410_addr.h"
#include "utils.h"
#include "nand.h"

#define DEV_ADDR_CYCLE (5)

///////////////////////////////////////////////
// NAND Controller Macro
///////////////////////////////////////////////
#define NF_CE_L(bank)		{	\
								if (bank == 0) rNFCONT &= ~NF_NFCE0;	\
								else if (bank == 1) rNFCONT &= ~NF_NFCE1;	\
							}
#define NF_CE_H(bank)		{	\
								if (bank == 0) rNFCONT |= NF_NFCE0;	\
								else if (bank == 1) rNFCONT |= NF_NFCE1;		\
							}
#define NF_CMD(cmd)			(rNFCMD = (unsigned char)cmd)
#define NF_ADDR(addr)		(rNFADDR = (unsigned char)addr)
#define NF_DATA_R()			(rNFDATA8)
#define NF_DATA_R4()		(rNFDATA32)
#define NF_DATA_W4(n)		(rNFDATA32 = (DWORD)n)
#define NF_SET_ECC_DEC()	(rNFCONT &= ~NF_4BIT_ECC_ENC)
#define NF_MECC_Reset()		(rNFCONT |= NF_INIT_MECC)
#define NF_MECC_Lock()		(rNFCONT |= NF_MAIN_ECC_LOCK)
#define NF_MECC_UnLock()	(rNFCONT &= ~NF_MAIN_ECC_LOCK)
#define NF_CLEAR_ECC_DEC_DONE()	(rNFSTAT |= NF_ECC_DEC_DONE)
#define NF_WAIT_ECC_DEC_DONE()	{	\
										while(!(rNFSTAT&NF_ECC_DEC_DONE));	\
									}

#define NF_WRMECCD0(data)			{rNFMECCD0 = (data);}
#define NF_WRMECCD1(data)			{rNFMECCD1 = (data);}
#define NF_ECC_DEC_ERROR()			((rNFECCERR0>>26)&0x7)
#define NF_ECC_ERR0()				(rNFECCERR0)
#define NF_ECC_ERR1()				(rNFECCERR1)
#define NF_ECC_ERR_PATTERN()		(rNFMLCBITPT)

#define NF_DETECT_RB()	{	\
								while(!(rNFSTAT&NF_RNB_READY));	\
							}

#define NF_WAIT_RnB(bank)	{	\
								NF_CMD(CMD_READ_STATUS);		\
								while(!(NF_DATA_R()&0x40));			\
							}

#define NF_SET_ADDR(nPpn, nOffset)	{	\
										NF_ADDR(nOffset&0xFF);			\
										NF_ADDR((nOffset>>8)&0xFF);		\
										NF_ADDR(nPpn&0xFF);			\
										NF_ADDR((nPpn>>8)&0xFF);		\
										if (DEV_ADDR_CYCLE > 4)			\
											NF_ADDR((nPpn>>16)&0xFF);	\
									}

#define NF_SET_CLK(tacls, twrph0, twrph1)		(rNFCONF = (rNFCONF&~0x7770)		\
											|NF_TACLS(tacls) | NF_TWRPH0(twrph0) | NF_TWRPH1(twrph1))


///////////////////////////////////////////////
// Assembly Read Function (in nand.s)
///////////////////////////////////////////////
void _Read_512Byte(unsigned char* pBuf);
void _Write_Dummy_Byte_AllFF(int nByteSize);  // nByteSize is the multifilication of 4
int CorrectECC8Data(unsigned char *pEncodingBaseAddr);


void NAND_Init(void)
{

	// Initialize NAND Flash Controller for MLC NAND Flash
	rNFCONF = NF_8BIT_ECC | NF_TACLS(DEFAULT_TACLS) | NF_TWRPH0(DEFAULT_TWRPH0) | NF_TWRPH1(DEFAULT_TWRPH1);
	rNFCONT = NF_MAIN_ECC_LOCK | NF_SPARE_ECC_LOCK | NF_INIT_MECC | NF_INIT_SECC | NF_NFCE1 | NF_NFCE0 | NF_NFCON_EN;
	rNFSTAT = NF_RNB_READY;	// Clear RnB Transition Detect Bit

	rNFCONF = rNFCONF & ~(1<<30);
	rNFCONT |= (1<<18)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9); //ECC for programming.// Enable RnB Interrupt 
	rNFSTAT |= ((1<<6)|(1<<5)|(1<<4));

	NAND_Reset(0);
}

void NAND_Reset(DWORD dwBank)
{
	// Chip Select
	NF_CE_L(dwBank);

	// Reset Command is accepted during Busy
	NF_CMD(CMD_RESET);

	// Chip Unselect
	NF_CE_H(dwBank);
}

BOOL NAND_Read(DWORD dwBank, DWORD dwPage, unsigned char *pBuf, BOOL b4KPage)
{
	DWORD SpareDataDummy;
	DWORD dwOffset;
	DWORD dwCnt;
	DWORD dwSpareAddress = 2048 + 1;	//include Bad block

	unsigned char uSctCnt;
	BOOL bRet = TRUE;

	if (b4KPage == TRUE) uSctCnt = 8;
	else uSctCnt = 4;

	rNFCONF = ( rNFCONF&~(0x3<<23) ) |(2<<30)|(1<<23)|(0x7<<12)|(0x7<<8)|(0x7<<4);
	rNFCONT = ( rNFCONT&~(0x1<<18) ) |(0<<18)|(0<<11)|(0<<10)|(0<<9)|(1<<6)|(1<<0); // Init NFCONT	
	rNFSTAT |= ((1<<6)|(1<<5)|(1<<4));

	NAND_Reset(dwBank);
	
	NF_MECC_Lock(); // Main ECC Lock
	NF_CE_L(dwBank);
	rNFSTAT |= (1<<4); // RnB Clear


	NF_CMD(CMD_READ);
	NF_SET_ADDR(dwPage, 0x00);
	NF_CMD(CMD_READ_CONFIRM);
	NF_DETECT_RB();
	rNFSTAT |= (1<<4); // RnB Clear

	//READ Spare ECC Data
	for(dwCnt = 0; dwCnt < uSctCnt; dwCnt++) {
		NF_MECC_Lock(); // Main ECC Lock
		rNFSTAT |= (1<<4); // RnB Clear

		if(!dwCnt) {
			NF_CMD(CMD_READ);
			NF_SET_ADDR(dwPage, 0);
			NF_CMD(CMD_READ_CONFIRM);

			NF_DETECT_RB();
			rNFSTAT |= (1<<4); // RnB Clear			
		}
		else
		{
			dwOffset = dwCnt * 512;
			NF_CMD(CMD_RANDOM_DATA_OUTPUT);
			NF_ADDR(dwOffset&0xFF);
			NF_ADDR((dwOffset>>8)&0xFF);
			NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM);
		}

		NF_MECC_UnLock(); 	// Main ECC Unlock
		NF_MECC_Reset();	 // Initialize ECC
 
		//read 512byte
		_Read_512Byte(pBuf + 512*dwCnt);

                if (b4KPage == TRUE)
                        dwOffset = 4096 + (dwCnt * 13);
                else
                        dwOffset = 2048 + (dwCnt * 13);

		NF_CMD(CMD_RANDOM_DATA_OUTPUT);
		NF_ADDR(dwOffset&0xFF);
		NF_ADDR((dwOffset>>8)&0xFF);
		NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM);

		//read Spare ECC Data		
		SpareDataDummy = NF_DATA_R4();
		SpareDataDummy = NF_DATA_R4();
		SpareDataDummy = NF_DATA_R4();
		SpareDataDummy = NF_DATA_R();

		NF_MECC_Lock(); // Main ECC Lock

		while(!(rNFSTAT&(1<<6))); 	// Check decoding done 
		rNFSTAT = rNFSTAT | (1<<6);   // Decoding done Clear

		while( rNF8ECCERR0 & (unsigned int)(1<<31) ) ; // 8bit ECC Decoding Busy Check.

		if(CorrectECC8Data((pBuf + 512*dwCnt))) {
			return FALSE;

		}		
	}

	NF_CE_H(dwBank);
	
	return TRUE;
}




int CorrectECC8Data(unsigned char *pEncodingBaseAddr)
{	
	unsigned int i,uErrorByte[9];
	unsigned char uErrorBit[9];
	unsigned int uErrorType;
	
	
	uErrorType = (rNF8ECCERR0>>25)&0xf;// Searching Error Type //How many Error bits does exist?	
	uErrorByte[1] = rNF8ECCERR0&0x3ff;// Searching Error Byte //Where is the error byte?
	uErrorByte[2] = (rNF8ECCERR0>>15)&0x3ff;	
	uErrorByte[3] = (rNF8ECCERR1)&0x3ff;
	uErrorByte[4] = (rNF8ECCERR1>>11)&0x3ff;	
	uErrorByte[5] = (rNF8ECCERR1>>22)&0x3ff;	
	uErrorByte[6] = (rNF8ECCERR2)&0x3ff;
	uErrorByte[7] = (rNF8ECCERR2>>11)&0x3ff;
	uErrorByte[8] = (rNF8ECCERR2>>22)&0x3ff;
	
	uErrorBit[1] = rNFMLC8BITPT0&0xff;// Searching Error Bit //Where is the error bit?
	uErrorBit[2] = (rNFMLC8BITPT0>>8)&0xff;
	uErrorBit[3] = (rNFMLC8BITPT0>>16)&0xff;
	uErrorBit[4] = (rNFMLC8BITPT0>>24)&0xff;	
	uErrorBit[5] = rNFMLC8BITPT1&0xff;
	uErrorBit[6] = (rNFMLC8BITPT1>>8)&0xff;
	uErrorBit[7] = (rNFMLC8BITPT1>>16)&0xff;
	uErrorBit[8] = (rNFMLC8BITPT1>>24)&0xff;
	
	if(uErrorType == 0x0) {
		return 0;
	}

	if(uErrorType == 0x9) {
		return 1;
	}
	for(i=1;i<=uErrorType ;i++)	
	{
		if(uErrorByte[i] < 512)	
			pEncodingBaseAddr[uErrorByte[i]]^=uErrorBit[i];
		else
		{;	}			
	}
	return 0;
	
}



void Read_DeviceID(DWORD dwBank, unsigned char *pDID, unsigned char *pHID)
{
	unsigned char ucMID, ucDID, ucHID[3];
	int i;

	// Chip Select
	NF_CE_L(dwBank);
	NF_WAIT_RnB(dwBank);

	// Read ID Command
	NF_CMD(CMD_READ_ID);
	NF_ADDR(0x00);

	// Find Maker Code
	for (i=0; i<10; i++)
	{
		ucMID = NF_DATA_R();		// Maker Code
		if (ucMID == 0xEC) break;
	}

	// Read Device Code
	ucDID = NF_DATA_R();		// Device Code
	ucHID[0] = NF_DATA_R();		// Internal Chip Number
	ucHID[1] = NF_DATA_R();		// Page, Block, Redundant Area Size
	ucHID[2] = NF_DATA_R();		// Plane Number, Size

	// Chip Unselect
	NF_CE_H(dwBank);

	if (ucMID == 0xEC)
	{
		*pDID = ucDID;
		*pHID = ucHID[0];
	}
	else
	{
		*pDID = 0x00;
		*pHID = 0x00;
	}
}

⌨️ 快捷键说明

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