您的位置:首页 > 运维架构 > Linux

linux系统移植之nand ecc错误

2014-04-28 08:40 155 查看
Host:Ubuntu-12.04

Target:Tiny6410

简介:移植linux-3.2.4时遇到的错误,由NAND ECC引起,导致Oops - undefined instruction的错误。

错误提示:No oob scheme defined for oobsize 436

kernel BUG at drivers/mtd/nand/nand_base.c:3268!



通常Oops错误提示会告诉我们错误发生的位置(PC值)、错误所处的函数(nand_scan_tail)以及函数的调用关系。不过这段函数中恰好有BUG()函数的存在,它赤裸裸告诉我们错误就发生在nand_base.c的第3268行。所以直接去跟踪源码好了。源码跟踪如下

1、nand_scan_tail(&nmtd->mtd)部分源码

/*

* If no default placement scheme is given, select an appropriate one

*/

if (!chip->ecc.layout) {

switch (mtd->oobsize) {

case 8:

chip->ecc.layout = &nand_oob_8;

break;

case 16:

chip->ecc.layout = &nand_oob_16;

break;

case 64:

chip->ecc.layout = &nand_oob_64;

break;

case 128:

chip->ecc.layout = &nand_oob_128;

break;

default:

printk(KERN_WARNING "No oob scheme defined for "

"oobsize %d\n", mtd->oobsize);

BUG();//报告错误的位置

}

}

我的板子上mtd->oobsize的值读出来是436(有看到别人的读出来是218),在驱动代码里没有这个值,所以BUG()报错了,但这并不是真正的错误。nand flash驱动我也不懂,不过可以试着跟着源码看看引起错误的真正原因。首先引起我关注的是这段代码的入口if
(!chip->ecc.layout) ,我先将它做个标记。然后追踪代码的调用关系,根据Oops的信息发现是s3c2410.c中的static
int s3c24xx_nand_probe()调用了nand_scan_tail(),部分代码如下:

s3c2410_nand_init_chip(info,
nmtd, sets);

nmtd->scan_res = nand_scan_ident(&nmtd->mtd,

(sets) ? sets->nr_chips : 1,

NULL);

if (nmtd->scan_res == 0) {

s3c2410_nand_update_chip(info, nmtd);

nand_scan_tail(&nmtd->mtd);

s3c2410_nand_add_partition(info, nmtd, sets);

}

这里我注意到2个函数,一个是s3c2410_nand_init_chip(),一个是s3c2410_nand_update_chip()。首先看s3c2410_nand_update_chip(),部分代码如下:

if
(chip->ecc.mode != NAND_ECC_HW)

return;

/*
change the behaviour depending on wether we are using

* the large or small page nand device */

if (chip->page_shift > 10) {

chip->ecc.size = 256;

chip->ecc.bytes = 3;

} else {

chip->ecc.size = 512;

chip->ecc.bytes = 3;

chip->ecc.layout = &nand_hw_eccoob;

}

这段代码说明,当ECC的mode不是NAND_ECC_HW时,则初始化ecc的部分成员,包括laout,否则,不需要初始化,直接返回。根据前面的分析可知,chip->ecc.layout的是否初始化直接影响nand_scan_tail(&nmtd->mtd)函数的后续判断。这下问题清晰明了了,ecc的mode决定程序的走向,所以我们需要对mode追本溯源,而这一步,将在s3c2410_nand_init_chip()函数找到答案。追踪该函数代码,部分如下:

#ifdef
CONFIG_MTD_NAND_S3C2410_HWECC

static int hardware_ecc = 1;

#else

static int hardware_ecc = 0;

#endif

......

if
(hardware_ecc) {

chip->ecc.calculate = s3c2410_nand_calculate_ecc;

chip->ecc.correct = s3c2410_nand_correct_data;

chip->ecc.mode = NAND_ECC_HW;

......

问题终于搞清楚了,原来是配置内核的时候我直接使用make s3c6400_deconfig生成.config,没有选择硬件ECC,导致程序默认启用了软件ECC,引起了错误。由于不懂NAND驱动及ECC校验方法,所以只能解释到这里,后续仍需跟进nand驱动及ECC校验方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: