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] 下一页
|