u-boot-2014.10移植第22天----添加nand flash命令支持(四)
2015-02-09 10:07
603 查看
解决问题:
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 = %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;
+ }
再在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, 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
明天继续。
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 = %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;
+ }
再在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, 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
明天继续。
相关文章推荐
- [置顶] u-boot-2014.10移植第19天----添加nand flash命令支持(一)
- [置顶] u-boot-2014.10移植第20天----添加nand flash命令支持(二)
- u-boot-2014.10移植第21天----添加nand flash命令支持(三)
- TX2440 ARM开发板Uboot移植(三、添加Nand Flash的有关操作支持)
- u-boot-2014.10移植第17天----添加DM9000网卡支持(一)
- u-boot-2014.10移植第18天----添加DM9000网卡支持(二)
- u-boot-2011.03在mini2440/micro2440上的移植(五)——支持Nand Flash
- <2012 12 05> FL2440开发板的U-boot-2010.09版本移植(七)NAND Flash启动支持
- u-boot移植(四)添加网络支持
- U-boot移植日志(7)--使u-boot的help命令支持通配符(*)
- AT91SAM9260下的U-Boot移植和添加LCD驱动支持
- fl2440的U-boot-2010.09移植(四) 添加NOR Flash启动支持
- 第一次移植uboot(3)(添加DM9000网卡支持) .
- 移植u-boot1.1.4支持操作nandFlash的nand erase命令
- u-boot-2012.04.01移植到TQ2440(五):支持NAND FLASH读写
- TQ2440 u-boot-2012.04.01移植四支持NAND Flash
- U-boot移植 (v2012.04.1 S3C2440平台) (三) Nor flash Nand flash 驱动支持
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###8. u-boot引导启动nand flash中内核和根文件系统cramfs和用户文件系统yaffs2支持
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###7.NAND FLASH部分移植和支持NAND FLASH启动和读写
- u-boot移植(六)添加nandflash支持