|  
 
 
  
LOCAL BOOL isBusy() {     return !(PADAT & PA15); } LOCAL int wait() {     int i = 0;     for(i=0;i<TIMEOUT_LOOP;++i)     {         if(!isBusy())             return 0;     }     printf("wait timeout!\n");     return -1; } LOCAL void set_command(UCHAR cmd) {     *((volatile UCHAR*)NAND_CMD) = cmd; } LOCAL void set_addr(UCHAR addr) {     *((volatile UCHAR*)NAND_ADDR) = addr; } LOCAL UCHAR nand_read(void) {     return *((volatile UCHAR*)(0x50000000)); } LOCAL void nand_write(UCHAR c) {      *((volatile UCHAR*)(0x50000000))=c; } void nand_init() {     int i = 0;     nand_info.checked = 0;     *((UINT32 *)(0xf0010128))=0x50000801;/*Base Register bank5*/     *((UINT32 *)(0xf001012c))=0xfff00856;/*Option Register bank5*/     PAPAR &= ~PA15;     PADIR &= ~PA15;     if(read_id())     {         printf("wrong id \n");         return;     }           if(isChecked())     {         printf("isChecked\n");         nand_info.checked = 1;         if(load_info())         {             printf("error in init flash\n");             nand_info.checked = 0;             nand_erase(0);             return;         }         nand_info.checked = 1;         printf(" init flash ok!\n");               }     else     {                   for(i = 0; i < 8192; i++)             nand_info.badBlockTable[i] = 0;         for(i = 0; i < 4096 ; i++)                    nand_info.map.map_short[i] = i+1;                for(i = 0; i < 4095 ; i++)             nand_info.bottomHaltInValid[i] = 0;         initalBadBlockCheck();         printf("initalBadBlockCheck ok\n");         nand_info.checked = 1;                   if(nand_erase(0))         {             printf("error in erasing block 0\n");             return;         }         printf("nand_erase(0) ok\n");                   if(program_info())         {             printf("error in programming block 0\n");             nand_info.checked = 0;             return;         }         printf("nand_program_block(0) ok\n");                         }             } LOCAL UINT32 make_addr(UINT32 blocknum,UINT32 page,UINT32 sector,UINT32 offset,int flag) {     UINT32 addr = 0;     if(blocknum>=8192)     {         DEBUG_PRINT(DEBUG_ERROR,("error in make_addr: blocknum>=8192!\n"));                return 0xFFFFFFFF;     }     if(page>=64)     {         DEBUG_PRINT(DEBUG_ERROR,("error in make_addr: page>=64!\n"));         return 0xFFFFFFFF;     }     if(sector>=4)     {         DEBUG_PRINT(DEBUG_ERROR,("error in make_addr: sector>=4!\n"));         return 0xFFFFFFFF;     }     if(flag)     {         if(offset>=16)         {             DEBUG_PRINT(DEBUG_ERROR,("error in make_addr: spare offset>=16!\n"));             return 0xFFFFFFFF;         }         addr = (blocknum<<17)+(page<<11)+(sector<<4)+offset;     }     else     {         if(offset>=512)         {             DEBUG_PRINT(DEBUG_ERROR,("error in make_addr: offset>=512!\n"));             return 0xFFFFFFFF;         }         addr = (blocknum<<17)+(page<<11)+(sector<<9)+offset;     }           return addr;             } LOCAL int set_data_addr(UINT32 addr,int flag)/*addr(11~29) -- raw addr  ; addr(0~10) -- 2k coloum addr ; flag -- spare*/ {     UCHAR col[2];     UCHAR raw[3];     if(addr & 0xC0000000)     {         printf("addr error!\n");         return -1;     }     if(flag)/*spare*/     {         if(addr & 0x7C0)         {             DEBUG_PRINT(DEBUG_ERROR,("spare addr error!%x %x\n",addr & 0x7C0,addr));             return -1;         }         col[0] = addr&0xFF;         col[1] = ((addr>>8) &0x7) + 0x08;         raw[0] = (addr>>11)&0xFF;         raw[1] = (addr>>19)&0xFF;         raw[2] = (addr>>27)&0x07;     }     else     {         col[0] = addr&0xFF;         col[1] = (addr>>8) &0x7;         raw[0] = (addr>>11)&0xFF;         raw[1] = (addr>>19)&0xFF;         raw[2] = (addr>>27)&0x07;     }     set_addr(col[0]);     set_addr(col[1]);     set_addr(raw[0]);     set_addr(raw[1]);     set_addr(raw[2]);     return 0; } LOCAL int nand_read_sector(UCHAR* buf,UINT32 blocknum,UINT32 page,UINT32 sector) {     UCHAR col[2];     UCHAR raw[3];     UCHAR ecc1[3];     UCHAR ecc2[3];     long offset;     UCHAR correct,old;     eccdiff_t ret;     int len = 512;     int i=0;     UINT32 addr =0;     if(blocknum>=8192)     {         DEBUG_PRINT(DEBUG_ERROR,("error in nand_read_sector: blocknum>=8192!\n"));         return -1;     }     if(page>=64)     {         DEBUG_PRINT(DEBUG_ERROR,("error in nand_read_sector: page>=64!\n"));         return -1;     }     if(sector>=4)     {         DEBUG_PRINT(DEBUG_ERROR,("error in nand_read_sector: sector>=4!\n"));         return -1;     }     /*read ecc*/     addr = make_addr( blocknum, page, sector,1,1);           set_command(0x00);     set_data_addr(addr,1);           set_command(0x30);     if(wait()) return -1;     for(i = 0; i < 3; i++)         ecc1[i] = nand_read();               /*read sector*/     addr = make_addr( blocknum, page, sector,0,0);     set_command(0x00);     set_data_addr(addr,0);           set_command(0x30);     if(wait()) return -1;     for(i = 0; i < 512; i++)         buf[i] = nand_read();     make_ecc_512(ecc2, buf);     ret = compare_ecc_512(ecc1, ecc2, buf, &offset, &correct);     if(ret == ECC_NO_ERROR)         return 0;     /*else if(ret == ECC_CORRECTABLE_ERROR)     {         old = buf[offset];         buf[offset]= correct;         DEBUG_PRINT(DEBUG_READ,("ECC_CORRECTABLE_ERROR : buf[%d]: %x-->%x\n",offset,old,correct));         return 0;     }*/     else     {         DEBUG_PRINT(DEBUG_ERROR,("ecc error in block%d  page%d  sector%d \n",blocknum,page,sector));         DEBUG_PRINT(DEBUG_ERROR,("ecc1 %x,%x,%x ecc2 %x,%x,%x \n",ecc1[0],ecc1[1],ecc1[2],ecc2[0],ecc2[1],ecc2[2]));            return -1;     } }   int nand_erase(UINT32 blocknum) {     UCHAR raw[3];     int i;     if(blocknum>=8192)     {         DEBUG_PRINT(DEBUG_ERROR,("erase: error block num!\n"));         return -1;     }     raw[0] = (blocknum<<6)&0xC0;     raw[1] = (blocknum>>2)&0xFF;     raw[2] = (blocknum>>10)&0x07;     set_command(0x60);     set_addr(raw[0]);     set_addr(raw[1]);     set_addr(raw[2]);     set_command(0xD0);           if(wait()) return -1;     set_command(0x70);     if(nand_read()&0x1)     {         DEBUG_PRINT(DEBUG_ERROR,("erase: error in erasing block %d!\n",blocknum));         return -2;     }     return 0;       }     LOCAL int nand_program_block(UCHAR* src,UINT32 blocknum,UINT32 len) {     UCHAR col[2];     UCHAR raw[3];     int i=0,j=0;     UCHAR buf[512];     if(len>64*2048) len=64*2048;                           if(blocknum>=8192)     {         DEBUG_PRINT(DEBUG_ERROR,("error in program: blocknum>=8192!\n"));                return -1;     }     for(i=0;i<64;i++)/*64 pages*/         for(j=0;j<4;j++)/*4 sectors*/         {             memset(buf,0xFF,512);                            memcpy( buf,src,len>512?512:len);             if(nand_program_sector(buf,blocknum,i,j))             {                 DEBUG_PRINT(DEBUG_ERROR,("error in program blocknum%d page%d sector%d!\n",blocknum,i,j));                                return -2;             }                           DEBUG_PRINT(DEBUG_PROGRAM,("page %d  sector %d\n",i,j));             if(len>512)             {                 src+=512;                 len-=512;             }             else                                return 0;                       }        return 0;       } LOCAL int nand_program_sector( UCHAR* src,UINT32 blocknum,UINT32 page,UINT32 sector) {     UCHAR col[2];     UCHAR raw[3];     UCHAR ecc[3];     UINT32 addr;     int len = 512;     int i=0;           if(blocknum>=8192)     {         DEBUG_PRINT(DEBUG_ERROR,("error in program: blocknum>=8192!\n"));         return -1;     }     if(page>=64)     {         DEBUG_PRINT(DEBUG_ERROR,("error in program: page>=64!\n"));         return -1;     }     if(sector>=4)     {         DEBUG_PRINT(DEBUG_ERROR,("error in program: sector>=4!\n"));         return -1;     }     make_ecc_512(ecc, src);       addr = make_addr( blocknum, page, sector,0,0);     /*program data*/           DEBUG_PRINT(DEBUG_PROGRAM,("%x %x %x %x %x \n",col[0],col[1],raw[0],raw[1],raw[2]));     set_command(0x80);     set_data_addr(addr,0);        for(i=0;i<512;i++)         nand_write(src[i]);     set_command(0x10);           if(wait()) return -1;     set_command(0x70);     if(nand_read()&0x1)     {         DEBUG_PRINT(DEBUG_ERROR,("erase: error in programming block %d page %d sector $d!\n",blocknum,page,sector));         return -2;     }     /*program ecc*/     addr = make_addr( blocknum, page, sector,1,1);           set_command(0x80);     set_data_addr(addr,1);        for(i=0;i<3;i++)         nand_write(ecc[i]);     set_command(0x10);           if(wait()) return -1;     set_command(0x70);     if(nand_read()&0x1)     {         DEBUG_PRINT(DEBUG_ERROR,("erase: error in programming ecc for block %d page %d sector $d!\n",blocknum,page,sector));         return -2;     }     return 0;       } 
上一页  [1] [2] [3] [4] 下一页  
 |