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

📄 nand.c

📁 sansumg s3c2443 bootload 的源码
💻 C
字号:
//#include <windows.h>
#include "2443addr.h"
//#include "utils.h"
#include "nand.h"
#include "def.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_ECC_DEC_ERROR()			((rNFECCERR0>>26)&0x7)
#define NF_ECC_ERR0()				(rNFECCERR0)
#define NF_ECC_ERR1()				(rNFECCERR1)
#define NF_ECC_ERR_PATTERN()		(rNFMLCBITPT)
#if	0	// Busy Check using RnB Pin

#define NF_WAIT_RnB(bank)	{	\
								while(!(rNFSTAT&NF_RNB_READY));	\
							}
#else	// Busy Check using I/O[6] Pin (Need Dummy READ Command)
#define NF_WAIT_RnB(bank)	{	\
								NF_CMD(CMD_READ_STATUS);		\
								while(!(NF_DATA_R()&0x40));			\
							}
#endif

#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_468Byte_AllFF(void);

void NAND_Init(void)
{
	// Initialize NAND Flash Controller for MLC NAND Flash
	rNFCONF = NF_4BIT_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

	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);
}

/*
UINT32 Read_Sector(UINT32 nBank, UINT32 nPpn, UINT32 nSctOffset, UINT8* pBuf, pSECCCxt pSpareCxt, BOOL32 bCheckAllFF)
{
	UINT32 nOffSet;
	UINT32 nRet = 0;

	//NAND_MSG((_T("[FIL]++Read_Sector(%d, %d)\n\r"), nPpn, nSctOffset));

	// Move pointer to Sector Offset
	nOffSet = nSctOffset*NAND_SECTOR_SIZE;

	// Random data output command
	NF_CMD(CMD_RANDOM_DATA_OUTPUT);
	NF_ADDR(nOffSet&0xFF);
	NF_ADDR((nOffSet>>8)&0xFF);
	NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM);

	// Initialize 4-bit ECC Decoding
	NF_SET_ECC_DEC();
	NF_MECC_Reset();
	NF_MECC_UnLock();

	// Read 512 bytes Sector data
	_Read_512Byte(pBuf+NAND_SECTOR_SIZE*nSctOffset);

	//NF_MECC_Lock();	// Do NOT Lock MECC when using 4-bit ECC Decoding

	NF_CLEAR_ECC_DEC_DONE();

	//NF_CE_H(nBank);
	NF_SET_CLK(DUMMY_R_TACLS, DUMMY_R_TWRPH0, DUMMY_R_TWRPH1);		// Don't set clk to (0, 0, 0) !!! Decoding error occurs

	// Instead of Read Main ECC from NAND, Write Main ECC with CE don't care
	if (bCheckAllFF)
	{
		NF_DATA_W4(0xC633ECD7);	// All 0xFF ECC
		NF_DATA_W4(0x00805369);
	}
	else
	{
		NF_DATA_W4(pSpareCxt->aMECC[nSctOffset*2]);
		NF_DATA_W4(pSpareCxt->aMECC[nSctOffset*2+1]);
	}

	NF_SET_CLK(DEFAULT_TACLS, DEFAULT_TWRPH0, DEFAULT_TWRPH1);
	NF_CE_L(nBank);

	// Waiting for Main ECC compare
	NF_WAIT_ECC_DEC_DONE();

	nRet = Decoding_MainECC(pBuf+NAND_SECTOR_SIZE*nSctOffset);

	if (nRet&ECC_UNCORRECTABLE_ERROR)
	{
		//NAND_ERR((_T("[FIL:ERR] Read_Sector() : ECC Uncorrectable Error in Page %d Sector %d\n\r"), nPpn, nSctOffset));
	}
	else if (nRet&ECC_CORRECTABLE_ERROR)
	{
		//NAND_MSG((_T("[FIL] Read_Sector() : ECC Correctable Error in Page %d Sector %d\n\r"), nPpn, nSctOffset));
	}

	//NAND_MSG((_T("[FIL]--Read_Sector()\n\r")));

	return nRet;
}

UINT32 Decoding_MainECC(UINT8* pBuf)
{
	UINT32 nError0, nError1;
	UINT32 nErrorCnt, nErrorByte, nErrorPattern;
	UINT32 nRet = 0;

	//NAND_MSG((_T("[FIL]++Decoding_MainECC()\n\r")));

	nError0 = NF_ECC_ERR0();
	nError1 = NF_ECC_ERR1();

	//NAND_MSG((_T("[FIL] NF_ECC_ERR0 = 0x%08x()\n\r"), nError0));
	//NAND_MSG((_T("[FIL] NF_ECC_ERR1 = 0x%08x()\n\r"), nError1));

		nErrorCnt = (nError0>>26)&0x7;

		if (nErrorCnt == 0)			// No Error
		{
			//NAND_MSG((_T("[FIL] Decoding_MainECC() : No ECC Error\n\r")));
		}
		else	 if (nErrorCnt > 4)			// Uncorrectable Error
		{
			//NAND_ERR((_T("[FIL:ERR] Decoding_MainECC() : Uncorrectable Error\n\r")));
			nRet = ECC_UNCORRECTABLE_ERROR;
		}
		else							// Correctable Error
		{
			//NAND_MSG((_T("[FIL] Decoding_MainECC() : Correctable Error %d bit\n\r"), nErrorCnt));

			nErrorPattern = NF_ECC_ERR_PATTERN();

			// 1st Bit Error Correction
			nErrorByte = nError0&0x3ff;
		if (nErrorByte < 512)
		{
			//NAND_ERR((_T("[FIL] Decoding_MainECC() : 1st Error Buf[%d] [%02x]->"), nErrorByte, pBuf[nErrorByte]));
			pBuf[nErrorByte] = pBuf[nErrorByte]^(nErrorPattern&0xff);
			//NAND_ERR((_T("[%02x]\n\r"), pBuf[nErrorByte]));
		}

			if (nErrorCnt > 1)
			{
				// 2nd Bit Error Correction
				nErrorByte = (nError0>>16)&0x3ff;
			if (nErrorByte < 512)
			{
				//NAND_ERR((_T("[FIL] Decoding_MainECC() : 2nd Error Buf[%d] [%02x]->"), nErrorByte, pBuf[nErrorByte]));
				pBuf[nErrorByte] = pBuf[nErrorByte]^((nErrorPattern>>8)&0xff);
				//NAND_ERR((_T("[%02x]\n\r"), pBuf[nErrorByte]));
			}

				if (nErrorCnt > 2)
				{
					// 3rd Bit Error Correction
					nErrorByte = nError1&0x3ff;
				if (nErrorByte < 512)
				{
					//NAND_ERR((_T("[FIL] Decoding_MainECC() : 3rd Error Buf[%d] [%02x]->"), nErrorByte, pBuf[nErrorByte]));
					pBuf[nErrorByte] = pBuf[nErrorByte]^((nErrorPattern>>16)&0xff);
					//NAND_ERR((_T("[%02x]\n\r"), pBuf[nErrorByte]));
				}

					if (nErrorCnt > 3)
					{
						// 4 th Bit Error Correction
						nErrorByte = (nError1>>16)&0x3ff;
					if (nErrorByte < 512)
					{
						//NAND_ERR((_T("[FIL] Decoding_MainECC() : 4th Error Buf[%d] [%02x]->"), nErrorByte, pBuf[nErrorByte]));
						pBuf[nErrorByte] = pBuf[nErrorByte]^((nErrorPattern>>24)&0xff);
						//NAND_ERR((_T("[%02x]\n\r"), pBuf[nErrorByte]));
					}
					}
				}
			}

			nRet = ECC_CORRECTABLE_ERROR;
		}

	//NAND_MSG((_T("[FIL]--Decoding_MainECC()\n\r")));

	return nRet;
}
*/


/*
BOOL
NAND_Read(DWORD nBank, DWORD nPpn, unsigned char *pDBuf)
{
	UINT32 nPbn;
	UINT32 nPOffset;

	UINT32 nPageReadStatus = 0;
	UINT32 nPageReadStatus1st = 0;
	UINT32 nPageReadStatus2nd = 0;
	UINT32 nCnt;
	UINT32 nRet = 0; 

	BOOL32 bECCErr = 0;
	BOOL32 bPageClean = 1;		// When the data is all 0xFF, regard the page as clean
	BOOL32 bIsSBufNull = 0;	// When the pSBuf is NULL, set to check whether the page is clean or not

	BOOL32 bRetry = 1;

	UINT32  nLoopCount;
	UINT32  nVBank;
	UINT32  nPairBank;

	pSECCCxt pSpareCxt;
	
	SECCCxt SpareCxt;
	
	nVBank = nBank;	// Do not change nank before copy to nVBank

	NAND_Sync(nVBank, 0);

_B_SecondRead:	// back here again for read right plane

	//if(pSBuf == 0x0)
	//{
	//	pSBuf = aTempSBuf;
	//	bIsSBufNull = 1;
	//}

	pSpareCxt = &SpareCxt;

	// Chip Select
	NF_CE_L(nBank);

	// Read Command (Always read spare area before main area in a page
	NF_CMD(CMD_READ);
	NF_SET_ADDR(nPpn, NAND_MAINPAGE_SIZE);
	NF_CMD(CMD_READ_CONFIRM);

	NF_WAIT_RnB(nBank);

		// Dummy Command to Set Proper Pointer to Read Position after NF_WAIT_RnB()
	NF_CMD(CMD_READ);

	// Read Spare Area
	//nRet = Read_Spare(nBank, nPpn, pSpareCxt);
	//if ((nRet & ECC_UNCORRECTABLE_ERROR) == 0)
	//{
		nPageReadStatus = (nRet<<16);

		// Read Main Area
		if(pDBuf != 0x00)
		{
			for (nCnt=0; nCnt<4; nCnt++)
			{
				nRet = Read_Sector(nBank, nPpn, nCnt, pDBuf, pSpareCxt, bPageClean);
				nPageReadStatus |= (nRet<<(nCnt*4));
			}
		}
	//}

	// Chip Unselect
	NF_CE_H(nBank);

}
*/

//////////////
/*
BOOL NAND_Read(DWORD dwBank, DWORD dwPage, unsigned char *pBuf)
{
	DWORD SpareCxt[11];	// 3 word spare context, 8 word main ECC
	DWORD dwOffset;
	DWORD dwCnt;
	BOOL bRet = FALSE;

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

	//if (Read_Spare(dwBank, dwPage, SpareCxt, FALSE))
	//{
	//	if (Read_Spare(dwBank, dwPage, SpareCxt, TRUE))
	//	{
	//		// Uncorrectable Error
	//		return TRUE;
	//	}
	//}

	// Read Main Area
	for (dwCnt=0; dwCnt<4; dwCnt++)
	{
		nRet = Read_Sector(nBank, nPpn, dwCnt, pDBuf, pSpareCxt, bPageClean);
		nPageReadStatus |= (nRet<<(nCnt*4));
	}

	// Chip Unselect
	NF_CE_H(dwBank);

	return bRet;
}
*/


BOOL NAND_Read(DWORD dwBank, DWORD dwPage, unsigned char *pBuf)
{
	DWORD SpareCxt[11];	// 3 word spare context, 8 word main ECC
	DWORD dwOffset;
	DWORD dwCnt;
	BOOL bRet = FALSE;

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

	if (Read_Spare(dwBank, dwPage, SpareCxt, FALSE))
	{
		if (Read_Spare(dwBank, dwPage, SpareCxt, TRUE))
		{
			// Uncorrectable Error
			return TRUE;
		}
	}

	// Read Main Area
	for (dwCnt=0; dwCnt<4; dwCnt++)
	{
		dwOffset = NAND_SECTOR_SIZE*dwCnt;

		// Random data output command
		NF_CMD(CMD_RANDOM_DATA_OUTPUT);
		NF_ADDR(dwOffset&0xFF);
		NF_ADDR((dwOffset>>8)&0xFF);
		NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM);

		// Initialize 4-bit ECC Decoding
		NF_SET_ECC_DEC();
		NF_MECC_Reset();
		NF_MECC_UnLock();

		_Read_512Byte(pBuf+NAND_SECTOR_SIZE*dwCnt);

		//NF_MECC_Lock();	// Do NOT Lock MECC when using 4-bit ECC Decoding

		// Read 7 bytes ECC for Sector
		NF_CLEAR_ECC_DEC_DONE();
		
		NF_CE_H(dwBank);
		NF_SET_CLK(DUMMY_R_TACLS, DUMMY_R_TWRPH0, DUMMY_R_TWRPH1);		// Don't set clk to (0, 0, 0) !!! Decoding error occurs

		NF_DATA_W4(SpareCxt[dwCnt*2+3]);
		NF_DATA_W4(SpareCxt[dwCnt*2+4]);

		NF_SET_CLK(DEFAULT_TACLS, DEFAULT_TWRPH0, DEFAULT_TWRPH1);
		NF_CE_L(dwBank);
		
		NF_WAIT_ECC_DEC_DONE();

		if (Decoding_ECC(pBuf+NAND_SECTOR_SIZE*dwCnt, 512))
		{
			// Uncorrectable ECC Error
			bRet = TRUE;
		}
	}

	// Chip Unselect
	NF_CE_H(dwBank);

	return bRet;
}


BOOL Read_Spare(DWORD dwBank, DWORD dwPage, DWORD *pSpareCxt, BOOL bSecondTry)
				{
	DWORD dwOffset;
	BOOL bRet = FALSE;
	int i;

	dwOffset = NAND_MAINPAGE_SIZE+NAND_SCXT_OFFSET;	// Position to SpareContext (Skipped BadMark, CleanMark, 2 byte Reserved)

	if (bSecondTry)
{
	// Random data output command
	NF_CMD(CMD_RANDOM_DATA_OUTPUT);
		NF_ADDR(dwOffset&0xFF);
		NF_ADDR((dwOffset>>8)&0xFF);
	NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM);
	}
	else
	{
		NF_CMD(CMD_READ);
		NF_SET_ADDR(dwPage, dwOffset);
		NF_CMD(CMD_READ_CONFIRM);
		NF_WAIT_RnB(dwBank);

		// Dummy Command to Set Proper Pointer to Read Position after NF_WAIT_RnB()
		NF_CMD(CMD_READ);
	}

	// Initialize 4-bit ECC Decoding
	NF_SET_ECC_DEC();
	NF_MECC_Reset();
	NF_MECC_UnLock();

	for (i=0; i<11; i++)
	{
		pSpareCxt[i] = NF_DATA_R4();	// read 12 byte spare context
	}

	NF_CE_H(dwBank);
	NF_SET_CLK(DUMMY_R_TACLS, DUMMY_R_TWRPH0, DUMMY_R_TWRPH1);		// Don't set clk to (0, 0, 0) !!! Decoding error occurs
	_Write_Dummy_468Byte_AllFF();
	NF_SET_CLK(DEFAULT_TACLS, DEFAULT_TWRPH0, DEFAULT_TWRPH1);
	NF_CE_L(dwBank);

	//NF_MECC_Lock();	// Do NOT Lock MECC when using 4-bit ECC Decoding

	// Read Spare ECC
	NF_CLEAR_ECC_DEC_DONE();

	if (bSecondTry)
	{
		dwOffset = NAND_MAINPAGE_SIZE+NAND_SECC2_OFFSET;	// Position to Spare ECC 2nd copy
	// Random data output command
	NF_CMD(CMD_RANDOM_DATA_OUTPUT);
		NF_ADDR(dwOffset&0xFF);
		NF_ADDR((dwOffset>>8)&0xFF);
	NF_CMD(CMD_RANDOM_DATA_OUTPUT_CONFIRM);

	}

	NF_DATA_R4();			// 8 byte Spare ECC data
	NF_DATA_R4();			// Actually after read 7th byte, ECC decoding starts!!

	// Wait Spare ECC Compare Done
	NF_WAIT_ECC_DEC_DONE();

	return Decoding_ECC((UINT8 *)pSpareCxt, 44);
}


BOOL Decoding_ECC(UINT8* pBuf, DWORD nValidBufLength)
{
	UINT32 nError0, nError1;
	UINT32 nErrorCnt;
	UINT32 nRet = 0;

	nError0 = NF_ECC_ERR0();
	nError1 = NF_ECC_ERR1();

	nErrorCnt = (nError0>>26)&0x7;

	if (nErrorCnt == 0)
	{
		// No ECC Error
		return FALSE;
	}
	else if (nErrorCnt > 4)
	{
		// Uncorrectable ECC Error
		return TRUE;
	}
	else		// Check ECC error occurs in first 32 bytes (468 byte is Dummy 0xFF)
	{
		UINT32 nErrorByte, nErrorPattern;

		nErrorPattern = NF_ECC_ERR_PATTERN();

		// 1st Bit Error Correction
		nErrorByte = nError0&0x3ff;
		if (nErrorByte < nValidBufLength)
		{
			pBuf[nErrorByte] = pBuf[nErrorByte]^(nErrorPattern&0xff);
		}
		else if (nErrorByte < 512)
		{
			// Error in Dummy
			return FALSE;
		}

		if (nErrorCnt > 1)
		{
			// 2nd Bit Error Correction
			nErrorByte = (nError0>>16)&0x3ff;
			if (nErrorByte < nValidBufLength)
			{
				pBuf[nErrorByte] = pBuf[nErrorByte]^((nErrorPattern>>8)&0xff);
			}
			else if (nErrorByte < 512)
			{
				// Error in Dummy
				return FALSE;
			}

			if (nErrorCnt > 2)
			{
				// 3rd Bit Error Correction
				nErrorByte = nError1&0x3ff;
				if (nErrorByte < nValidBufLength)
				{
					pBuf[nErrorByte] = pBuf[nErrorByte]^((nErrorPattern>>16)&0xff);
				}
				else if (nErrorByte < 512)
				{
					// Error in Dummy
					return FALSE;
				}

				if (nErrorCnt > 3)
				{
					// 4 th Bit Error Correction
					nErrorByte = (nError1>>16)&0x3ff;
					if (nErrorByte < nValidBufLength)
					{
						pBuf[nErrorByte] = pBuf[nErrorByte]^((nErrorPattern>>24)&0xff);
					}
					else if (nErrorByte < 512)
					{
						// Error in Dummy
						return FALSE;
					}
				}
			}
		}

		// Correctable ECC Error
		return FALSE;
	}
}


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 + -