S3C2440-Nandflash
void NF_Init(){
//GPA 17~22接在nandflash上
rGPACON = rGPACON & ("(0x3f<<17)) | (0x3f<<17);
//TACLS為CLE/ALE有效到nWE有效之間的持續(xù)時間,TWRPH0為nWE的有效持續(xù)時間,TWRPH1為nWE無效到CLE/ALE無效之間的持續(xù)時間,這些時間都是以HCLK為單位的(本文程序中的HCLK=100MHz)
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
//非鎖定,屏蔽nandflash中斷,初始化ECC及鎖定main區(qū)和spare區(qū)ECC,使能nandflash片選及控制器
rNFCONT = (0<<13)|(0<<12)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
}
void NF_Reset(){
NF_CE_L();
NF_WAITRB();
NF_CMMD(CMD_RESET);
NF_DETECT();
NF_CE_H();
}
void NF_ReadID(){
char MID, DID, cyc3, cyc4, cyc5;
NF_CE_L();
NF_CLEARRB();
NF_CMMD(CMD_READID);
NF_ADDR(0x00);
MID = NF_RDDATA8(); //廠商ID
while(!(rUTRSTAT0&0x4));
rUTXH0 = MID;
DID = NF_RDDATA8(); //設(shè)備ID
while(!(rUTRSTAT0&0x4));
rUTXH0 = DID;
cyc3 = NF_RDDATA8(); //其他信息
while(!(rUTRSTAT0&0x4));
rUTXH0 = cyc3;
cyc4 = NF_RDDATA8();
while(!(rUTRSTAT0&0x4));
rUTXH0 = cyc4;
cyc5 = NF_RDDATA8();
while(!(rUTRSTAT0&0x4));
rUTXH0 = cyc5;
NF_CE_H();
}
U8 NF_RandomWrite(U32 pagenumber, U32 add, U8 data){ //根據(jù)時序來就行
U8 state;
NF_CE_L();
NF_CMMD(CMD_WRITE1);
NF_ADDR(0x00);
NF_ADDR(0x00);
NF_ADDR(pagenumber&0xff);
NF_ADDR((pagenumber>>8)&0xff);
NF_ADDR((pagenumber>>16)&0xff);
NF_CMMD(CMD_RANDOMWRITE);
NF_ADDR(add&0xff); //確定頁內(nèi)地址
NF_ADDR((add>>8)&0xff);
NF_WRDATA8(data); //寫數(shù)據(jù)
NF_CMMD(CMD_WRITE2);
NF_WAITRB();
NF_CMMD(CMD_READSTATE);
do{
state = NF_RDDATA8();
}while(!(state&0x40));
if(state&0x1){
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0x44;
return 0x44; //0x44隨機寫失敗
}
else{
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0x66;
return 0x66; //0x66隨機寫成功
}
}
U8 NF_RandomRead(U32 pagenumber, U32 add){ //根據(jù)時序來就行
char ch;
NF_CE_L();
NF_CMMD(CMD_READ1);
NF_ADDR(0x00);
NF_ADDR(0x00);
NF_ADDR(pagenumber&0xff);
NF_ADDR((pagenumber>>8)&0xff);
NF_ADDR((pagenumber>>16)&0xff);
NF_CMMD(CMD_READ2);
NF_WAITRB();
NF_CMMD(CMD_RANDOMREAD1);
NF_ADDR(add&0xff);
NF_ADDR((add>>8)&0xff);
NF_CMMD(CMD_RANDOMREAD2);
ch = NF_RDDATA8(); //讀數(shù)據(jù)
while(!(rUTRSTAT0&0x4));
rUTXH0 = ch;
NF_CE_H();
return ch;
}
U8 NF_IsBadBlock(U32 block){
U8 result;
result = NF_RandomRead(block*64, 2054); //0"2047是main區(qū)數(shù)據(jù),2048"2051是main區(qū)的ECC校驗,2052"2053是spare區(qū)的ECC校驗
if(result == 0x33){
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0x62;
return 0x62; //0x62是壞塊
}
else{
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0x42;
return 0x42; //0x42不是壞塊
}
}
U8 NF_MarkBadblock(U32 block){
U8 result;
result = NF_RandomWrite(block*64, 2054, 0x33); //0x33標記壞塊 block*64得到的是block塊第一個頁的地址
if(result == 0x66){
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0x61;
return 0x61; //0x61標記壞塊成功
}
else{
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0x41;
return 0x41; //0x41標記壞塊失敗
}
}
void __irq UART0_ISR(void){
U8 ch;
rSRCPND |= (0x1<<28);
rINTPND |= (0x1<<28);
rSUBSRCPND |= 0x1<<0;
if(rUTRSTAT0 & 0x1){
ch = rURXH0;
while(!(rUTRSTAT0&0x4));
rUTXH0 = ch;
cmd = ch;
}
}
int Main(){
count = 0;
rULCON0 = 0x3;
rUCON0 = (1<<11)|(1<<2)|(1<<0);
rUBRDIV0 = 26;
rSRCPND = 0x1<<28;
rINTPND = 0x1<<28;
rSUBSRCPND = 0x1<<0;
rINTMSK &= "(0x1<<28);
rINTSUBMSK &= "(0x1<<0);
pISR_UART0 = (U32)UART0_ISR;
NF_Init();
while(1){
switch(cmd){
case 0x11:
NF_Reset();
break;
case 0x22:
NF_ReadID();
break;
case 0x33:
NF_RandomRead(2001*64,0x3);
break;
case 0x44:
NF_RandomWrite(2001*64,2052,0xbc);
break;
case 0x55:
NF_PageRead(2001*64);
break;
case 0x66:
while(!(rUTRSTAT0&0x4));
rUTXH0 = 0xba;
NF_PageWrite(2001*64);
break;
case 0x77:
NF_BlockErase(2001);
break;
case 0x88:
NF_IsBadBlock(2001);
break;
case 0x99:
NF_MarkBadblock(2001);
break;
}
cmd = 0;
}
評論