www.pudn.com > ARM9_PROGRAM.rar > k9s1208.c
//==================================================================== // File Name : k9s1208.c // Function : SmartMedia SAMSUNG 64MB (K9S1208) Test Program // Program : Weon-Tark Kang (Tark) // Modify : On-Pil Shin (SOP) // Date : October 23, 2002 // Version : 0.0 // History // 0.0 : Programming start -> Tark // (20030324) : Added K9S1208 Erase -> SOP //==================================================================== #include#include "def.h" #include "option.h" #include "addr.h" #include "lib.h" #include "slib.h" #define BAD_CHECK (1) #define ECC_CHECK (0) //*************** H/W dependent functions *************** void __RdPage528(U8 *pPage); void __WrPage528(U8 *pPage); static U16 NF_CheckId(void); static int NF_EraseBlock(U32 blockNum); static int NF_ReadPage(U32 block,U32 page,U8 *buffer); static int NF_WritePage(U32 block,U32 page,U8 *buffer); //buffer size is 512 bytes static int NF_IsBadBlock(U32 block); static int NF_MarkBadBlock(U32 block); static void NF_Reset(void); static void NF_Init(void); //******************************************************* int DownloadData(void); static void InputTargetBlock(void); static U32 srcAddress; static U32 targetBlock; // Block number (0 ~ 4095) static U32 targetSize; // Total byte size U32 downloadAddress; U32 downloadProgramSize=0x0; void K9S1208_Program(void) { // unsigned long interrupt_reservoir; int i; int programError=0; U8 *srcPt,*saveSrcPt; U32 blockIndex; downloadAddress=0x30100000; Uart_Printf("\n[SMC(K9S1208V0M) NAND Flash writing program]\n"); //Uart_Printf("The program buffer: 0x30100000~0x31ffffff\n"); //tark #if 0 if(!DownloadData()) { Uart_Printf("Download Fail\n"); return; } #endif NF_Init(); rINTMSK = BIT_ALLMSK; targetSize=downloadProgramSize; if(targetSize==0) { srcAddress=0x30100000; Uart_Printf("the data must be downloaded using ICE from %xh\n",srcAddress); } else srcAddress=downloadAddress+4; //to discard the data head for the size InputTargetBlock(); Uart_Printf("source base address(0x3010000x)=0x%x\n",srcAddress); Uart_Printf("target start block number =%d\n",targetBlock); Uart_Printf("target size (0x4000*n) =0x%x\n",targetSize); srcPt=(U8 *)srcAddress; blockIndex=targetBlock; while(1) { saveSrcPt=srcPt; #if BAD_CHECK if(NF_IsBadBlock(blockIndex)) // 1:bad 0:good { blockIndex++; // for next block continue; } #endif if(!NF_EraseBlock(blockIndex)) { blockIndex++; // for next block continue; } for(i=0;i<32;i++) { if(!NF_WritePage(blockIndex,i,srcPt))// block num, page num, buffer { programError=1; break; } #if ECC_CHECK if(!NF_ReadPage(blockIndex,i,srcPt)) { Uart_Printf("ECC Error(block=%d,page=%d!!!\n",blockIndex,i); } #endif srcPt+=512; // Increase buffer addr one pase size Uart_Printf("."); if((U32)srcPt>=(srcAddress+targetSize)) // Check end of buffer break; // Exit for loop } if(programError==1) { blockIndex++; srcPt=saveSrcPt; programError=0; continue; } if((U32)srcPt>=(srcAddress+targetSize)) break; // Exit while loop blockIndex++; } } //================================================================================== void K9S1208_Erase(void) { int i; U32 blockIndex=0; Uart_Printf("\n[ SMC(K9S1208V0M) NAND Flash Erase Program ]\n"); Uart_Printf("\nNow NAND Flash Erasing ....\n"); NF_Init(); rINTMSK = BIT_ALLMSK; for(blockIndex=0;blockIndex<4096;blockIndex++) { #if BAD_CHECK if(NF_IsBadBlock(blockIndex)) // 1:bad 0:good { blockIndex++; // for next block continue; } #endif if(!NF_EraseBlock(blockIndex)) { blockIndex++; // for next block continue; } } Uart_Printf("\nSMC(K9S1208V0M) NAND Flash Erase Completed !!!\n"); } //================================================================================== static void InputTargetBlock(void) { Uart_Printf("\nSource size:0h~%xh\n",downloadProgramSize); Uart_Printf("\nAvailable target block number: 0~4095\n"); Uart_Printf("Input target block number:"); targetBlock=Uart_GetIntNum(); // Block number(0~4095) if(targetSize==0) { Uart_Printf("Input target size(0x4000*n):"); targetSize=Uart_GetIntNum(); // Total byte size } } void K9S1208_PrintBadBlockNum(void) { int i; U16 id; Uart_Printf("\n[SMC(K9S1208V0M) NAND Flash bad block check]\n"); NF_Init(); id=NF_CheckId(); Uart_Printf("ID=%x(0xec76)\n",id); if(id!=0xec76) return; for(i=0;i<4096;i++) { NF_IsBadBlock(i); // Print bad block } } void K9S1208_PrintBlock(void)// Printf one page { int i,j; U16 id; U32 block,page; U8 buffer[512]; Uart_Printf("\n[SMC(K9S1208V0M) NAND Flash block read]\n"); NF_Init(); id=NF_CheckId(); Uart_Printf("ID=%x(0xec76)\n",id); if(id!=0xec76) return; Uart_Printf("Input target block number :"); block=Uart_GetIntNum(); Uart_Printf("Input target page number :"); page=Uart_GetIntNum(); NF_ReadPage(block,page,buffer); Uart_Printf("block=%d,page=%d:",block,page); for(j=0;j<512;j++) { if(j%16==0) Uart_Printf("\n%3xh:",j); Uart_Printf("%02x ",buffer[j]); } Uart_Printf("\n"); } //************************************************* //************************************************* //** H/W dependent functions ** //************************************************* //************************************************* //The code is made for bi-endian mode // block0: reserved for boot strap // block1~4095: used for OS image // badblock SE: xx xx xx xx xx 00 .... // good block SE: ECC0 ECC1 ECC2 FF FF FF .... #define WRITEVERIFY (0) //verifing is enable at writing. /* #define FC_CMD() {rPDATA|=CLE;rPDATA&=~(ALE|CE);} #define FC_ADDR() {rPDATA|=ALE;rPDATA&=~(CLE|CE);} #define FC_DATA() {rPDATA&=~(ALE|CLE|CE);} #define FC_INACTIVE() {rPDATA|=CE;rPDATA&=~(ALE|CLE);} */ #define NF_CMD(cmd) {rNFCMD=cmd;} #define NF_ADDR(addr) {rNFADDR=addr;} #define NF_nFCE_L() {rNFCONF&=~(1<<11);} #define NF_nFCE_H() {rNFCONF|=(1<<11);} #define NF_RSTECC() {rNFCONF|=(1<<12);} #define NF_RDDATA() (rNFDATA) #define NF_WRDATA(data) {rNFDATA=data;} #define NF_WAITRB() {while(!(rNFSTAT&(1<<0)));} //wait tWB and check F_RNB pin. #define ID_K9S1208V0M 0xec76 #if 1 // HCLK=100Mhz #define TACLS 0 //1clk(0ns) #define TWRPH0 3 //3clk(25ns) #define TWRPH1 0 //1clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns #else // HCLK=50Mhz #define TACLS 0 //1clk(0ns) #define TWRPH0 1 //2clk(25ns) #define TWRPH1 0 //1clk(10ns) #endif static U8 seBuf[16]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; // 1block=(512+16)bytes x 32pages // 4096block // A[23:14][13:9] // block page static int NF_EraseBlock(U32 block) { U32 blockPage=(block<<5); int i; #if BAD_CHECK if(NF_IsBadBlock(block)) return 0; #endif NF_nFCE_L(); NF_CMD(0x60); // Erase one block 1st command NF_ADDR(blockPage&0xff); // Page number=0 NF_ADDR((blockPage>>8)&0xff); NF_ADDR((blockPage>>16)&0xff); NF_CMD(0xd0); // Erase one blcok 2nd command for(i=0;i<10;i++); //wait tWB(100ns)//?????? NF_WAITRB(); // Wait tBERS max 3ms. NF_CMD(0x70); // Read status command if (NF_RDDATA()&0x1) // Erase error { NF_nFCE_H(); Uart_Printf("[ERASE_ERROR:block#=%d]\n",block); NF_MarkBadBlock(block); return 0; } else { NF_nFCE_H(); return 1; } } static int NF_IsBadBlock(U32 block) { int i; unsigned int blockPage; U8 data; blockPage=(block<<5); // For 2'nd cycle I/O[7:5] NF_nFCE_L(); NF_CMD(0x50); // Spare array read command NF_ADDR(517&0xf); // Read the mark of bad block in spare array(M addr=5) NF_ADDR(blockPage&0xff); // The mark of bad block is in 0 page NF_ADDR((blockPage>>8)&0xff); // For block number A[24:17] NF_ADDR((blockPage>>16)&0xff); // For block number A[25] for(i=0;i<10;i++); // wait tWB(100ns) //????? NF_WAITRB(); // Wait tR(max 12us) data=NF_RDDATA(); NF_nFCE_H(); if(data!=0xff) { Uart_Printf("[block %d has been marked as a bad block(%x)]\n",block,data); return 1; } else { return 0; } } static int NF_MarkBadBlock(U32 block) { int i; U32 blockPage=(block<<5); seBuf[0]=0xff; seBuf[1]=0xff; seBuf[2]=0xff; seBuf[5]=0x44; // Bad blcok mark=0 NF_nFCE_L(); NF_CMD(0x50); //???? NF_CMD(0x80); // Write 1st command NF_ADDR(0x0); // The mark of bad block is NF_ADDR(blockPage&0xff); // marked 5th spare array NF_ADDR((blockPage>>8)&0xff); // in the 1st page. NF_ADDR((blockPage>>16)&0xff); // for(i=0;i<16;i++) { NF_WRDATA(seBuf[i]); // Write spare array } NF_CMD(0x10); // Write 2nd command for(i=0;i<10;i++); //tWB = 100ns. ///??????? NF_WAITRB(); // Wait tPROG(200~500us) 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 1; } static int NF_ReadPage(U32 block,U32 page,U8 *buffer) { int i; unsigned int blockPage; U8 ecc0,ecc1,ecc2; U8 *bufPt=buffer; U8 se[16]; page=page&0x1f; blockPage=(block<<5)+page; NF_RSTECC(); // Initialize ECC NF_nFCE_L(); NF_CMD(0x00); // Read command NF_ADDR(0); // Column = 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & Page num. NF_ADDR((blockPage>>16)&0xff); // for(i=0;i<10;i++); //wait tWB(100ns)/////?????? NF_WAITRB(); // Wait tR(max 12us) for(i=0;i<512;i++) { *bufPt++=NF_RDDATA(); // Read one page } ecc0=rNFECC0; ecc1=rNFECC1; ecc2=rNFECC2; for(i=0;i<16;i++) { se[i]=NF_RDDATA(); // Read spare array } //__RdPage528(pPage); NF_nFCE_H(); if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2]) { Uart_Printf("[ECC OK:%x,%x,%x]\n",se[0],se[1],se[2]); return 1; } else { Uart_Printf("[ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x]\n", se[0],se[1],se[2],ecc0,ecc1,ecc2); return 0; } } static int NF_WritePage(U32 block,U32 page,U8 *buffer) { int i; U32 blockPage=(block<<5)+page; U8 *bufPt=buffer; NF_RSTECC(); // Initialize ECC NF_nFCE_L(); NF_CMD(0x0);//?????? NF_CMD(0x80); // Write 1st command NF_ADDR(0); // Column 0 NF_ADDR(blockPage&0xff); // NF_ADDR((blockPage>>8)&0xff); // Block & page num. NF_ADDR((blockPage>>16)&0xff); // for(i=0;i<512;i++) { NF_WRDATA(*bufPt++); // Write one page to NFM from buffer } seBuf[0]=rNFECC0; seBuf[1]=rNFECC1; seBuf[2]=rNFECC2; seBuf[5]=0xff; // Marking good block for(i=0;i<16;i++) { NF_WRDATA(seBuf[i]); // Write spare array(ECC and Mark) } NF_CMD(0x10); // Write 2nd command for(i=0;i<10;i++); //tWB = 100ns. ////?????? NF_WAITRB(); //wait tPROG 200~500us; 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); NF_MarkBadBlock(block); return 0; } else { NF_nFCE_H(); #if (WRITEVERIFY==1) //return NF_VerifyPage(block,page,pPage); #else return 1; #endif } } static U16 NF_CheckId(void) { int i; U16 id; NF_nFCE_L(); NF_CMD(0x90); NF_ADDR(0x0); for(i=0;i<10;i++); //wait tWB(100ns)////????? id=NF_RDDATA()<<8; // Maker code(K9S1208V:0xec) id|=NF_RDDATA(); // Devide code(K9S1208V:0x76) NF_nFCE_H(); return id; } static void NF_Reset(void) { int i; U16 id; NF_nFCE_L(); NF_CMD(0xFF); //reset command for(i=0;i<10;i++); //tWB = 100ns. //?????? NF_WAITRB(); //wait 200~500us; NF_nFCE_H(); } static void NF_Init(void) { rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); // 1 1 1 1, 1 xxx, r xxx, r xxx // En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 NF_Reset(); } int DownloadData(void) { int i,tmp; U16 checkSum=0,dnCS; U32 fileSize=10; U8 *downPt; Uart_Printf("Download through UART0 from 0x30100000.\n"); downPt=(U8 *)downloadAddress; Uart_Printf("\ndownloadAddress=%x\n",downloadAddress); Uart_Printf("Download the plain binary file to be written\n"); Uart_Printf("The file format: (4)+(n)+CS(2)\n"); Uart_Printf("Download methods: 115.2KBPS,8Bit,NP,1STOP\n"); Uart_Printf("\nSTATUS:"); rINTMSK=BIT_ALLMSK; tmp=RdURXH0(); //To remove overrun error state. i=0; while(i 0;i--) { if( seBuf[6]>>(i*2-2) == 0x0 | seBuf[6]>>(i*2-2) == 0x3 ) { Uart_Printf("The error is above 2bits-Can not recover!!!\n"); return 0; } } */ colECC=seBuf[8]>>2; lowECC=((seBuf[8]&0x3)<<16)|(seBuf[7]<<8)|(seBuf[6]<<0); Uart_Printf("Low ECC=0x%x, Col ECC=0x%x\n", lowECC, colECC); // Column parity for(i=0;i<3;i++) col |= (Check10(colECC, i) <