📄 nand.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 + -