📄 nand.c
字号:
NF_CMD(Controller, 0x80); // 1st Write command
NF_ADDR(Controller, 0);
NF_ADDR(Controller, 0);
NF_ADDR(Controller, uBlockPage&0xff); //
NF_ADDR(Controller, (uBlockPage>>8)&0xff); // Block & Page num.
NF_ADDR(Controller, (uBlockPage>>16)&0xff); //
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) // MLC ECC Size : 512bytes
{
NF_WRDATA8(Controller, *pBuffer++); // Write one page
}
#else
for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++)
{
NF_WRDATA(Controller, *pBufferW++); // Write one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
pBufferW += NAND_MLC_TRANS_SIZE/4;
#endif
//NF_MECC_Lock(Controller);
while(!g_Nand_4bitEccEncDone);
uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;
aNand_Spare_Data[1]=(u8)(uMecc0&0xff);
aNand_Spare_Data[2]=(u8)((uMecc0>>8) & 0xff);
aNand_Spare_Data[3]=(u8)((uMecc0>>16) & 0xff);
aNand_Spare_Data[4]=(u8)((uMecc0>>24) & 0xff);
aNand_Spare_Data[5]=(u8)(uMecc1&0xff);
aNand_Spare_Data[6]=(u8)((uMecc1>>8) & 0xff);
aNand_Spare_Data[7]=(u8)((uMecc1>>16) & 0xff);
//////////////////////////
// Write 512 ~ 1023
//////////////////////////
g_Nand_4bitEccEncDone = 0;
NF_RSTECC(Controller); // Initialize ECC
#if (NAND_REG_BUG == TRUE)
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
#endif
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) // MLC ECC Size : 512bytes
{
NF_WRDATA8(Controller, *pBuffer++); // Write one page
}
#else
for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++)
{
NF_WRDATA(Controller, *pBufferW++); // Write one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
pBufferW += NAND_MLC_TRANS_SIZE/4;
#endif
while(!g_Nand_4bitEccEncDone);
uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;
aNand_Spare_Data[8]=(u8)(uMecc0&0xff);
aNand_Spare_Data[9]=(u8)((uMecc0>>8) & 0xff);
aNand_Spare_Data[10]=(u8)((uMecc0>>16) & 0xff);
aNand_Spare_Data[11]=(u8)((uMecc0>>24) & 0xff);
aNand_Spare_Data[12]=(u8)(uMecc1&0xff);
aNand_Spare_Data[13]=(u8)((uMecc1>>8) & 0xff);
aNand_Spare_Data[14]=(u8)((uMecc1>>16) & 0xff);
//////////////////////////
// Write 1024 ~ 1535
//////////////////////////
g_Nand_4bitEccEncDone = 0;
NF_RSTECC(Controller); // Initialize ECC
#if (NAND_REG_BUG == TRUE)
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
#endif
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) // MLC ECC Size : 512bytes
{
NF_WRDATA8(Controller, *pBuffer++); // Write one page
}
#else
for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++)
{
NF_WRDATA(Controller, *pBufferW++); // Write one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
pBufferW += NAND_MLC_TRANS_SIZE/4;
#endif
while(!g_Nand_4bitEccEncDone);
uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;
aNand_Spare_Data[15]=(u8)(uMecc0&0xff);
aNand_Spare_Data[16]=(u8)((uMecc0>>8) & 0xff);
aNand_Spare_Data[17]=(u8)((uMecc0>>16) & 0xff);
aNand_Spare_Data[18]=(u8)((uMecc0>>24) & 0xff);
aNand_Spare_Data[19]=(u8)(uMecc1&0xff);
aNand_Spare_Data[20]=(u8)((uMecc1>>8) & 0xff);
aNand_Spare_Data[21]=(u8)((uMecc1>>16) & 0xff);
//////////////////////////
// Write 1536 ~ 2047
//////////////////////////
g_Nand_4bitEccEncDone = 0;
NF_RSTECC(Controller); // Initialize ECC
#if (NAND_REG_BUG == TRUE)
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<12)|(1<<13); // 4bit ECC decoding/encoding Interrupt enable...because error
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
#endif
#if NAND_TRANSFER_MODE == POLLING_TRANSFER
#if 0
for(i=0 ; i<NAND_MLC_TRANS_SIZE ; i++) // MLC ECC Size : 512bytes
{
NF_WRDATA8(Controller, *pBuffer++); // Write one page
}
#else
for(i=0 ; i<NAND_MLC_TRANS_SIZE/4 ; i++)
{
NF_WRDATA(Controller, *pBufferW++); // Write one page
}
#endif
#elif NAND_TRANSFER_MODE == DMA_TRANSFER
Nand_DmaDone = 0;
DMACH_Setup(DMA_A, 0x0, (u32)pBufferW, 0, (u32)(&(NAND(Controller)->rNFDATA)), 1, WORD, NAND_MLC_TRANS_SIZE/4, DEMAND, MEM, DMA1_NAND_RX, BURST128, &g_oNandDmac1);
DMACH_Start(&g_oNandDmac1);
while(!Nand_DmaDone);
pBufferW += NAND_MLC_TRANS_SIZE/4;
#endif
while(!g_Nand_4bitEccEncDone);
uMecc0 = Inp32(&(NAND(Controller)->rNFMECC0));
uMecc1 = Inp32(&(NAND(Controller)->rNFMECC1)) & 0xFFFFFF;
aNand_Spare_Data[22]=(u8)(uMecc0&0xff);
aNand_Spare_Data[23]=(u8)((uMecc0>>8) & 0xff);
aNand_Spare_Data[24]=(u8)((uMecc0>>16) & 0xff);
aNand_Spare_Data[25]=(u8)((uMecc0>>24) & 0xff);
aNand_Spare_Data[26]=(u8)(uMecc1&0xff);
aNand_Spare_Data[27]=(u8)((uMecc1>>8) & 0xff);
aNand_Spare_Data[28]=(u8)((uMecc1>>16) & 0xff);
//////////////////////////
// Spare Area Write
//////////////////////////
for(i=0 ; i<uSpareSize ; i++)
NF_WRDATA8(Controller, aNand_Spare_Data[i]);
NF_CMD(Controller, 0x10); // 2nd Write Command
while(!g_Nand_RnBTransition)
{
if(g_Nand_IllegalAccError == 1)
{
NAND_Reset(Controller);
g_Nand_IllegalAccError = 0;
return eNAND_ProgramError;
}
}
//Read Program Status
NF_CMD(Controller, 0x70);
while(!((uStatus = NF_RDDATA8(Controller)) & (1<<6)));
if(uStatus & 0x01)
eError = eNAND_ProgramError; // Error in Program
else
eError = eNAND_NoError;
NF_nFCE_H(Controller);
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp &= ~((1<<13)|(1<<12)|(1<<10)|(1<<9)); // 4bit ECC encoding & Illegal Access & RnB Transition Interrupt disable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
if(NAND_Inform[Controller].uPerformanceCheck == 0)
{
if(NAND_Inform[Controller].uECCtest == 1)
{
for(i=0 ; i<uSpareSize ; i++)
aNand_Spare_Data_Temp[i] = aNand_Spare_Data[i];
}
for(i=0 ; i<uSpareSize ; i++)
*aSpareBuffer++ = aNand_Spare_Data[i];
}
INTC_Disable(NUM_NFC);
return eError;
}
//////////
// Function Name : NAND_WritePage
// Function Description : This function write the 1 page data of external MLC Type NAND device
// Input : Controller - Nand Controller Port Number
// uBlock - Write Block
// uPage - Write Page
// pBuffer - Write data buffer
// Output : Nand Error Type
NAND_eERROR NAND_WritePage(u32 Controller, u32 uBlock, u32 uPage, u8 *pBuffer, u8 *aSpareBuffer)
{
NAND_eERROR eError;
if( (NAND_Inform[Controller].uNandType == NAND_Normal8bit) || (NAND_Inform[Controller].uNandType == NAND_Advanced8bit) )
eError = NAND_WritePageSLC(Controller, uBlock, uPage, pBuffer, aSpareBuffer);
else //if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
eError = NAND_WritePageMLC(Controller, uBlock, uPage, pBuffer, aSpareBuffer);
return eError;
}
//////////
// Function Name : NAND_EraseSingleBlock
// Function Description : This function erase 1 block data
// Input : Controller - Nand Controller Port Number
// uBlock - Erase Block
// Output : Nand Error Type
NAND_eERROR NAND_EraseSingleBlock(u32 Controller, u32 uBlock)
{
u32 uTemp, uBlockPage, uStatus;
NAND_eERROR eError;
if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
{
uBlockPage=(uBlock<<5);
}
else if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
{
uBlockPage=(uBlock<<6);
}
else //if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
{
uBlockPage=(uBlock<<7);
}
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<10) | (1<<9); // Illegal Access & RnB Transition Interrupt enable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
Outp32(&(NAND(Controller)->rNFSTAT), (1<<5)|(1<<4)); // Illegal Access & RnB Interrupt Pending bit clear
INTC_Enable(NUM_NFC);
//Invalid Block Check
eError = NAND_CheckInvalidBlock(Controller, uBlockPage);
if(eError != eNAND_NoError)
return eError;
g_Nand_RnBTransition = 0;
g_Nand_IllegalAccError = 0;
NF_nFCE_L(Controller);
NF_CLEAR_RnB(Controller);
NF_CMD(Controller, 0x60); // 1st Erase Command
NF_ADDR(Controller, uBlockPage&0xff); // The mark of bad block is in 0 page
NF_ADDR(Controller, (uBlockPage>>8)&0xff); // For block number A[24:17]
NF_ADDR(Controller, (uBlockPage>>16)&0xff); // For block number A[25]
NF_CMD(Controller, 0xd0); // 2nd Erase command
while(!g_Nand_RnBTransition)
{
if(g_Nand_IllegalAccError == 1)
{
NAND_Reset(Controller);
g_Nand_IllegalAccError = 0;
return eNAND_EraseError;
}
}
NF_CMD(Controller, 0x70); // Read status command
while(!((uStatus = NF_RDDATA8(Controller)) & (1<<6)));
if(uStatus & 0x01)
eError = eNAND_EraseError; // Error in Program
else
eError = eNAND_NoError;
// if (NF_RDDATA8(Controller)&0x1) // Erase error check
// eError = eNAND_EraseError;
// else
// eError = eNAND_NoError;
NF_nFCE_H(Controller);
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp &= ~((1<<10)|(1<<9)); // Illegal Access & RnB Transition Interrupt disable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
// rb1004 : must be modify...Interrupt Controller
//INT_Disable1(BIT_INT_NFC);
INTC_Disable(NUM_NFC);
return eError;
}
//////////
// Function Name : NAND_EraseMultiBlock
// Function Description : This function erase the multi-block data
// Input : Controller - Nand Controller Port Number
// uBlock - Erase Block
// uBlockNum - Erase Block Number
// Output : Nand Error Type
NAND_eERROR NAND_EraseMultiBlock(u32 Controller, u32 uBlock, u32 uBlockNum)
{
u32 i, j, uMultiEraseNum, uTemp, uStatus;
u32 uBlockShift, uBlockPage;
NAND_eERROR eError;
eError = eNAND_NoError;
if(NAND_Inform[Controller].uNandType == NAND_Normal8bit)
{
uBlockPage=(uBlock<<5);
uBlockShift = 5;
uMultiEraseNum = 4;
}
else if(NAND_Inform[Controller].uNandType == NAND_Advanced8bit)
{
uBlockPage=(uBlock<<6);
uBlockShift = 6;
uMultiEraseNum = 2;
}
else //if(NAND_Inform[Controller].uNandType == NAND_MLC8bit)
{
uBlockPage=(uBlock<<7);
uBlockShift = 7;
uMultiEraseNum = 2;
}
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp |= (1<<10) | (1<<9); // Illegal Access & RnB Transition Interrupt enable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
Outp32(&(NAND(Controller)->rNFSTAT), (1<<5)|(1<<4)); // Illegal Access & RnB Interrupt Pending bit clear
INTC_Enable(NUM_NFC);
//Invalid Block Check
for(i=uBlock ; i<(uBlock+uBlockNum-1) ; i++)
{
eError = NAND_CheckInvalidBlock(Controller, i);
if(eError != eNAND_NoError)
return eError;
}
for(i=0 ; i<uBlockNum ; i+=uMultiEraseNum )
{
g_Nand_RnBTransition = 0;
g_Nand_IllegalAccError = 0;
NF_nFCE_L(Controller);
NF_CLEAR_RnB(Controller);
for(j=0 ; j<uMultiEraseNum ; j++)
{
NF_CMD(Controller, 0x60); // 1st Erase Command
NF_ADDR(Controller, uBlockPage&0xff);
NF_ADDR(Controller, (uBlockPage>>8)&0xff);
NF_ADDR(Controller, (uBlockPage>>16)&0xff);
uBlockPage += (1<<uBlockShift);
}
NF_CMD(Controller, 0xd0); // 2nd Erase command
while(!g_Nand_RnBTransition)
{
if(g_Nand_IllegalAccError == 1)
{
NAND_Reset(Controller);
g_Nand_IllegalAccError = 0;
NF_nFCE_H(Controller);
uTemp = NAND_ReadNFCONRegister(Controller);
uTemp &= ~((1<<10)|(1<<9)); // Illegal Access & RnB Transition Interrupt disable
Outp32(&(NAND(Controller)->rNFCONT), uTemp);
INTC_Disable(NUM_NFC);
return eNAND_EraseError;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -