新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > yaffs2中,mount mtd block設(shè)備后,insmod就死掉了

yaffs2中,mount mtd block設(shè)備后,insmod就死掉了

作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò) 收藏
Linux 2.6.22,加了最新的yaffs2,實(shí)現(xiàn)了nand flash驅(qū)動(dòng)后,用mtd test測(cè)試驅(qū)動(dòng)工作都正常的。

但是,最新發(fā)現(xiàn)一個(gè)很詭異的問(wèn)題:

本文引用地址:http://butianyuan.cn/article/201611/318891.htm

mount /dev/mtdblock4 /mnt/usb_msc 后,自動(dòng)掛載成yaff2文件系統(tǒng)之后,再去insmod任何一個(gè)ko,都會(huì)死掉,而且還是沒(méi)有任何輸出信息的,連kernel的oops,對(duì)應(yīng)ko里面第一行打印,都沒(méi)有。

【解決過(guò)程】

1.后來(lái)經(jīng)過(guò)測(cè)試,發(fā)現(xiàn),對(duì)于pagesize是2K的nand flash來(lái)說(shuō)(此處由于特殊需要(硬件HW ECC占用太多),所以需要進(jìn)制yaffs2的tag ecc(以節(jié)省空間存放HW ECC)),都是可以正常工作的,但是對(duì)于4K Pagesize的nand,就工作不正常。而之前已經(jīng)用mtd test的一系列工具驗(yàn)證了,2K和4K的nand的驅(qū)動(dòng),都是可以正常工作的。

2.去看了下mtd層關(guān)于2K和4K的,有什么不一樣的地方,發(fā)現(xiàn)對(duì)應(yīng)的includemtd-abi.h中,struct nand_ecclayout中,eccpos還是64,所以將其改為128,再去測(cè)試,問(wèn)題如故。

3.其他的,找不到原因了,所以,推斷是yaffs2與MTD的兼容等方面的問(wèn)題。

4.后來(lái)又經(jīng)過(guò)測(cè)試,以/dev/mtdblock4作為參數(shù),用

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

去掛載了usb masstorage,去windows中格式化該U盤(pán)成fat32,然后去板子上,去

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

掛載成fat分區(qū),然后這樣,就可以避開(kāi)yaffs2,只是和mtd層有關(guān)系,結(jié)果測(cè)試下來(lái),

數(shù)據(jù)讀寫(xiě),都還是對(duì)的,但是還是先mount,后面再執(zhí)行其他的,涉及到內(nèi)核數(shù)據(jù)結(jié)果的操作,就還是死掉

即不論是掛載成yaffs2:

mount /dev/mtdblock4 /mnt/usb_msc

還是

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

后面對(duì)該分區(qū)的數(shù)據(jù)讀寫(xiě)都是OK的,但是就是之后再去

insmod ***.ko 或者其他的loadkmap 等等涉及內(nèi)核的操作的程序,都會(huì)導(dǎo)致內(nèi)核死掉,而且此處的死掉,

和一般的oops,空指針等還不同,完全沒(méi)有任何輸出。

死掉后,去用rvds連接板子,發(fā)現(xiàn)pc始終在0xFFFF000C,對(duì)應(yīng)的就是ARM 的預(yù)取指中止異常:

ARM體系結(jié)構(gòu)所支持的異常類型

異常類型 具體含義
復(fù)位 復(fù)位電平有效時(shí),產(chǎn)生復(fù)位異常,程序跳轉(zhuǎn)到復(fù)位處理程序處執(zhí)行。
未定義指令 遇到不能處理的指令時(shí),產(chǎn)生未定義指令異常。
軟件中斷 執(zhí)行SWI指令產(chǎn)生,用于用戶模式下的程序調(diào)用特權(quán)操作指令。
指令預(yù)取中止 處理器預(yù)取指令的地址不存在,或該地址不允許當(dāng)前指令訪問(wèn),產(chǎn)生指令預(yù)取中止異常。
數(shù)據(jù)中止 處理器數(shù)據(jù)訪問(wèn)指令的地址不存在,或該地址不允許當(dāng)前指令訪問(wèn)時(shí),產(chǎn)生數(shù)據(jù)中止異常。
IRQ 外部中斷請(qǐng)求有效,且CPSR中的I位為0時(shí),產(chǎn)生IRQ異常。
FIQ 快速中斷請(qǐng)求引腳有效,且CPSR中的F位為0時(shí),產(chǎn)生FIQ異常。

異常向量表(Exception Vectors)

地址 異常 進(jìn)入模式

0x0000,0000 復(fù)位管理模式

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

0x0000,0008軟件中斷 管理模式

0x0000,000c 中止(預(yù)存指令) 中止模式

0x0000,0010 中止(數(shù)據(jù)) 中止模式

0x0000,0014 保留 保留

0x0000,0018 IRQ IRQ

0x0000,001c FIQ FIQ

也就是說(shuō)明,最后出錯(cuò)的預(yù)取指中止,就是去本來(lái)應(yīng)該存儲(chǔ)對(duì)應(yīng)的指令(代碼)的地方,去讀取指令,

結(jié)果實(shí)際取指取出來(lái)的是非法的,所以出現(xiàn)此預(yù)取指中止異常,死掉了。

5.最后發(fā)現(xiàn),問(wèn)題出在

includelinuxmtdnand.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的對(duì)應(yīng)的宏:

#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去申請(qǐng)的空間,就是2048bytes了,這樣,對(duì)于2K pagesize的nand,肯定是工作正常的,但是對(duì)于4K pagesize的,如果上層,比如yaffs2,通過(guò)mtd去讀取數(shù)據(jù),一個(gè)page的數(shù)據(jù)就是4K了,然后會(huì)放到這個(gè)buffer里面,結(jié)果后面2048的系統(tǒng)數(shù)據(jù),就被沖掉了,如果系統(tǒng)之后用到這部分的數(shù)據(jù)或指令,就會(huì)有問(wèn)題。而此處出現(xiàn)的預(yù)取指中止異常,那就是說(shuō)明,后面這2048字節(jié),里面很可能包含了某些系統(tǒng)相關(guān)的指令(和其他數(shù)據(jù)),結(jié)果系統(tǒng)執(zhí)行到這里,取指不正常,所以掛掉了。

【解決辦法】

解決辦法也很簡(jiǎn)單,就是把對(duì)應(yīng)的宏,該成足夠大,比如:

#define MTD_NAND_MAX_PAGESIZE 8192
#define MTD_NAND_MAX_OOBSIZE 256

這樣,以后即使是8K的nand,也可以很好的支持了。



關(guān)鍵詞: yaffs2mountmtdblockinsmo

評(píng)論


技術(shù)專區(qū)

關(guān)閉