1. 程式人生 > >flash_erase擦除NAND flash壞塊失敗

flash_erase擦除NAND flash壞塊失敗

板子使用busybox檔案系統,帶了mtd-utils的工具,包括flash_erase。首先檢視幫助資訊:

[[email protected] ~]# 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   don't 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
[[email protected] ~]#

看樣子flash_erase預設不擦除壞塊的,但可以使用-N選項啟用這個功能。但是結果如下:

[[email protected] ~]# 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\n", __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\n", argv[0]);
                rt = -1;
                goto exit;
        }
        printf("the device you want to erase is %s\n", argv[1]);

        dev_fd = open (argv[1], O_SYNC | O_RDWR);
        if (dev_fd < 0) {
                printf("open %s failed\n", argv[1]);
                perror("erase mtd");
                rt =  -1;
                goto exit;
        }

        if (ioctl(dev_fd, MEMGETINFO, &mtd) < 0) {
                printf("%s:MTD getinfo failed\n", 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\n", argv[1]);
                perror("erase mtd");
                rt = -1;
                goto close;
        }
        printf("erase %s sucess\n", argv[1]);

close:
        close(dev_fd);
exit:
        return rt;
}


============================================
作者:yuanlulu
http://blog.csdn.net/yuanlulu
版權沒有,但是轉載請保留此段宣告

============================================