微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > yaffs2中,mount mtd block设备后,insmod就死掉了

yaffs2中,mount mtd block设备后,insmod就死掉了

时间:11-20 来源:互联网 点击:
Linux 2.6.22,加了最新的yaffs2,实现了nand flash驱动后,用mtd test测试驱动工作都正常的。

但是,最新发现一个很诡异的问题:

mount /dev/mtdblock4 /mnt/usb_msc 后,自动挂载成yaff2文件系统之后,再去insmod任何一个ko,都会死掉,而且还是没有任何输出信息的,连kernel的oops,对应ko里面第一行打印,都没有。

1.后来经过测试,发现,对于pagesize是2K的nand flash来说(此处由于特殊需要(硬件HW ECC占用太多),所以需要进制yaffs2的tag ecc(以节省空间存放HW ECC)),都是可以正常工作的,但是对于4K Pagesize的nand,就工作不正常。而之前已经用mtd test的一系列工具验证了,2K和4K的nand的驱动,都是可以正常工作的。

2.去看了下mtd层关于2K和4K的,有什么不一样的地方,发现对应的include\mtd-abi.h中,struct nand_ecclayout中,eccpos还是64,所以将其改为128,再去测试,问题如故。

3.其他的,找不到原因了,所以,推断是yaffs2与MTD的兼容等方面的问题。

4.后来又经过测试,以/dev/mtdblock4作为参数,用

insmod dwc_otg.ko
insmod gadgetfs.ko
insmod g_file_storage.ko file=/dev/mtdblock4 stall=0 removable=1

去挂载了usb masstorage,去windows中格式化该U盘成fat32,然后去板子上,去

mount /dev/mtdblock4 /mnt/usb_msc -t vfat

挂载成fat分区,然后这样,就可以避开yaffs2,只是和mtd层有关系,结果测试下来,

数据读写,都还是对的,但是还是先mount,后面再执行其他的,涉及到内核数据结果的操作,就还是死掉

即不论是挂载成yaffs2:

mount /dev/mtdblock4 /mnt/usb_msc

还是

mount /dev/mtdblock4 /mnt/usb_msc -t vfat

后面对该分区的数据读写都是OK的,但是就是之后再去

insmod ***.ko 或者其他的loadkmap 等等涉及内核的操作的程序,都会导致内核死掉,而且此处的死掉,

和一般的oops,空指针等还不同,完全没有任何输出。

死掉后,去用rvds连接板子,发现pc始终在0xFFFF000C,对应的就是ARM 的预取指中止异常:

ARM体系结构所支持的异常类型

异常类型 具体含义
复位 复位电平有效时,产生复位异常,程序跳转到复位处理程序处执行。
未定义指令 遇到不能处理的指令时,产生未定义指令异常。
软件中断 执行SWI指令产生,用于用户模式下的程序调用特权操作指令。
指令预取中止 处理器预取指令的地址不存在,或该地址不允许当前指令访问,产生指令预取中止异常。
数据中止 处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时,产生数据中止异常。
IRQ 外部中断请求有效,且CPSR中的I位为0时,产生IRQ异常。
FIQ 快速中断请求引脚有效,且CPSR中的F位为0时,产生FIQ异常。

异常向量表(Exception Vectors)

地址 异常 进入模式

0x0000,0000 复位管理模式

ox0000,0004 未定义指令 未定义模式

0x0000,0008软件中断 管理模式

0x0000,000c 中止(预存指令) 中止模式

0x0000,0010 中止(数据) 中止模式

0x0000,0014 保留 保留

0x0000,0018 IRQ IRQ

0x0000,001c FIQ FIQ

也就是说明,最后出错的预取指中止,就是去本来应该存储对应的指令(代码)的地方,去读取指令,

结果实际取指取出来的是非法的,所以出现此预取指中止异常,死掉了。

5.最后发现,问题出在

include\linux\mtd\nand.h中:

struct nand_buffers {
uint8_t ecccalc[MTD_NAND_MAX_OOBSIZE];
uint8_t ecccode[MTD_NAND_MAX_OOBSIZE];
uint8_t databuf[MTD_NAND_MAX_PAGESIZE + MTD_NAND_MAX_OOBSIZE];
};
databuf的对应的宏:

#define MTD_NAND_MAX_PAGESIZE 2048

#define MTD_NAND_MAX_OOBSIZE 64

因此,在

int nand_scan_tail(struct mtd_info *mtd)
{

...

if (!(chip->options & NAND_OWN_BUFFERS))
chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
...
}

kmalloc去申请的空间,就是2048bytes了,这样,对于2K pagesize的nand,肯定是工作正常的,但是对于4K pagesize的,如果上层,比如yaffs2,通过mtd去读取数据,一个page的数据就是4K了,然后会放到这个buffer里面,结果后面2048的系统数据,就被冲掉了,如果系统之后用到这部分的数据或指令,就会有问题。而此处出现的预取指中止异常,那就是说明,后面这2048字节,里面很可能包含了某些系统相关的指令(和其他数据),结果系统执行到这里,取指不正常,所以挂掉了。

解决办法也很简单,就是把对应的宏,该成足够大,比如:

#define MTD_NAND_MAX_PAGESIZE 8192
#define MTD_NAND_MAX_OOBSIZE 256

这样,以后即使是8K的nand,也可以很好的支持

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top