linux系统移植之nand ecc错误

来源:互联网 发布:斗鱼tv网络直播门事件 编辑:程序博客网 时间:2024/05/18 01:34

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校验方法。

0 0
原创粉丝点击