flash_erase擦除NAND flash坏块失败
板子使用busybox文件系统,带了mtd-utils的工具,包括flash_erase。首先查看帮助信息:
[root@M3250 ~]# flash_erase --h Usage: flash_erase [options] MTD_DEVICE <start offset> <block count> Erase blocks of the specified MTD device. Specify a count of 0 to erase to end of device. -j, --jffs2 format the device for jffs2 -N, --noskipbad dont skip bad blocks -u, --unlock unlock sectors before erasing -q, --quiet display progress messages --silent same as --quiet --help display this help and exit --version output version information and exit [root@M3250 ~]#
看样子flash_erase默认不擦除坏块的,但可以使用-N选项启用这个功能。但是结果如下:
[root@M3250 ~]# flash_erase -N /dev/mtd4 0 0 Erasing 128 Kibyte @ 0 -- 0 % nand_erase_nand: attempt to erase a bad block at page 0x0001ff00 Erasing 128 Kibyte @ 2nand_erase_nand: attempt to erase a bad block at page0x0001ff40 Erasing 128 Kibyte @ 40000 -- 50 % complete libmtd: error!: MEMERASE64 ioctl failed for eraseblock 2 (mtd4) error 5 (Input/output error) flash_erase: error!: /dev/mtd4: MTD Erase failure error 5 (Input/output error) Erasing 128 Kibyte @ 60000 -- 75 % complete libmtd: error!: MEMERASE64 ioctl failed for eraseblock 3 (mtd4) error 5 (Input/output error) flash_erase: error!: /dev/mtd4: MTD Erase failure error 5 (Input/output error) Erasing 128 Kibyte @ 60000 -- 100 % complete
还是擦不了。看了下内核的代码,在/drivers/mtd/nand/nand_base.c中nand_erase_nand函数有这么一段:
while (len) { /* * heck if we have a bad block, we do not erase bad blocks ! */ if (nand_block_checkbad(mtd, ((loff_t) page) << chip->page_shift, 0, allowbbt)) { printk(KERN_WARNING "%s:attempt to erase a bad block " "at page 0x%08x ", __func__, page); instr->state = MTD_ERASE_FAILED; goto erase_exit; }
结论就是linux内核不支持擦除坏块。 解决办法:在uboot中使用"nand scrub"擦除。
附上自己写的mtd擦除程序:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <mtd/mtd-user.h> #include <sys/ioctl.h> int main(int argc, char *argv[]) { int dev_fd; int result; erase_info_t erase; mtd_info_t mtd; int rt = 0; if (argc !=2) { printf("%s:input a argument like /dev/mtdX ", argv[0]); rt = -1; goto exit; } printf("the device you want to erase is %s ", argv[1]); dev_fd = open (argv[1], O_SYNC | O_RDWR); if (dev_fd < 0) { printf("open %s failed ", argv[1]); perror("erase mtd"); rt = -1; goto exit; } if (ioctl(dev_fd, MEMGETINFO, &mtd) < 0) { printf("%s:MTD getinfo failed ", argv[1]); perror("get mtd info"); rt = -1; goto close; } erase.start = 0; erase.length = mtd.size; if (ioctl (dev_fd, MEMERASE, &erase) < 0) { printf("%s: erase failed ", argv[1]); perror("erase mtd"); rt = -1; goto close; } printf("erase %s sucess ", argv[1]); close: close(dev_fd); exit: return rt; }
============================================