久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > yaffs2中,mount mtd block設備后,insmod就死掉了

yaffs2中,mount mtd block設備后,insmod就死掉了

作者: 時間:2016-11-20 來源:網絡 收藏
Linux 2.6.22,加了最新的yaffs2,實現了nand flash驅動后,用mtd test測試驅動工作都正常的。

但是,最新發現一個很詭異的問題:

本文引用地址:http://cqxgywz.com/article/201611/318891.htm

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的,有什么不一樣的地方,發現對應的includemtd-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.最后發現,問題出在

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的對應的宏:

#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,也可以很好的支持了。



評論


技術專區

關閉