/* * Command line handling. * * This software is free. */ #include #include #include #include #include #include #include #include #include "include.h" #include "configs.h" #include "nand_ecc.h" #define printf_log(fp,fmt,args...) fprintf(fp,fmt,## args) static u8 nand_buf[(2048+64)*128]; //Max 128 pages! static u8 check_buf[(2048+64)*128]; static u32 spage, epage, chip_num; static u8 *filename,ops_t,idx,cs_index,args_num; static np_data *npdata; static FILE *log_fp; #define USE_VALID_CHECK int nand_check_cmp(u8 *buf1,u8 *buf2,u32 len) { u32 i; for (i = 0; i < len; i++) { if (buf1[i] != buf2[i]) { printf("Check error! %x\n",i); return -1; } } return 0; } void dump_npdata(np_data *np) { int i; printf("Process type:%d \n",np->pt); printf("NAND interface ps:%d bw:%d rc:%d ppb:%d os:%d bbp:%d bba:%d\n", np->ps,np->bw,np->rc,np->ppb,np->os,np->bbp,np->bba); printf("ECC configration type:%d index:%d\n",np->et,np->ep); printf("ECC position:"); for (i = 0;i < oob_64[np->ep].eccbytes;i++) { if (i % 9 == 0) printf("\n"); printf("%d ",oob_64[np->ep].eccpos[i]); } } //a check sample for WINCE //Modify this function according to your system int check_invalid_block(u8 *buf,np_data *np) { int i,j; u8 *p = buf + np->ps ,* q ; q = buf + (( np->ps + np->os ) * np->ppb - 1) - 10; if ( (*q) != 0xff ) { // printf("A mark erase block! \n"); return 0; } for ( i = 0; i < np->ppb; i ++ ) { for (j = 0; j < np->os; j ++ ) { if ( p[j] != 0xff ) { return 1; } } p += np->ps; } // printf("A never use block! \n"); return 0; } int do_read_flash(np_data *np) { FILE *fp; u32 sp; int i,j,k; if ((fp = fopen((const char *)np->fname, "w+")) == NULL ) { printf("Can not open source or object file!\n"); return -1; } i = np->epage - np->spage; j = i / MAX_BUF_PAGE; k = i % MAX_BUF_PAGE; sp = np->spage; for (i=0;inand_check_block(sp/np->ppb)) { printf_log(log_fp,"Skip a old block at %x!\n",sp/np->ppb); sp += MAX_BUF_PAGE; printf("Skip a old block!\n"); continue; } np->nand_read(nand_buf, sp, MAX_BUF_PAGE); #ifdef USE_VALID_CHECK if ( check_invalid_block(nand_buf,np) ) { #endif fwrite(nand_buf,1,MAX_BUF_SIZE,fp); printf("Read block %d finish\n",sp/np->ppb); #ifdef USE_VALID_CHECK } else printf("Skip a invalid block! %d \n",sp/np->ppb); #endif sp += MAX_BUF_PAGE; } if (k) { if (np->nand_check_block(sp/np->ppb)) { printf_log(log_fp,"Skip a old block at %x!\n",sp/np->ppb); printf("Skip a old block!\n"); } else { np->nand_read(nand_buf, sp, k); #ifdef USE_VALID_CHECK if ( check_invalid_block(nand_buf,np) ) { #endif fwrite(nand_buf, 1, k*OOBPAGE_SIZE, fp); #ifdef USE_VALID_CHECK } else printf("Skip a invalid block! %d \n",sp/np->ppb); #endif } } printf("Read nand flash finish!\n"); fclose(fp); return 0; } int do_write_flash(np_data *np) { FILE *fp; u32 sp,flen,offset; int i,j,k,r,error_flag=0; if ((fp = fopen((const char *)np->fname,"r")) == NULL ) { printf("Can not open source or object file!\n"); return -1; } fseek(fp,0,SEEK_END); flen = ftell(fp); i = flen / OOBPAGE_SIZE; if (flen % OOBPAGE_SIZE !=0) { printf("Source file length is not fit!\n"); return -1; } sp = np->spage; if (sp % np->ppb !=0) { printf("Start page number not blockaligned!\n"); return -1; } //Erase object block first j = sp / np->ppb; k = flen/OOBPAGE_SIZE; if (k % np->ppb == 0) k = k / np->ppb; else k = k / np->ppb +1; np->nand_erase(k,j,0); j = i / MAX_BUF_PAGE; k = i % MAX_BUF_PAGE; offset = 0; // printf("j k %d %d %d %d\n",j,k,i,flen); for (i=0;iepage - np->ppb;sp += np->ppb) { //old bad block if (!np->nand_check_block(sp/np->ppb)) break; printf("Skip a old bad blocks!\n"); printf_log(log_fp,"Skip a old block at %x!\n",sp/np->ppb); } if (sp/np->ppb > np->epage /np->ppb) { printf("Program end but not finish,due to bad block!\n"); printf_log(log_fp,"Program end but not finish,due to bad block!\n"); return -1; } if (np->nand_program(nand_buf,sp,np->ppb)) { error_flag = 1; printf("Program error!\n"); printf_log(log_fp,"Program error! %x\n",sp/np->ppb); break; } memset(check_buf,0,MAX_BUF_SIZE); np->nand_read(check_buf,sp,np->ppb); if (np->nand_check(nand_buf,check_buf, MAX_BUF_SIZE) ) { //check error! error_flag = 1; printf("Error retry!\n"); printf_log(log_fp,"Error retry!\n"); continue; } else { error_flag = 0; break; } } if (error_flag) { //block has broken! printf("Found a new bad block: %x!\n",sp/np->ppb); printf_log(log_fp,"Found a new bad block at %x!\n",sp/np->ppb); np->nand_erase(1,sp/np->ppb,0); //erase before mark bad block! np->nand_block_markbad(sp /np->ppb); sp += np->ppb; goto BLOCK_BROKEN; } else { printf("Write block %d finish\n",sp/np->ppb); sp += np->ppb; offset += MAX_BUF_SIZE; } } if (k) { fseek(fp,offset,SEEK_SET); fread(nand_buf,1,k * OOBPAGE_SIZE ,fp); BLOCK_BROKEN1: for (r=0;repage - np->ppb;sp += np->ppb) { //old bad block if (!np->nand_check_block(sp/np->ppb)) break; printf("Skip a old bad blocks!\n"); printf_log(log_fp,"Skip a old block at %x!\n",sp/np->ppb); } if (sp/np->ppb > np->epage/np->ppb) { printf("Program end but not finish,due to bad block!\n"); printf_log(log_fp,"Program end but not finish,due to bad block!\n"); return 0; } if (np->nand_program(nand_buf,sp,k)) { error_flag = 1; printf("Program error!\n"); printf_log(log_fp,"Program error! %x\n",sp/np->ppb); break; } memset(check_buf,0,MAX_BUF_SIZE); np->nand_read(check_buf,sp,k); if (np->nand_check(nand_buf,check_buf, k * OOBPAGE_SIZE) ) { //check error! error_flag = 1; printf("Error retry!\n"); printf_log(log_fp,"Error retry!\n"); continue; } else { error_flag = 0; break; } } if (error_flag) { //block has broken! printf("Found a new bad block : %x!\n",sp/np->ppb); printf_log(log_fp,"Found a new bad block at %x!\n",sp/np->ppb); np->nand_erase(1,sp/np->ppb,0); //erase before mark bad block! np->nand_block_markbad(sp /np->ppb); sp += np->ppb; goto BLOCK_BROKEN1; } } printf("Nand flash write finish!\n"); return 0; } void show_usage() { printf("Nand flash programmer.Version v1.0\n"); printf("Usage: nandprog spage epage opration_type obj_file chip_index [config_index]\n\n"); printf(" spage operation start page number\n"); printf(" epage operation end page number\n"); printf(" opration_type operation type read or write\n"); printf(" obj_file source or object filename\n"); printf(" chip_index chip select index\n"); printf(" config_index optional,when chosen,\n"); printf(" will use one of these default configrations instead of load from CFG\n"); } int cmdline(int argc, char *argv[], np_data *np) { if (argc<6 || argc>7) { show_usage(); return -1; } if (strlen(argv[1])>8) { printf("Start address page error!\n"); return -1; } spage = atoi(argv[1]); if (spage > MAX_PAGE) { printf("Start address page error!\n"); return -1; } if (strlen(argv[2])>8) { printf("End address page error!\n"); return -1; } epage = atoi(argv[2]); if (epage > MAX_PAGE) { printf("End address page error!\n"); return -1; } if (strlen(argv[3])>1) { printf("Operation type error!\n"); return -1; } if (argv[3][0] == 'r') ops_t = READ_FLASH; else if (argv[3][0] == 'w') ops_t = WRITE_FLASH; else { printf("Operation type error!\n"); return -1; } if (strlen(argv[4])>20) { printf("Source or object file name error!\n"); return -1; } filename = (unsigned char *)argv[4]; if (strlen(argv[5])>2) { printf("Chip select number error!\n"); return -1; } cs_index = atoi(argv[5]); if (epage <= spage) { printf("End page number must larger than start page number!\n"); return -1; } if (argc == 7) { args_num = 7; if (strlen(argv[6])>3) { printf("Processor type error!\n"); return -1; } idx = atoi(argv[6]); if (idx > 20) { printf("Processor type error!\n"); return -1; } } else args_num = 6; printf("Deal command line: spage%d epage%d ops%d file:%s cs%d\n", spage,epage,ops_t,filename,cs_index); return 0; } void init_funs(np_data *np) { switch (np->pt) { case JZ4740: np->ebase = 0x13010000; np->dport = 0x18000000; np->gport = 0x10010000; np->bm_ms = 0x100; np->pm_ms = 0x20000; np->gm_ms = 0x500; np->ap_offset = 0x10000; np->cp_offset = 0x8000; np->nand_init = nand_init_4740; np->nand_erase = nand_erase_4740; np->nand_program = nand_program_4740; np->nand_read = nand_read_4740_rs; np->nand_read_raw = nand_read_raw_4740; np->nand_read_oob = nand_read_oob_4740; np->nand_block_markbad = nand_block_markbad_4740; np->nand_check = nand_check_cmp; np->nand_check_block = nand_check_block_4740; if (np->et == HARDRS) np->nand_read = nand_read_4740_rs; else np->nand_read = nand_read_4740_hm; break; case JZ4730: np->ebase = 0x13010000; np->dport = 0x14000000; np->gport = 0x0; np->bm_ms = 0x100; np->pm_ms = 0xb0000; np->gm_ms = 0x0; np->ap_offset = 0x80000; np->cp_offset = 0x40000; np->nand_init = nand_init_4730; np->nand_erase = nand_erase_4730; np->nand_program = nand_program_4730; np->nand_read = nand_read_4730; np->nand_read_oob = nand_read_oob_4730; np->nand_block_markbad = nand_block_markbad; np->nand_check = nand_check_cmp; np->nand_check_block = nand_check_block; np->nand_select = chip_select_4730; break; case JZ4760: break; } // dump_npdata(np); } np_data * cmdinit() { int fd; if (args_num>6) { npdata = &config_list[idx]; if (npdata) printf("Load configration index success!\n"); else { printf("Load configration index fail!\n"); return 0; } } else { npdata = load_cfg(); if (npdata) printf("Load configration file success!\n"); else { printf("Load configration file fail!\n"); return 0; } } if (!npdata) return 0; init_funs(npdata); npdata->spage = spage; npdata->epage = epage; npdata->fname = filename; npdata->ops = ops_t; npdata->cs = cs_index; if((fd=open("/dev/mem",O_RDWR|O_SYNC))==-1) { printf("Can not open memory file!\n"); return 0; } npdata->base_map = mmap(NULL,npdata->bm_ms,PROT_READ | PROT_WRITE,MAP_SHARED,fd,npdata->ebase); if(npdata->base_map == MAP_FAILED) { printf("Can not map EMC_BASE ioport!\n"); return 0; } else printf("Map EMC_BASE success :%x\n",(u32)npdata->base_map); npdata->port_map=mmap(NULL,npdata->pm_ms ,PROT_READ | PROT_WRITE,MAP_SHARED,fd,npdata->dport); if(npdata->port_map== MAP_FAILED) { printf("Can not map NAND_PORT ioport!\n"); return 0; } else printf("Map NAND_PORT success :%x\n",(u32)npdata->port_map); if (npdata->pt == JZ4740) { npdata->gpio_map=mmap(NULL,npdata->gm_ms ,PROT_READ | PROT_WRITE,MAP_SHARED,fd,npdata->gport); if(npdata->gpio_map== MAP_FAILED) { printf("Can not map GPIO ioport!\n"); return 0; } else printf("Map GPIO_PORT success :%x\n",(u32)npdata->gpio_map); } close(fd); printf("Memory map all success!\n"); npdata->nand_init(npdata); return npdata; } int cmdexcute(np_data *np) { int ret; if ((log_fp=fopen(NUM_FILENAME,"a+"))==NULL ) { printf("Can not open number file!\n"); return -1; } fscanf(log_fp,"%d",&chip_num); fclose(log_fp); chip_num++; if ((log_fp=fopen(NUM_FILENAME,"w"))==NULL ) { printf("Can not open number file!\n"); return -1; } printf_log(log_fp,"%d",chip_num); fclose(log_fp); if ((log_fp=fopen(LOG_FILENAME,"a+"))==NULL ) { printf("Can not open log file!\n"); return -1; } printf_log(log_fp,"\nNo.%d :\n",chip_num); if (np->ops == READ_FLASH) { printf_log(log_fp,"Read nand flash!\n"); printf_log(log_fp,"Args:index=%d spage=%d epage=%d file=%s cs=%d\n", idx,spage,epage,filename,cs_index); ret= do_read_flash(np); } else { printf_log(log_fp,"Write nand flash!\n"); printf_log(log_fp,"Args:index=%d spage=%d epage=%d file=%s cs=%d\n", idx,spage,epage,filename,cs_index); ret= do_write_flash(np); } if (!ret) printf_log(log_fp,"Operation success!\n"); else printf_log(log_fp,"Operation fail!\n"); fclose(log_fp); return 0; } int cmdexit(np_data *np) { munmap(np->base_map,np->bm_ms); munmap(np->port_map,np->pm_ms); if (np->pt == JZ4740) munmap(np->gpio_map,np->gm_ms); return 0; }