u-boot-2014.10移植第22天----添加nand flash命令支持(四)
解决问题: 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; 每个block用2个比特表示是否为坏块。 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 <fulinux@sina.com> */ #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 = %dn",a); int i; for(i = 0; i < 10; i++){ printf("0x%Xn",bbt[i]); } return 0; } /* -----End of main()----- */ 结果: ?./bbt-test ? ? 二进制为: 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; + } 再在nand_erase_opts函数中作如下修改: 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); 上面修改的意思是既然要将nand恢复出厂设置,那就不必要再去检测要擦出的函数是否是坏块了,所以把以前的那个检测是否是坏块的函数指针保存起来,在将其chip->block_bad指针指向了nand_block_bad_scrub函数,该函数什么都没做就返回了。同时将bbt清空,置为NULL,这在后面的 static int nand_block_checkbad(struct mtd_info *mtd,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,allowbbt); }函数中因为chip->bbt == NULL而执行chip->block_bad函数,但是该函数在上面已经换成的了一个什么都没做的nand_block_bad_scrub函数。所以不会返回有坏块。在nand_erase_nand函数中就不会因为调用nand_block_checkbad函数而始终擦除不了被标识的会快而出现问题了。 恢复出厂设置后,再将前面chip->block_bad指针重新指向先前的函数,同时再分配bbt区域,并重新扫描一下是否有坏块。 演示: [TQ2440 #] nand bad 明天继续。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |