int do_insnand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { size_t total = CFG_ENV_OFFSET; ulong addr = PHYS_SDRAM_1; movi_read((uint) addr, ofsinfo.bl2, MOVI_BL2_BLKCNT); nand_erase(&nand_info[0], 0x0, CFG_ENV_OFFSET + CFG_ENV_SIZE); nand_write(&nand_info[0], 0x0, &total, (u_char *) addr); printf("done\n"); return 1; }
int saveenv_nand_adv(void) { size_t total; int ret = 0; u_char *tmp; total = CFG_ENV_OFFSET; tmp = (u_char *) malloc(total); nand_read(&nand_info[0], 0x0, &total, (u_char *) tmp); puts("Erasing Nand..."); nand_erase(&nand_info[0], 0x0, CFG_ENV_OFFSET + CFG_ENV_SIZE); //#ifndef CONFIG_S5PC100_EVT1 if (nand_erase(&nand_info[0], 0x0, CFG_ENV_OFFSET + CFG_ENV_SIZE)) { free(tmp); return 1; } //#endif puts("Writing to Nand... "); ret = nand_write(&nand_info[0], 0x0, &total, (u_char *) tmp); total = CFG_ENV_SIZE; ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char *) env_ptr); //#ifndef CONFIG_S5PC100_EVT1 if (ret || total != CFG_ENV_SIZE) { free(tmp); return 1; } //#endif puts("done\n"); free(tmp); return ret; }
int saveenv_nand_adv(void) { #if defined(CONFIG_CMD_NAND) size_t total; int ret = 0; u_char *tmp; total = CONFIG_ENV_OFFSET; tmp = (u_char *) malloc(total); nand_read(&nand_info[0], 0x0, &total, (u_char *) tmp); puts("Erasing Nand..."); nand_erase(&nand_info[0], 0x0, CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE); if (nand_erase(&nand_info[0], 0x0, CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)) { free(tmp); return 1; } puts("Writing to Nand... "); ret = nand_write(&nand_info[0], 0x0, &total, (u_char *) tmp); total = CONFIG_ENV_SIZE; ret = nand_write(&nand_info[0], CONFIG_ENV_OFFSET, &total, (u_char *) env_ptr); if (ret || total != CONFIG_ENV_SIZE) { free(tmp); return 1; } puts("done\n"); free(tmp); return ret; #else return 0; #endif /* CONFIG_CMD_NAND */ }
int main() { nand_init(); nand_erase(0x600000, 0x100000); char *str = "jiangshen 123456789 haha"; nand_write((unsigned int)str, 0x600000, 2048); nand_read((unsigned int)0x41000000, 0x600000, 2048); return 0; }
void update_program(void) { unsigned char *buf = (unsigned char *)0x52000000; unsigned long len = 0; int have_begin = 0; int nodata_time = 0; char c; /* 读串口获得数据 */ printf("\n\ruse gtkterm to send file\n\r", len); while (1) { if (getc_nowait(&buf[len]) == 0) { have_begin = 1; nodata_time = 0; len++; } else { if (have_begin) { nodata_time++; } } if (nodata_time == 1000) { break; } } printf("have get %d bytes data\n\r", len); printf("Press Y to program the flash: \n\r"); c = getc(); if (c == 'y' || c == 'Y') { /* 烧写到nand flash block 0 */ nand_erase_block(0); nand_write(0, buf, len); printf("update program successful\n\r"); } else { printf("Cancel program!\n\r"); } }
int VFL_Write(u32 virtualPageNumber, u8* buffer, u8* spare) { u16 virtualBank; u16 virtualBlock; u16 virtualPage; u16 physicalBlock; u32 dwVpn; int page; int ret; dwVpn = virtualPageNumber + (NANDGeometry->pagesPerSuBlk * FTLData->field_4); if(dwVpn >= NANDGeometry->pagesTotal) { LOG("ftl: dwVpn overflow: %d\n", dwVpn); return -EINVAL; } if(dwVpn < NANDGeometry->pagesPerSuBlk) { LOG("ftl: dwVpn underflow: %d\n", dwVpn); } virtual_page_number_to_virtual_address(dwVpn, &virtualBank, &virtualBlock, &virtualPage); physicalBlock = virtual_block_to_physical_block(virtualBank, virtualBlock); page = physicalBlock * NANDGeometry->pagesPerBlock + virtualPage; #ifdef IPHONE_DEBUG LOG("ftl: vfl_write: vpn: %u, bank %d, page %u\n", virtualPageNumber, virtualBank, page); #endif ret = nand_read(virtualBank, page, PageBuffer, SpareBuffer, true, true); if(ret != ERROR_EMPTYBLOCK) { LOG("ftl: WTF trying to write to a non-blank page! vpn = %u bank = %d page = %u\r\n", virtualPageNumber, virtualBank, page); return -1; } ret = nand_write(virtualBank, page, buffer, spare, true); if(ret == 0) return 0; ++pstVFLCxt[virtualBank].field_16; vfl_gen_checksum(virtualBank); vfl_schedule_block_for_remap(virtualBank, virtualBlock); return -1; }
void nand_write_test(void) { char buf[100]; unsigned long addr; unsigned long size; printf("enter the start address: "); scanf("%s", buf); addr = strtoul(buf, NULL, 0); printf("enter the string: "); scanf("%s", buf); size = strlen(buf) + 1; nand_write(addr, (unsigned char *)buf, size); }
static int vfl_store_cxt(int bank) { int i; int good; SpareData* spareData = (SpareData*) SpareBuffer; --pstVFLCxt[bank].usnDec; pstVFLCxt[bank].usnInc = ++curVFLusnInc; pstVFLCxt[bank].nextcxtpage += 8; vfl_gen_checksum(bank); memset(spareData, 0xFF, NANDGeometry->bytesPerSpare); spareData->meta.usnDec = pstVFLCxt[bank].usnDec; spareData->type2 = 0; spareData->type1 = 0x80; for(i = 0; i < 8; ++i) { u32 index = pstVFLCxt[bank].activecxtblock; u32 block = pstVFLCxt[bank].VFLCxtBlock[index]; u32 page = block * NANDGeometry->pagesPerBlock; page += pstVFLCxt[bank].nextcxtpage - 8 + i; nand_write(bank, page, (u8*) &pstVFLCxt[bank], (u8*) spareData, true); } good = 0; for(i = 0; i < 8; ++i) { u32 index = pstVFLCxt[bank].activecxtblock; u32 block = pstVFLCxt[bank].VFLCxtBlock[index]; u32 page = block * NANDGeometry->pagesPerBlock; page += pstVFLCxt[bank].nextcxtpage - 8 + i; if(nand_read(bank, page, PageBuffer, (u8*) spareData, true, true) != 0) continue; if(memcmp(PageBuffer, &pstVFLCxt[bank], sizeof(VFLCxt)) != 0) continue; if(spareData->type2 == 0 && spareData->type1 == 0x80) ++good; } return (good > 3) ? 0 : -1; }
/* * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ #ifdef CFG_ENV_OFFSET_REDUND int saveenv(void) { ulong total; int ret = 0; env_ptr->flags++; total = CFG_ENV_SIZE; if(gd->env_valid == 1) { puts ("Erasing redundant Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE)) return 1; puts ("Writing to redundant Nand... "); ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, (u_char*) env_ptr); } else { puts ("Erasing Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) return 1; puts ("Writing to Nand... "); ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*) env_ptr); } if (ret || total != CFG_ENV_SIZE) return 1; puts ("done\n"); gd->env_valid = (gd->env_valid == 2 ? 1 : 2); return ret; } #else /* ! CFG_ENV_OFFSET_REDUND */ int saveenv(void) { ulong total; int ret = 0; puts ("Erasing Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) return 1; puts ("Writing to Nand... "); total = CFG_ENV_SIZE; ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); if (ret || total != CFG_ENV_SIZE) return 1; puts ("done\n"); return ret; }
/** * 作用:nandc模块按分区名和分区相对偏移来使能ECC功能的写数据操作,注意此函数的写操作带OOB数据且在写的过程中会擦除nandflash * * 参数: * @partition_name ---要写数据的分区名 * @partition_offset ---要写数据的分区相对偏移地址 * @ptr_ram_addr ---要写数据的地址 * @length ---要写数据的长度 * * 描述:根据分区名和分区的偏移地址来确定Flash的地址,再来写Flash操作 */ s32 bsp_nand_write(const char *partition_name, u32 partition_offset, void* ptr_ram_addr, u32 length) { u32 flash_addr, ret = NANDC_ERROR; struct ST_PART_TBL * ptable = find_partition_by_name(partition_name); if(!ptable) { goto ERRO; } /*得到要写Flash的地址*/ flash_addr = ptable->offset + partition_offset; /*在写的过程中会擦除nandflash,因此不需要调用者再来擦除一次*/ return nand_write(flash_addr, (u32)ptr_ram_addr, length, NULL); ERRO: return ret; }
int main(int argc, char *argv[]) { int i = 0; char *p=(void *)0x52000000; char *buf=(void *)0x51000000; WTCON=0; clock_init(); uart_init(); ddr_init(); nand_init(); memcpy(buf,"helloworld\n",12); memset(p,0,12); nand_erase(0x200000,12); nand_write(buf,0x200000,12); nand_read(p,0x200000,12); uprintf(p); uprintf("\n"); return 0; }
int K9F2G08_WriteTags(u32 block, u32 page, const u8 *spare, int ofs, int len) { int i,stat; u32 _page = block*PAGES_PER_BLOCK + page; /* nand_Init_ECC(); */ /* Initialize ECC */ nand_cs_en(); nand_write_cmd(NAND_CMD_SEQIN); for(i=0;i<10;i++); nand_write_addr((PAGE_DATA_SIZE+ofs)&0xff); nand_write_addr(((PAGE_DATA_SIZE+ofs)>>8)&0xff); nand_write_addr(_page&0xff); nand_write_addr((_page>>8)&0xff); nand_write_addr((_page>>16)&0xff); for(i=0;i<len;i++) { nand_write(*spare++); } nand_write_cmd(NAND_CMD_PAGEPROG); nand_wait(); /* wait tPROG 200~500us; */ stat = read_nand_stats(); if(!stat) /* Page write error */ { nand_cs_ds(); return 0; } else { nand_cs_ds(); return 1; } }
static int nand_burn_image(size_t image_size) { int ret, block_size; nand_info_t *nand; int dev = nand_curr_device; if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) || (!nand_info[dev].name)) { puts("\nno devices available\n"); return -ENOMEDIUM; } nand = &nand_info[dev]; block_size = nand->erasesize; /* Align U-Boot size to currently used blocksize */ image_size = ((image_size + (block_size - 1)) & (~(block_size - 1))); /* Erase the U-BOOT image space */ printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size); ret = nand_erase(nand, 0, image_size); if (ret) { printf("Error!\n"); goto error; } printf("Done!\n"); /* Write the image to flash */ printf("Writing image:..."); printf("&image_size = 0x%p\n", (void *)&image_size); ret = nand_write(nand, 0, &image_size, (void *)get_load_addr()); if (ret) printf("Error!\n"); else printf("Done!\n"); error: return ret; }
/* load from nand_flash */ int nand(int argc, char *argv[]) { int nand_addr, sdram_addr; unsigned int size; if (argc < 5) return 0; sdram_addr = atoi(argv[2]); nand_addr = atoi(argv[3]); size = atoi(argv[4]); printf("sdram 0x%x, nand 0x%x, size 0x%x\n", sdram_addr, nand_addr, size); if (strcmp(argv[1], "read") == 0) nand_read(sdram_addr, nand_addr, size); if (strcmp(argv[1], "write") == 0) nand_write(sdram_addr, nand_addr, size); printf("nand %s finished!\n", argv[1]); return 0; }
static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, int read) { int ret = 0; while (count--) { /* Raw access */ mtd_oob_ops_t ops = { .datbuf = (u8 *)addr, .oobbuf = ((u8 *)addr) + nand->writesize, .len = nand->writesize, .ooblen = nand->oobsize, .mode = MTD_OOB_RAW }; if (read) ret = nand->read_oob(nand, off, &ops); else ret = nand->write_oob(nand, off, &ops); if (ret) { printf("%s: error at offset %llx, ret %d\n", __func__, (long long)off, ret); break; } addr += nand->writesize + nand->oobsize; off += nand->writesize; } return ret; } static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int i, ret = 0; ulong addr; loff_t off, size; char *cmd, *s; nand_info_t *nand; #ifdef CONFIG_SYS_NAND_QUIET int quiet = CONFIG_SYS_NAND_QUIET; #else int quiet = 0; #endif const char *quiet_str = getenv("quiet"); int dev = nand_curr_device; int repeat = flag & CMD_FLAG_REPEAT; /* at least two arguments please */ if (argc < 2) goto usage; if (quiet_str) quiet = simple_strtoul(quiet_str, NULL, 0) != 0; cmd = argv[1]; /* Only "dump" is repeatable. */ if (repeat && strcmp(cmd, "dump")) return 0; if (strcmp(cmd, "info") == 0) { putc('\n'); for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { if (nand_info[i].name) nand_print_and_set_info(i); } return 0; } if (strcmp(cmd, "device") == 0) { if (argc < 3) { putc('\n'); if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE) puts("no devices available\n"); else nand_print_and_set_info(dev); return 0; } dev = (int)simple_strtoul(argv[2], NULL, 10); set_dev(dev); return 0; } #ifdef CONFIG_ENV_OFFSET_OOB /* this command operates only on the first nand device */ if (strcmp(cmd, "env.oob") == 0) return do_nand_env_oob(cmdtp, argc - 1, argv + 1); #endif /* The following commands operate on the current device, unless * overridden by a partition specifier. Note that if somehow the * current device is invalid, it will have to be changed to a valid * one before these commands can run, even if a partition specifier * for another device is to be used. */ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) { puts("\nno devices available\n"); return 1; } nand = &nand_info[dev]; if (strcmp(cmd, "bad") == 0) { printf("\nDevice %d bad blocks:\n", dev); for (off = 0; off < nand->size; off += nand->erasesize) if (nand_block_isbad(nand, off)) printf(" %08llx\n", (unsigned long long)off); return 0; } /* * Syntax is: * 0 1 2 3 4 * nand erase [clean] [off size] */ if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) { nand_erase_options_t opts; /* "clean" at index 2 means request to write cleanmarker */ int clean = argc > 2 && !strcmp("clean", argv[2]); int scrub_yes = argc > 2 && !strcmp("-y", argv[2]); int o = (clean || scrub_yes) ? 3 : 2; int scrub = !strncmp(cmd, "scrub", 5); int spread = 0; int args = 2; const char *scrub_warn = "Warning: " "scrub option will erase all factory set bad blocks!\n" " " "There is no reliable way to recover them.\n" " " "Use this command only for testing purposes if you\n" " " "are sure of what you are doing!\n" "\nReally scrub this NAND flash? <y/N>\n"; if (cmd[5] != 0) { if (!strcmp(&cmd[5], ".spread")) { spread = 1; } else if (!strcmp(&cmd[5], ".part")) { args = 1; } else if (!strcmp(&cmd[5], ".chip")) { args = 0; } else { goto usage; } } /* * Don't allow missing arguments to cause full chip/partition * erases -- easy to do accidentally, e.g. with a misspelled * variable name. */ if (argc != o + args) goto usage; printf("\nNAND %s: ", cmd); /* skip first two or three arguments, look for offset and size */ if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0) return 1; nand = &nand_info[dev]; memset(&opts, 0, sizeof(opts)); opts.offset = off; opts.length = size; opts.jffs2 = clean; opts.quiet = quiet; opts.spread = spread; if (scrub) { if (!scrub_yes) puts(scrub_warn); if (scrub_yes) opts.scrub = 1; else if (getc() == 'y') { puts("y"); if (getc() == '\r') opts.scrub = 1; else { puts("scrub aborted\n"); return -1; } } else { puts("scrub aborted\n"); return -1; } } ret = nand_erase_opts(nand, &opts); printf("%s\n", ret ? "ERROR" : "OK"); return ret == 0 ? 0 : 1; } if (strncmp(cmd, "dump", 4) == 0) { if (argc < 3) goto usage; off = (int)simple_strtoul(argv[2], NULL, 16); ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat); return ret == 0 ? 1 : 0; } if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) { size_t rwsize; ulong pagecount = 1; int read; int raw = 0; if (argc < 4) goto usage; addr = (ulong)simple_strtoul(argv[2], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ printf("\nNAND %s: ", read ? "read" : "write"); nand = &nand_info[dev]; s = strchr(cmd, '.'); if (s && !strcmp(s, ".raw")) { raw = 1; if (arg_off(argv[3], &dev, &off, &size)) return 1; if (argc > 4 && !str2long(argv[4], &pagecount)) { printf("'%s' is not a number\n", argv[4]); return 1; } if (pagecount * nand->writesize > size) { puts("Size exceeds partition or device limit\n"); return -1; } rwsize = pagecount * (nand->writesize + nand->oobsize); } else { if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0) return 1; rwsize = size; } if (!s || !strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i")) { if (read) ret = nand_read_skip_bad(nand, off, &rwsize, (u_char *)addr); else ret = nand_write_skip_bad(nand, off, &rwsize, (u_char *)addr, 0); #ifdef CONFIG_CMD_NAND_TRIMFFS } else if (!strcmp(s, ".trimffs")) { if (read) { printf("Unknown nand command suffix '%s'\n", s); return 1; } ret = nand_write_skip_bad(nand, off, &rwsize, (u_char *)addr, WITH_DROP_FFS); #endif }else if((!read) && (s != NULL) && (!strcmp(s, ".uboot")) && nand->writesize == 4096){ rwsize = 4096; nand_write(nand, off, &rwsize, (u_char *)addr); off+= 4096; addr+= 2048; nand_write(nand, off, &rwsize, (u_char *)addr); off+= 4096; addr+= 2048; nand_write(nand, off, &rwsize, (u_char *)addr); off+= 4096; addr+= 2048; nand_write(nand, off, &rwsize, (u_char *)addr); off+= 4096; addr+= 2048; rwsize = CONFIG_SYS_NAND_U_BOOT_SIZE - 8*1024; ret = nand_write(nand, off, &rwsize, (u_char *)addr); #ifdef CONFIG_CMD_NAND_YAFFS } else if (!strcmp(s, ".yaffs")) { if (read) { printf("Unknown nand command suffix '%s'.\n", s); return 1; } ret = nand_write_skip_bad(nand, off, &rwsize, q (u_char *)addr, WITH_INLINE_OOB); #endif } else if (!strcmp(s, ".oob")) { /* out-of-band data */ mtd_oob_ops_t ops = { .oobbuf = (u8 *)addr, .ooblen = rwsize, .mode = MTD_OOB_RAW }; if (read) ret = nand->read_oob(nand, off, &ops); else ret = nand->write_oob(nand, off, &ops); } else if (raw) {
int flash_test(void) { struct nand_chip *nand_chip = nand_info[0].priv; nand_info_t *nand; int count; int ret = 0; /*********************** ERASE - start ***************************************/ struct erase_info instr; ulong start; ulong end = 0x8000000; ulong ofs = 0; ulong block; ulong off; size_t size; int i = 0; int test_passed = 1; int p_test_passed = 1; u_char *read_buff = (u_char *) FLASH_READ_BUF_ADDR; u_char *write_buff = (u_char *) FLASH_WRITE_BUF_ADDR; nand = &nand_info[nand_curr_device]; /* Added to check nand bad block */ ret = check_nand_bad_block(nand); if (ret != 0) { printf("FAILED\n"); return -1; } for (count = 0; count < 3; count++) { start = 283; end = 345; if (count == 1) { start = 1103; end = 1165; } else if (count == 2) { start = 1922; end = 1984; } if (!end || end < 0) end = start; printf("Running Erase Test...Please wait..."); printf("Start Block : %d, End Block : %d\n", (int)start, (int)end); for (i = 0; i < 0x20000; i++) { write_buff[i] = (unsigned char)i; } for (block = start; block <= end; ofs++, block++) { instr.addr = block << nand_chip->phys_erase_shift; instr.len = 1 << nand_chip->phys_erase_shift; off = instr.addr; size = instr.len; ret = nand_erase(nand, off, size); if (ret) { if (!nand_block_isbad(nand, off)) { printf("erase failed at block %d\n", (int)block); p_test_passed = test_passed = 0; } continue; } } /*********************** ERASE - end ***************************************/ if (p_test_passed) { printf("PASSED\n"); } else printf("FAILED\n"); p_test_passed = 1; printf("Running Write test...Please wait..."); printf("Start Block : %d, End Block : %d\n", (int)start, (int)end); for (block = start; block <= end; ofs++, block++) { instr.addr = block << nand_chip->phys_erase_shift; instr.len = 1 << nand_chip->phys_erase_shift; off = instr.addr; size = instr.len; ret = nand_write(nand, off, &size, (u_char *) write_buff); if (ret) { printf("Error writing to NAND: ret = %d\n", ret); p_test_passed = test_passed = 0; continue; } } if (p_test_passed) { printf("PASSED\n"); } else printf("FAILED\n"); p_test_passed = 1; printf("Running Read test...Please wait..."); printf("Start Block : %d, End Block : %d\n", (int)start, (int)end); for (block = start; block <= end; ofs++, block++) { instr.addr = block << nand_chip->phys_erase_shift; instr.len = 1 << nand_chip->phys_erase_shift; off = instr.addr; size = instr.len; nand_read(nand, off, &size, (u_char *) read_buff); for (i = 0; i < 0x20000; i++) { if (read_buff[i] != (unsigned char)i) { if (!nand_block_isbad(nand, off)) { printf("write-read failed at offset 0x%x (0x%x)\n", (unsigned int)(block * 0x20000 + i), read_buff[i]); p_test_passed = test_passed = 0; } break; } } } if (p_test_passed) { printf("PASSED\n"); } else { printf("FAILED\n"); } } /*********************** ERASE - start ***************************************/ printf("Erase nand after completing the Nand write read test... \n"); { struct erase_info instr; ulong start; ulong end = 0x8000000; ulong ofs = 0; ulong block; ulong off, size; int i = 0; u_char *write_buff = (u_char *) FLASH_WRITE_BUF_ADDR; nand = &nand_info[nand_curr_device]; for (count = 0; count < 3; count++) { start = 283; end = 345; if (count == 1) { start = 1103; end = 1165; } else if (count == 2) { start = 1922; end = 1984; } if (!end || end < 0) end = start; printf("Running Erase Test...Please wait..."); printf("Start Block : %d, End Block : %d\n", (int)start, (int)end); for (i = 0; i < 0x20000; i++) { write_buff[i] = (unsigned char)i; } for (block = start; block <= end; ofs++, block++) { instr.addr = block << nand_chip->phys_erase_shift; instr.len = 1 << nand_chip->phys_erase_shift; off = instr.addr; size = instr.len; ret = nand_erase(nand, off, size); if (ret) { if (!nand_block_isbad(nand, off)) { printf("erase failed at block %d\n", (int)block); p_test_passed = test_passed = 0; } continue; } } } } /*********************** ERASE - end ***************************************/ printf("Nand Test Completed... %s\n", ((test_passed) ? "PASS" : "FAIL")); return 0; }
void cmd_nand_write(int argc, char** argv) { if(argc < 6) { bufferPrintf("Usage: %s <data> <spare> <bank> <page> <ecc>\r\n", argv[0]); return; } uint32_t address = parseNumber(argv[1]); uint32_t spare = parseNumber(argv[2]); uint32_t bank = parseNumber(argv[3]); uint32_t page = parseNumber(argv[4]); uint32_t ecc = parseNumber(argv[5]); bufferPrintf("nand_write(%d, %d, %x, %x, %d) = %d\r\n", bank, page, address, spare, ecc, nand_write(bank, page, (uint8_t*) address, (uint8_t*) spare, ecc)); }
void update_program(void) { unsigned char *buf = (unsigned char *)0x52000000; unsigned long len = 0; int have_begin = 0; int nodata_time = 0; unsigned long erase_addr; char c; int i; /* 读串口获得数据 */ printf("\n\ruse V2.2.exe/gtkterm to send file\n\r", len); while (1) { if (getc_nowait(&buf[len]) == 0) { have_begin = 1; nodata_time = 0; len++; } else { if (have_begin) { nodata_time++; } } if (nodata_time == 1000) { break; } } printf("have get %d bytes data\n\r", len); printf("the first 16 bytes data: \n\r"); for (i = 0; i < 16; i++) { printf("%02x ", buf[i]); } printf("\n\r"); printf("Press Y to program the flash: \n\r"); c = getc(); if (c == 'y' || c == 'Y') { /* 烧写到nand flash block 0 */ for (erase_addr = 0; erase_addr < ((len + 0x1FFFF) & ~0x1FFFF); erase_addr += 0x20000) { nand_erase_block(erase_addr); } nand_write(0, buf, len); printf("update program successful\n\r"); } else { printf("Cancel program!\n\r"); } }
static int nand_biterr(nand_info_t *nand, loff_t addr, int bit) { nand_erase_options_t opts; struct mtd_oob_ops ops; uint8_t *datbuf, *pagebuf, *write_buf; size_t size; loff_t write_addr; int ret, pages; datbuf = malloc(nand->erasesize); if (!datbuf) { printf("biterr: out of memory\n"); return 1; } pagebuf = malloc(nand->writesize + nand->oobsize); if (!pagebuf) { printf("biterr: out of memory\n"); free(datbuf); return 1; } /* first read the whole erase block */ size = nand->erasesize; ret = nand_read(nand, addr & ~(nand->erasesize - 1), &size, datbuf); if (ret < 0 && ret != -EUCLEAN) { printf("biterr: nand_read failed\n"); goto err; } nand_use_ecc(nand, 0); /* read the affected page with oob */ memset(&ops, 0, sizeof(ops)); ops.datbuf = pagebuf; ops.oobbuf = pagebuf + nand->writesize; ops.len = nand->writesize; ops.ooblen = nand->oobsize; ops.mode = MTD_OOB_RAW; ret = nand->read_oob(nand, addr & ~(nand->writesize - 1), &ops); if (ret < 0) { printf("biterr: read_oob failed\n"); nand_use_ecc(nand, 1); goto err; } /* flip the bit(s) */ pagebuf[(addr & (nand->writesize - 1)) + (bit & ~7)] ^= 1 << (bit & 7); /* erase */ memset(&opts, 0, sizeof(opts)); opts.quiet = 1; opts.offset = addr & ~(nand->erasesize - 1); opts.length = nand->erasesize; ret = nand_erase_opts(nand, &opts); if (ret < 0) { printf("biterr: erase failed\n"); nand_use_ecc(nand, 1); goto err; } /* write the affected page back with oob in raw mode */ memset(&ops, 0, sizeof(ops)); ops.datbuf = pagebuf; ops.oobbuf = pagebuf + nand->writesize; ops.len = nand->writesize; ops.ooblen = nand->oobsize; ops.mode = MTD_OOB_RAW; ret = nand->write_oob(nand, addr & ~(nand->writesize - 1), &ops); if (ret < 0) { printf("biterr: write_oob failed\n"); nand_use_ecc(nand, 1); goto err; } nand_use_ecc(nand, 1); /* write back the other pages as normal */ write_addr = addr & ~(nand->erasesize - 1); write_buf = datbuf; for (pages = nand->erasesize / nand->writesize; pages > 0; pages--, write_addr += nand->writesize, write_buf += nand->writesize) { /* skip the block that was written back raw */ if (write_addr == (addr & ~(nand->writesize - 1))) continue; size = nand->writesize; ret = nand_write(nand, write_addr, &size, write_buf); if (ret < 0) printf("biterr: error writing back page 0x%llx\n", write_addr); } free(datbuf); free(pagebuf); return 0; err: free(datbuf); free(pagebuf); return 1; }
/* * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ int saveenv_nand(void) { size_t total; int ret = 0, i; u32 erasebase; u32 eraselength; u32 eraseblock; u32 erasesize = nand_info[0].erasesize; uint8_t *data; puts("Erasing Nand...\n"); /* If the value of CFG_ENV_OFFSET is not a NAND block boundary, the * NAND erase operation will fail. So first check if the CFG_ENV_OFFSET * is equal to a NAND block boundary */ if ((CFG_ENV_OFFSET % (erasesize - 1)) != 0 ) { /* CFG_ENV_OFFSET is not equal to block boundary address. So, read * the read the NAND block (in which ENV has to be stored), and * copy the ENV data into the copied block data. */ /* Step 1: Find out the starting address of the NAND block to * be erased. Also allocate memory whose size is equal to tbe * NAND block size (NAND erasesize). */ eraseblock = CFG_ENV_OFFSET / erasesize; erasebase = eraseblock * erasesize; data = (uint8_t*)malloc(erasesize); if (data == NULL) { printf("Could not save enviroment variables\n"); return 1; } /* Step 2: Read the NAND block into which the ENV data has * to be copied */ total = erasesize; for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) { if (nand_scan(&nand_info[i], 1) == 0) { ret = nand_read(&nand_info[0], erasebase, &total, data); } else { printf("no devices available\n"); return 1; } } if (ret || total != erasesize) { printf("Could not save enviroment variables %d\n",ret); return 1; } /* Step 3: Copy the ENV data into the local copy of the block * contents. */ memcpy((data + (CFG_ENV_OFFSET - erasebase)), (void*)env_ptr, CFG_ENV_SIZE); } else { /* CFG_ENV_OFFSET is equal to a NAND block boundary. So * no special care is required when erasing and writing NAND * block */ data = env_ptr; erasebase = CFG_ENV_OFFSET; erasesize = CFG_ENV_SIZE; } /* Erase the NAND block which will hold the ENV data */ if (nand_erase(&nand_info[0], erasebase, erasesize)) return 1; puts("Writing to Nand... \n"); total = erasesize; /* Write the ENV data to the NAND block */ ret = nand_write(&nand_info[0], erasebase, &total, (u_char*)data); if (ret || total != erasesize) { printf("Could not save enviroment variables\n"); return 1; } if ((CFG_ENV_OFFSET % (erasesize - 1)) != 0 ) free(data); puts("Saved enviroment variables\n"); return ret; }
/* * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ #ifdef CFG_ENV_OFFSET_REDUND int saveenv(void) { ulong total; int ret = 0; env_ptr->flags++; total = CFG_ENV_SIZE; if(gd->env_valid == 1) { puts ("Erasing redundant Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE)) return 1; puts ("Writing to redundant Nand... "); ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, (u_char*) env_ptr); } else { puts ("Erasing Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) return 1; puts ("Writing to Nand... "); ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*) env_ptr); } if (ret || total != CFG_ENV_SIZE) return 1; puts ("done\n"); gd->env_valid = (gd->env_valid == 2 ? 1 : 2); return ret; } #else /* ! CFG_ENV_OFFSET_REDUND */ int saveenv(void) //YWDRIVER_MODI lwj :这里需要注意,还需要加一些代码,否则如果要保存环境变量的地方是坏块的话,就会出问题的。 { //YWDRIVER_MODI 2010/3/5 d48zm modify #if 0 int ret = 0; int blockstart = -1; ulong erasesize_blockalign = nand_info[0].erasesize; u_char* data_ptr = (u_char*)env_ptr; ssize_t offset = CFG_ENV_OFFSET; ssize_t envlen = CFG_ENV_SIZE; ulong writelen = erasesize_blockalign; ulong checklen = erasesize_blockalign; ssize_t boundbegin = CFG_ENV_OFFSET + YW_CFG_NAND_ENV_BOUND - erasesize_blockalign; while ((envlen > 0) && (offset <= boundbegin)){ if (envlen < erasesize_blockalign){ checklen = envlen; writelen = envlen; } /* * new eraseblock, check for bad block(s). Stay in the * loop to be sure if the offset changes because of * a bad block, that the next block that will be * written to is also checked. Thus avoiding errors if * the block(s) after the skipped block(s) is also bad * (number of blocks depending on the blockalign */ while (blockstart != (offset & (~erasesize_blockalign+1))) { blockstart = offset & (~erasesize_blockalign+1); int ret = nand_block_isbad(&nand_info[0], offset); if (ret < 0) { printf("Bad block check failed\n"); return 1; } if (ret == 1) { offset = blockstart + erasesize_blockalign; printf("\rBad block at 0x%lx " "in erase block from " "0x%x will be skipped\n", (long) offset, blockstart); } } printf ("Erasing Nand block at 0x%lx...", offset); if (nand_erase(&nand_info[0], offset, erasesize_blockalign)) return 1; puts ("Writing to Nand block... "); ret = nand_write(&nand_info[0], offset, &writelen, data_ptr); if (ret || writelen != checklen) return 1; envlen -= writelen; data_ptr += writelen; offset += writelen; } #else ulong total; int ret = 0; puts ("Erasing Nand..."); if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) return 1; puts ("Writing to Nand... "); total = CFG_ENV_SIZE; ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); if (ret || total != CFG_ENV_SIZE) return 1; #endif //YWDRIVER_MODI end puts ("done\n"); return ret; }