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校验方法。
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校验方法。
相关文章推荐
- S3C2416移植内核linux2.6.35步骤和错误,文件系统挂载不上?
- Linux 修改系统变量错误大致基础命令不能使用问题修复!
- 巧用backtrace系列函数,在不具备gdb环境的Linux系统上大致定位段错误位置
- 【转载】移植多款轻量级 Web服务器到ARM-Linux系统
- 移植交换芯片SDK到Linux系统
- linux系统移植和Uboot 移植
- 嵌入式Linux之我行——内核、文件系统、应用移植开发篇
- 移植linux2.6.29内核及根文件系统到UP-CPU-2410(1)
- Linux3.4.0 Yaffs2文件系统移植-支持Android4.0
- 基于S3C2440的Linux-3.6.6移植——devfs文件系统的IIC应用
- linux-2.6.32在mini2440开发板上移植----移植Nand驱动并修改分区信息
- MySQLdb错误 编码问题 linux系统粘贴板 python取环境变量 2016.05.27回顾
- linux-2.6.24.4内核移植到s3c2440----使用busybox-1.9.2制作根文件系统
- zybo开发板linux作业系统移植
- 在不具备gdb环境的类Linux系统开发板上调试段错误,大致定位出错函数位置
- Linux-2.6.28内核移植及Yaffs文件系统制作 for FL2440(一)
- Linux系统grub常见错误问题解决
- Linux系统内存错误产生的原因及调试方法
- linux-2.6.18内核移植及根文件系统的制做(简易)
- Linux 系统错误码及其说明