全部博文(92)
分类: 嵌入式
2010-06-19 20:41:44
void __irq NFCon_Int(void);
void * nand_func[][2]=
{
(void *)Print_Id, "Read ID ",
(void *)Nand_Reset, "Nand reset ",
(void *)Test_Block_Erase, "Block erase ",
(void *)Test_Page_Read, "Page read ",
(void *)Test_Page_Write, "Page write ",
(void *)PrintBadBlockNum, "Check Badblock ",
0,
};
void Test_Nand(void)
{
U8 ch;
U32 gpacon;
Uart_Printf("Nand test\n");
gpacon = rGPACON;
rGPACON = (rGPACON &~(0x3f<<17)) | (0x3f<<17);
// GPA 22 21 20 19 18 17
// nFCE nRSTOUT nFRE nFWE ALE CLE
Uart_Printf("Select Nand flash type, K9F1208(1)/K9F2G08(2) : ");
ch=Uart_Getch();
Uart_Printf("%c\n\n", ch);
switch(ch) {
case '1':
Nand_Selet = 1;
Test_K9F1208();
break;
case '2':
Nand_Selet = 2;
Test_K9F2G08();
break;
default:
break;
}
rGPACON = gpacon;
}
void Test_K9F2G08(void)
{
// int i;
U8 i;
Uart_Printf("\nK9F2G08(Large Page) Nand flash test start.\n");
InitNandFlash();
while(1)
{
PrintSubMessage();
Uart_Printf("\nSelect: ");
i = Uart_GetIntNum_GJ();
// Uart_Printf("i=%d\n",i);
if(i>=0 && (i<(sizeof(nand_func)/8)) )
( (void (*)(void)) (nand_func[i][0]) )(); // execute selected function.
else
Uart_Printf("\nWrong Num!\n");
}
}
void PrintSubMessage(void)
{
int i;
i=0;
Uart_Printf("\n");
while(1)
{ //display menu
Uart_Printf("%2d:%s\n",i,nand_func[i][1]);
i++;
if((int)(nand_func[i][0])==0)
{
Uart_Printf("\n");
break;
}
}
}
初始化NAND FLASH仅仅是做最简单的配置,通过#define的形式
static void InitNandCfg(void)
{
// for S3C2440
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
//Nand Flash configuration Register,主要配置三个时序
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
//Nand Flash control Register,
}
#define EnNandFlash() (rNFCONF |= (1<<0)) //bit0=1 enable NAND flash controller
#define DsNandFlash() (rNFCONF &= ~(1<<0)) //bit0=1 disable NAND flash controller
#define InitEcc() (rNFCONT |= (1<<4)) //bit4=1 initialize ECC
#define NoEcc() (rNFCONT &= ~(1<<4)) //bit4=0 initialize ECC
#define NF_ChipEn() (rNFCONT&=~(1<<1)) //bit1=0 NAND flash nFCE = L (active)
#define NF_ChipDs() (rNFCONT|=(1<<1)) //bit1=1 NAND flash nFCE = H (inactive)
#define NF_MECC_UnLock() {rNFCONT&=~(1<<5);}
#define NF_MECC_Lock() {rNFCONT|=(1<<5);}
#define NF_SECC_UnLock() {rNFCONT&=~(1<<6);}
#define NF_SECC_Lock() {rNFCONT|=(1<<6);}
//Nand Flash Command Register(NFCMMD)
#define NF_CMD(cmd) {rNFCMD=cmd;}
#define READCMD0 0 //Read0 model command == Page addr 0~127
#define READCMD1 1 //Read1 model command == Page addr 128~511
#define READCMD2 0x50 //Read2 model command == Page addr 512~527
#define READCMD3 0x30 //Read3 model for Large Page
#define ERASECMD0 0x60 //Block erase command 0
#define ERASECMD1 0xd0 //Block erase command 1
#define PROGCMD0 0x80 //page write command 0
#define PROGCMD1 0x10 //page write command 1
#define QUERYCMD 0x70 //query command
#define RdIDCMD 0x90 //read id command
#define RESETCMD 0xFF //reset command
这里的设置是根据K9F2G08UXA开发手册:
//Nand Flash Data Register,(这个寄存器只用低8位)
#define NF_RDDATA() (rNFDATA)
U16 Read_Status(void)
{
U16 stat;
int i;
NF_ChipEn();
NF_CMD(QUERYCMD);
for(i=0; i<10; i++);
stat = NF_RDDATA();
NF_ChipDs();
return stat;
}
1. 擦除操作
static int EraseBlock_2G08(U32 block)
{
U32 blockPage=(block<<5);
int i;
//启动NAND FLASH 中断
NFConDone=0;
rNFCONT|=(1<<9);
rNFCONT|=(1<<10);
pISR_NFCON= (unsigned)NFCon_Int;
rSRCPND=BIT_NFCON;
rINTMSK=~(BIT_NFCON);
#if BAD_CHECK
if(IsBadBlock_2G08(block))
return FAIL;
#endif
NF_ChipEn();
NF_CMD(ERASECMD0);
// Erase one block 1st command, Block Addr:A9-A25(2048个Blocks)
// Address 3-cycle
NF_ADDR(blockPage&0xff); // Page number=0
NF_ADDR((blockPage>>8)&0xff);
NF_ADDR((blockPage>>16)&0xff);
NF_CLEAR_RB();
NF_CMD(ERASECMD1); // Erase one blcok 2nd command
while(NFConDone==0);
rNFCONT&=~(1<<9);
rNFCONT&=~(1<<10); // Disable Illegal Access Interrupt
if(rNFSTAT&0x8)
return FAIL;
NF_CMD(QUERYCMD); // Read status command状态被放到rNFDATA中
if (NF_RDDATA()&0x1) // Erase error
{
NF_ChipDs();
Uart_Printf("[ERASE_ERROR:block#=%d]\n",block);
// MarkBadBlock_1208(block);
return FAIL;
}
else
{
NF_ChipDs();
return OK;
}
}
2. 读操作
static int ReadPage_2G08(U32 block,U32 page,U8 *buffer)
{
int i;
unsigned int blockPage;
U32 Mecc, Secc;
U8 *bufPt=buffer;
U8 se[64], ecc0, ecc1, ecc2, ecc3,a,b,c,d,e;
blockPage=(block<<5)+page;
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_ChipEn();
NF_CLEAR_RB();
NF_CMD(READCMD0); // Read command
NF_ADDR(0); // Column = 0
NF_ADDR(0);
NF_ADDR(blockPage&0xff); //
NF_ADDR((blockPage>>8)&0xff); // Block & Page num.
NF_ADDR((blockPage>>16)&0xff); //
NF_CMD(READCMD3);
NF_DETECT_RB();
for(i=0;i<2048;i++)
{
*bufPt++=NF_RDDATA8(); // Read one page,2k大小
}
}