解决问题:
nand0: MTD Erase failure: -5
drivers/mtd/nand/nand_bbt.c文件中初始化bbt
/* * Allocate memory (2bit per block) and clear the memory bad block * table. */ this->bbt = kzalloc(len, GFP_KERNEL); if (!this->bbt) return -ENOMEM;
nand_scan_bbt
------>nand_memory_bbt
----------->create_bbt
---------------->scan_block_fast
下面的两个函数用来查看和标记上面说的每个block的2比特位。初步分析坏块时2比特位置为11。
static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block) { uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT]; entry >>= (block & BBT_ENTRY_MASK) * 2; return entry & BBT_ENTRY_MASK; } static inline void bbt_mark_entry(struct nand_chip *chip, int block, uint8_t mark) { uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2); chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk; }我写了一个类似的程序来验证:
/* * Copyright: (C) 2014 fulinux <[email protected]> */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> uint8_t bbt[10]; void bbt_mark_entry(uint8_t *bbt, int block) { uint8_t msk = (0x03 & 0x03) << ((block & 0x03) * 2); bbt[block >> 2] |= msk; } uint8_t bbt_get_entry(uint8_t *bbt, int block) { uint8_t entry = bbt[block >> 2]; entry >>= (block & 0x3) * 2; return entry & 0x3; } /* * */ int main (int argc, char **argv) { uint8_t a; bbt_mark_entry(bbt, 5); bbt_mark_entry(bbt, 7); bbt_mark_entry(bbt, 2); a = bbt_get_entry(bbt, 5); printf("a = %d\n", a); int i; for(i = 0; i < 10; i++){ printf("0x%X\n", bbt[i]); } return 0; } /* -----End of main()----- */
结果:
./bbt-test
a = 3
0x30
0xCC
0x0
0x0
0x0
0x0
0x0
0x0
0x0
0x0
二进制为:
1100110000110000
说明是正确的。
最后的解决方法:
在drivers/mtd/nand/nand_util.c文件中添加如下函数:
#define cpu_to_je16(x) (x) #define cpu_to_je32(x) (x) + static int nand_block_bad_scrub(struct mtd_info *mtd, loff_t ofs, int getchip) + { + return 0; + }
int percent_complete = -1; + int (*nand_block_bad_old)(struct mtd_info *, loff_t, int) = NULL; const char *mtd_device = meminfo->name;
if (opts->scrub) { erase.scrub = opts->scrub; + nand_block_bad_old = chip->block_bad; + chip->block_bad = nand_block_bad_scrub; /* * We don't need the bad block table anymore... * after scrub, there are no bad blocks left! */ if (chip->bbt) { kfree(chip->bbt); } chip->bbt = NULL;最后:
+ if(nand_block_bad_old){ + chip->block_bad = nand_block_bad_old; + } if (opts->scrub) chip->scan_bbt(meminfo);
static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) { struct nand_chip *chip = mtd->priv; if (!chip->bbt){ return chip->block_bad(mtd, ofs, getchip); } /* Return info from the table */ return nand_isbad_bbt(mtd, ofs, allowbbt); }函数中因为chip->bbt == NULL而执行chip->block_bad函数,但是该函数在上面已经换成的了一个什么都没做的nand_block_bad_scrub函数。所以不会返回有坏块。在nand_erase_nand函数中就不会因为调用nand_block_checkbad函数而始终擦除不了被标识的会快而出现问题了。
恢复出厂设置后,再将前面chip->block_bad指针重新指向先前的函数,同时再分配bbt区域,并重新扫描一下是否有坏块。
演示:
[TQ2440 #] nand bad
Device 0 bad blocks:
[TQ2440 #] nand markbad 0
block 0x00000000 successfully marked as bad
[TQ2440 #] nand scrub 0 4000
NAND scrub: device 0 offset 0x0, size 0x4000
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 0x0 -- 100% complete.
OK
明天继续。