NAND 坏块的手动解除

      NAND的校验,在一定程度上保证了数据完整性,但是判断方式会误判出可用的“坏块”,然后将其标记,下次读写时会跳过,但是呢,在写入后校验时,调用的确实memcmp(),这个是标准函数,不会跳过坏块,这样遇到坏块就校验不过,然后就提示fail


OK210 # nand erase.chip

NAND erase.chip: device 0 whole chip
Skipping bad block at  0x00080000                                          
Erasing at 0x3ff80000 -- 100% complete.
OK
OK210 # nand write 0 $filesize

NAND write: device 0 offset 0x9104, size 0x3fff6efc
size adjusted to 0x3ff76efc (1 bad blocks)
Attempt to write non page-aligned data
 0 bytes written: ERROR
OK210 # nand write 20000000 0 $filesize

NAND write: device 0 offset 0x0, size 0x9104
nand_write: rval=0
memcmp: rval=1
nand_verify: rval=-5
NAND write to offset 0 failed -5
 0 bytes written: ERROR
OK210 #

     
OK210 # nand bad

Device 0 bad blocks:
  00080000



int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf)
{
        int rval = 0;
        size_t verofs;
        size_t verlen = mtd->writesize;
        uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen);

        if (!verbuf)
                return -ENOMEM;

        /* Read the NAND back in page-size groups to limit malloc size */
        for (verofs = ofs; verofs < ofs + len;
             verofs += verlen, buf += verlen) {
                verlen = min(mtd->writesize, (uint32_t)(ofs + len - verofs));
                rval = nand_read(mtd, verofs, &verlen, verbuf);
                if (!rval || (rval == -EUCLEAN)) {
                        rval = memcmp(buf, verbuf, verlen);
                        printf("memcmp: rval=%d\n", rval);
                }
    
                if (rval)
                        break;
        }

        free(verbuf);

        return rval ? -EIO : 0;
}


      不知道什么时候,0x00080000被标记为坏块,因此在写入时跳过0x00080000,但是nand_verify校验时没有跳过,就这样返回了-EIO。


      u-boot-2016.07这个版本,在doc下的说明文档中也说了,使用的是linux的nand代码,并没有完整、系统性测过,在uboot环境下可能会有问题。

NOTE:
=====

The Disk On Chip driver is currently broken and has been for some time.
There is a driver in drivers/mtd/nand, taken from Linux, that works with
the current NAND system but has not yet been adapted to the u-boot
environment.

        不管是不是nand驱动问题, 0x00080000可能是被误标记的,所以需要清除它。


OK210 # nand erase scrub     
nand - NAND sub-system

Usage:
nand info - show available NAND devices
nand device [dev] - show or set current device
nand read - addr off|partition size
nand write - addr off|partition size
    read/write 'size' bytes starting at offset 'off'
    to/from memory address 'addr', skipping bad blocks.
nand read.raw - addr off|partition [count]
nand write.raw - addr off|partition [count]
    Use read.raw/write.raw to avoid ECC and access the flash as-is.
nand erase[.spread] [clean] off size - erase 'size' bytes from offset 'off'
    With '.spread', erase enough for given file size, otherwise,
    'size' includes skipped bad blocks.
nand erase.part [clean] partition - erase entire mtd partition'
nand erase.chip [clean] - erase entire chip'
nand bad - show bad blocks
nand dump[.oob] off - dump page
nand scrub [-y] off size | scrub.part partition | scrub.chip
    really clean NAND erasing bad blocks (UNSAFE)
nand markbad off [...] - mark bad block(s) at offset (UNSAFE)
nand biterr off - make a bit error at offset (UNSAFE)
OK210 # nand scrub.params
nand - NAND sub-system

Usage:
nand info - show available NAND devices
nand device [dev] - show or set current device
nand read - addr off|partition size
nand write - addr off|partition size
    read/write 'size' bytes starting at offset 'off'
    to/from memory address 'addr', skipping bad blocks.
nand read.raw - addr off|partition [count]
nand write.raw - addr off|partition [count]
    Use read.raw/write.raw to avoid ECC and access the flash as-is.
nand erase[.spread] [clean] off size - erase 'size' bytes from offset 'off'
    With '.spread', erase enough for given file size, otherwise,
    'size' includes skipped bad blocks.
nand erase.part [clean] partition - erase entire mtd partition'
nand erase.chip [clean] - erase entire chip'
nand bad - show bad blocks
nand dump[.oob] off - dump page
nand scrub [-y] off size | scrub.part partition | scrub.chip
    really clean NAND erasing bad blocks (UNSAFE)
nand markbad off [...] - mark bad block(s) at offset (UNSAFE)
nand biterr off - make a bit error at offset (UNSAFE)
OK210 # nand scrub.part params

NAND scrub.part: device 0 offset 0x80000, size 0x80000
Warning: scrub option will erase all factory set bad blocks!
         There is no reliable way to recover them.
         Use this command only for testing purposes if you
         are sure of what you are doing!

Really scrub this NAND flash? <y/N>
Erasing at 0x80000 -- 100% complete.
OK
OK210 #

      我认为它是好的,下面操作看看,是否还会不会被标记为坏块。

OK210 # nand scrub.chip

NAND scrub.chip: device 0 whole chip
Warning: scrub option will erase all factory set bad blocks!
         There is no reliable way to recover them.
         Use this command only for testing purposes if you
         are sure of what you are doing!

Really scrub this NAND flash? <y/N>
y
Erasing at 0x3ff80000 -- 100% complete.
OK
OK210 # 
OK210 # 
OK210 # 
OK210 # 
OK210 # 
OK210 # nand erase.chip

NAND erase.chip: device 0 whole chip
Skipping bad block at  0x3fe00000                                          
Skipping bad block at  0x3fe80000                                          
Skipping bad block at  0x3ff00000                                          
Skipping bad block at  0x3ff80000                                          

OK
OK210 # nand bad

Device 0 bad blocks:
  3fe00000
  3fe80000
  3ff00000
  3ff80000
OK210 # 

      至少说明 0x00080000是可以的