📄 k9k2g16.c
字号:
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
0xffffffff,0xffffffff,0xffffffff,0xffffffff,
0xffffffff,0xffffffff,0xffffffff,0xffffffff
};
void InputTargetBlock16(void)
{
U32 no_block, no_page, no_byte;
Uart_Printf("\nSource size:0h~%xh\n",downloadProgramSize);
Uart_Printf("\nAvailable target block number: 0~2048\n");
Uart_Printf("Input target block number:");
targetBlock=Uart_GetIntNum(); // Block number(0~4095)
if(targetSize==0)
{
#if 0
Uart_Printf("Input target size(0x4000*n):");
targetSize=Uart_GetIntNum(); // Total byte size
#else
Uart_Printf("Input program file size(bytes): ");
targetSize=Uart_GetIntNum(); // Total byte size
#endif
}
no_block = (U32)((targetSize/2048)/64);
no_page = (U32)((targetSize/2048)%64);
no_byte = (U32)(targetSize%2048);
Uart_Printf("File:%d[%d-block,%d-page,%d-bytes].\n", targetSize, no_block, no_page, no_byte);
}
static int NF16_EraseBlock(U32 block)
{
U32 blockPage=(block<<6);
int i;
NFConDone16=0;
rNFCONT|=(1<<9); //Enable RnB Interrupt
rNFCONT|=(1<<10); //Enable Illegal Access Interrupt
pISR_NFCON= (unsigned)NFCon_Int16;
rSRCPND=BIT_NFCON;
rINTMSK=~(BIT_NFCON);
#if BAD_CHECK
if(NF16_IsBadBlock(block))
return FAIL;
#endif
NF_nFCE_L();
NF_CMD(0x60); // Erase one block 1st command, Block Addr:A11-A27
// Address 3-cycle
NF_ADDR(blockPage&0xff); // A[18:11]
NF_ADDR((blockPage>>8)&0xff); // A[26:19]
NF_ADDR((blockPage>>16)&0xff); // A27
NF_CLEAR_RB();
NF_CMD(0xd0); // Erase one blcok 2nd command
while(NFConDone16==0);
rNFCONT&=~(1<<9); // Disable RnB Interrupt
rNFCONT&=~(1<<10); // Disable Illegal Access Interrupt
if(rNFSTAT&0x8) return FAIL;
NF_CMD(0x70); // Read status command
if (NF_RDDATA()&0x1) // Erase error
{
NF_nFCE_H();
Uart_Printf("[ERASE_ERROR:block#=%d]\n",block);
// NF16_MarkBadBlock(block);
return FAIL;
}
else
{
NF_nFCE_H();
return OK;
}
}
void __irq NFCon_Int16(void)
{
NFConDone16=1;
rINTMSK|=BIT_NFCON;
ClearPending(BIT_NFCON);
if(rNFSTAT&0x8) Uart_Printf("Illegal Access is detected!!!\n");
// else Uart_Printf("RnB is Detected!!!\n");
}
static int NF16_IsBadBlock(U32 block)
{
int i;
unsigned int blockPage;
U32 bad_block_data;
blockPage=(block<<6); // For 2'nd cycle I/O[7:5]
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0x00); // read command
NF_ADDR((1024+6)&0xff); // 2060 = 0x080c
NF_ADDR(((1024+6)>>8)&0xff); // A[10:8]
NF_ADDR((blockPage)&0xff); // A[11;18]
NF_ADDR((blockPage>>8)&0xff); // A[26:19]
NF_ADDR((blockPage>>16)&0xff); // A27
NF_CMD(0x30); // 2'nd command
NF_DETECT_RB(); // Wait tR(max 12us)
bad_block_data=NF_RDDATA();
NF_nFCE_H();
if(bad_block_data!=0xffffffff)
{
Uart_Printf("[ block %d has been marked as a bad block(%x)]\n",block,bad_block_data);
return FAIL;
}
else
{
return OK;
}
}
static int NF16_MarkBadBlock(U32 block)
{
int i;
U32 blockPage=(block<<6);
se16Buf[0]=0xffffffff;
se16Buf[1]=0xffffffff;
se16Buf[3]=BAD_MARK; // Bad blcok mark=0x4444
NF_nFCE_L();
NF_CMD(0x80); // Write 1st command
NF_ADDR((1024+6)&0xff); // 2060 = 0x080c
NF_ADDR(((1024+6)>>8)&0xff); // A[10:8]
NF_ADDR((blockPage)&0xff); // A[11;18]
NF_ADDR((blockPage>>8)&0xff); // A[26:19]
NF_ADDR((blockPage>>16)&0xff); // A[27]
for(i=0;i<32/2;i++) {
NF_WRDATA(se16Buf[i]); // Write spare array
}
NF_CLEAR_RB();
NF_CMD(0x10); // Write 2nd command
NF_DETECT_RB();
NF_CMD(0x70);
for(i=0;i<3;i++); //twhr=60ns////??????
if (NF_RDDATA()&0x1) // Spare arrray write error
{
NF_nFCE_H();
Uart_Printf("[Program error is occurred but ignored]\n");
}
else
{
NF_nFCE_H();
}
Uart_Printf("[block #%d is marked as a bad block]\n",block);
return OK;
}
static int NF16_ReadPage(U32 block,U32 page,U32 *buffer)
{
int i;
unsigned int blockPage;
U32 ecc_low,ecc_high;
U32 Mecc0, Mecc1, Secc;
U16 ecc0, ecc1, ecc2, ecc3;
U32 *bufPt=buffer;
U32 se[16];
blockPage=(block<<6)+page;
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0x00); // Read command
NF_ADDR(0); // Column (A[7:0]) = 0
NF_ADDR(0); // A[10:8]
NF_ADDR((blockPage)&0xff); // A[18:11]
NF_ADDR((blockPage>>8)&0xff); // A[26:19]
NF_ADDR((blockPage>>16)&0xff); // A27
NF_CMD(0x30); // 2'nd command
NF_DETECT_RB();
#if TRANS_MODE16==C_LANG
for(i=0;i<512;i++) {
*bufPt++=NF_RDDATA(); // Read one page
}
#elif TRANS_MODE16==DMA
// Nand to memory dma setting
rSRCPND=BIT_DMA0; // Init DMA src pending.
rDISRC0=NFDATA; // Nand flash data register
rDISRCC0=(0<<0) | (1<<0); //arc=AHB,src_addr=fix
rDIDST0=(unsigned)bufPt;
rDIDSTC0=(0<<1) | (0<<0); //dst=AHB,dst_addr=inc;
rDCON0=(1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(0<<23)|(1<<22)|(2<<20)|(2048/4/4);
//Handshake,AHB,interrupt,(4-burst),whole,S/W,no_autoreload,word,count=128;
// DMA on and start.
rDMASKTRIG0=(1<<1)|(1<<0);
while(!(rSRCPND & BIT_DMA0)); // Wait until Dma transfer is done.
rSRCPND=BIT_DMA0;
#endif
NF_MECC_Lock();
//ECC check by software
/*
ecc_low=rNFMECC0; // ECC 0~3 for data[7:0]
ecc_high=rNFMECC1; // ECC 3rd and 4th
#if 0
ecc0 = (U16)((ecc_high) <<8) | (U16)(ecc_low&0xff);
ecc1 = (U16)((ecc_high>>8)<<8) | (U16)((ecc_low>>8)&0xff);
ecc2 = (U16)((ecc_high>>16)<<8) | (U16)((ecc_low>>16)&0xff);
ecc3 = (U16)((ecc_high>>24)<<8) | (U16)((ecc_low>>24)&0xff);
ecc_low = (U32)ecc1<<16 | (U32)ecc0;
ecc_high = (U32)ecc3<<16 | (U32)ecc2;
#endif
for(i=0;i<16;i++) {
se[i]=NF_RDDATA(); // Read spare array with 4byte width
NF16_Spare_Data[i]=se[i];
}
//__RdPage528(pPage);
NF_nFCE_H();
if(ecc_low==se[0] && ecc_high==se[1]) {
return OK;
} else {
Uart_Printf("[ECC ERROR(RD):read:%x,%x, reg:%x,%x]\n",
se[0],se[1],ecc_low,ecc_high);
return FAIL;
}
*/
// ECC check by hardware
NF_SECC_UnLock();
Mecc0=NF_RDDATA();
Mecc1=NF_RDDATA();
NF_SECC_Lock();
rNFMECCD0=((Mecc1&0xff00)<<16)|((Mecc0&0xff00)<<8)|((Mecc1&0xff)<<8)|((Mecc0&0xff));
rNFMECCD1=(Mecc1&0xff000000)|((Mecc0&0xff000000)>>8)|((Mecc1&0xff0000)>>8)|((Mecc0&0xff0000)>>16);
NF16_Spare_Data[0]=Mecc0;
NF16_Spare_Data[1]=Mecc1;
NF16_Spare_Data[2]=NF_RDDATA();
NF16_Spare_Data[3]=NF_RDDATA();
// Uart_Printf("NFSECC:0x%x\n", rNFSECC);
Secc=NF_RDDATA();
rNFSECCD=(Secc&0xff000000)|((Secc&0xff0000)>>8)|((Secc&0xff00)<<8)|(Secc&0xff);
NF16_Spare_Data[4]=Secc;
for(i=5;i<16;i++) {
NF16_Spare_Data[i]=NF_RDDATA(); // Read spare array with 4byte width
}
NF_nFCE_H();
if (((rNFESTAT0&0xf) == 0x0) &&((rNFESTAT1&0xf) == 0x0)){
Uart_Printf("ECC OK !!!\n");
return OK;
}
else {
Uart_Printf("ECC FAIL !!!\n");
return FAIL;
}
}
static int NF16_WritePage(U32 block,U32 page,U32 *buffer)
{
int i;
U32 blockPage,Mecc0, Mecc1, Secc;
U32 *bufPt=buffer;
blockPage=(block<<6)+page;
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_nFCE_L();
NF_CMD(0x80); // Write 1st command
NF_ADDR(0); // Column (A[7:0]) = 0
NF_ADDR(0); // A[10:8]
NF_ADDR((blockPage)&0xff); // A[18:11]
NF_ADDR((blockPage>>8)&0xff); // A[26:19]
NF_ADDR((blockPage>>16)&0xff); // A7
// Write page data.
#if TRANS_MODE16==C_LANG
for(i=0;i<512;i++) {
NF_WRDATA(*bufPt++); // Write one page to NFM from buffer
}
#elif TRANS_MODE16==DMA
// Memory to Nand dma setting
rSRCPND=BIT_DMA0; // Init DMA src pending.
rDISRC0=(unsigned)bufPt; // Nand flash data register
rDISRCC0=(0<<1) | (0<<0); //arc=AHB,src_addr=inc
rDIDST0=NFDATA;
rDIDSTC0=(0<<1) | (1<<0); //dst=AHB,dst_addr=fix;
rDCON0=(1<<31)|(1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(1<<22)|(2<<20)|(2048/4);
//Handshake,AHB,interrupt,unit,whole,S/W,no_autoreload,word,count=128;
// DMA on and start.
rDMASKTRIG0=(1<<1)|(1<<0);
while(!(rSRCPND & BIT_DMA0)); // Wait until Dma transfer is done.
rSRCPND=BIT_DMA0;
#endif
/*
NF_MECC_Lock();
// Get ECC data.
se16Buf[0]=rNFMECC0; // Ecc lower
se16Buf[1]=rNFMECC1; // Ecc high
se16Buf[3]=0xffffffff; // Marking good block(lower 16-bit is valid)
//Write extra data(ECC, bad marking)
for(i=0;i<16;i++) {
NF_WRDATA(se16Buf[i]); // Write spare array(ECC and Mark)
NF16_Spare_Data[i]=se16Buf[i];
}
NF_CLEAR_RB();
NF_CMD(0x10); // Write 2nd command
NF_DETECT_RB();
NF_CMD(0x70); // Read status command
for(i=0;i<3;i++); //twhr=60ns
if (NF_RDDATA()&0x1) {// Page write error
NF_nFCE_H();
Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);
NF16_MarkBadBlock(block);
return FAIL;
} else {
NF_nFCE_H();
return OK;
}
*/
NF_MECC_Lock();
// Uart_Printf("NFMECC0:0x%x, NFMECC1:0x%x\n", rNFMECC0,rNFMECC1);
se16Buf[0]=rNFMECC0;
se16Buf[1]=rNFMECC1;
se16Buf[3]=0xffffffff; // Marking good block(lower 16-bit is valid)
// check spare ecc
NF_SECC_UnLock();
for(i=0;i<4;i++) {
NF_WRDATA(se16Buf[i]); // Write spare array(ECC and Mark)
NF16_Spare_Data[i]=se16Buf[i];
}
NF_SECC_Lock();
// Uart_Printf("NFSECC:0x%x\n", rNFSECC);
Secc=rNFSECC;
se16Buf[4]=Secc;
for(i=4;i<16;i++) {
NF_WRDATA(se16Buf[i]); // Write spare array(ECC and Mark)
NF16_Spare_Data[i]=se16Buf[i];
}
NF_CLEAR_RB();
NF_CMD(0x10); // Write 2nd command
#if 1
NF_DETECT_RB();
#else
while(!((rNFSTAT&0x4)||(rNFSTAT&0x8)));
if(rNFSTAT&0x8){
Uart_Printf("Illegal Access is detected!!!\n");
return FAIL;
}
#endif
NF_CMD(0x70); // Read status command
for(i=0;i<3;i++); //twhr=60ns
if (NF_RDDATA()&0x1) {// Page write error
NF_nFCE_H();
Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);
NF16_MarkBadBlock(block);
return FAIL;
} else {
NF_nFCE_H();
return OK;
}
}
static U32 NF16_CheckId(void)
{
int i;
U32 id;
U16 id1, id2, id3, id4;
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(0x90);
NF_ADDR(0x0);
for (i=0; i<10; i++);
//read by halfword !!!
id1 = NF_RDDATA16(); // read 4byte.
id2 = NF_RDDATA16();
id3 = NF_RDDATA16();
id4 = NF_RDDATA16();
id=((id4<<24)|(id3<<16)|(id2<<8)|id1);
NF_nFCE_H();
return id;
}
static void NF16_Init(void)
{
// for S3C2440
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(1<<0);
// TACLS [14:12] CLE&ALE duration = HCLK*TACLS.
// TWRPH0 [10:8] TWRPH0 duration = HCLK*(TWRPH0+1)
// TWRPH1 [6:4] TWRPH1 duration = HCLK*(TWRPH1+1)
// AdvFlash(R) [3] Advanced NAND, 0:256/512, 1:1024/2048
// PageSize(R) [2] NAND memory page size
// when [3]==0, 0:256, 1:512 bytes/page.
// when [3]==1, 0:1024, 1:2048 bytes/page.
// AddrCycle(R) [1] NAND flash addr size
// when [3]==0, 0:3-addr, 1:4-addr.
// when [3]==1, 0:4-addr, 1:5-addr.
// BusWidth(R/W) [0] NAND bus width. 0:8-bit, 1:16-bit.
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
// Lock-tight [13] 0:Disable lock, 1:Enable lock.
// Soft Lock [12] 0:Disable lock, 1:Enable lock.
// EnablillegalAcINT[10] Illegal access interupt control. 0:Disable, 1:Enable
// EnbRnBINT [9] RnB interrupt. 0:Disable, 1:Enable
// RnB_TrandMode[8] RnB transition detection config. 0:Low to High, 1:High to Low
// SpareECCLock [6] 0:Unlock, 1:Lock
// MainECCLock [5] 0:Unlock, 1:Lock
// InitECC(W) [4] 1:Init ECC decoder/encoder.
// Reg_nCE [1] 0:nFCE=0, 1:nFCE=1.
// NANDC Enable [0] operating mode. 0:Disable, 1:Enable.
// rNFSTAT = 0;
// Nand_Reset();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -