歡迎轉載,轉載時請保留作者信息,謝謝。
博客園地址:http://www.cnblogs.com/embedded-tzp
Csdn博客地址:http://blog.csdn.net/xiayulewa
在內核下載運行后,會出現各種各樣的問題,將遇到的問題和解決方案貼出來。
No filesystem could mount root, tried: ext3 cramfs vfat msdos romfs(沒有文件系統)
問題分析:
在make menuconfig時,沒有配置文件系統類型。
解決方案:
: make menuconfig: 將M改為yes, 見下圖
Failed to execute /linuxrc. Attempting defaults...
問題分析:
程序不可執行或者沒有權限執行,修改根文件系統里的linuxrc的組改為root。
解決方案:
# chown -R root:root '/home/tang/work/fs/ramdisk_fs', 或者制作文件系統時就以root身份來做
ls輸出亂碼
問題分析:
ls是 busybox的命令,其輸出加了一些格式輸出。
解決方案:.
兩種方式,或者重新配置busybox並編譯,或者 改為用secureCRT 工具
見http://blog.chinaunix.net/uid-26404477-id-3459315.html
irq 57: nobody cared (try booting with the "irqpoll" option)
問題描述:
當開發板執行ifconfig eth0 192.168.1.3時,出錯,現象如下:
irq 57: nobody cared (try booting with the "irqpoll" option) (__report_bad_irq: Spurious.c (src\kernel\irq))
CPU: 0 PID: 770 Comm: ifconfig Not tainted 3.10.53 #28
[<c000d8ec>] (unwind_backtrace+0x0/0xf4) from [<c000bea4>] (show_stack+0x10/0x14)
[<c000bea4>] (show_stack+0x10/0x14) from [<c005305c>] (__report_bad_irq+0x20/0xb4)
[<c005305c>] (__report_bad_irq+0x20/0xb4) from [<c0053314>] (note_interrupt+0x224/0x288)
[<c0053314>] (note_interrupt+0x224/0x288) from [<c00514d8>] (handle_irq_event_percpu+0xa8/0x1c0)
[<c00514d8>] (handle_irq_event_percpu+0xa8/0x1c0) from [<c0051618>] (handle_irq_event+0x28/0x38)
[<c0051618>] (handle_irq_event+0x28/0x38) from [<c0053aec>] (handle_edge_irq+0x7c/0x130)
[<c0053aec>] (handle_edge_irq+0x7c/0x130) from [<c005107c>] (generic_handle_irq+0x34/0x40)
[<c005107c>] (generic_handle_irq+0x34/0x40) from [<c019b528>] (s3c_irq_demux+0xb4/0x120)
[<c019b528>] (s3c_irq_demux+0xb4/0x120) from [<c005107c>] (generic_handle_irq+0x34/0x40)
[<c005107c>] (generic_handle_irq+0x34/0x40) from [<c00099fc>] (handle_IRQ+0x30/0x84)
[<c00099fc>] (handle_IRQ+0x30/0x84) from [<c000855c>] (s3c24xx_handle_irq+0x90/0x140)
[<c000855c>] (s3c24xx_handle_irq+0x90/0x140) from [<c0008e74>] (__irq_svc+0x34/0x40)
Exception stack(0xc2f67ce8 to 0xc2f67d30)
7ce0: 00000001 0000000a 00000000 20000013 00000002 00000002
7d00: c04e4160 c2f66000 c04a4f5c c04e4140 c201d90c c04e4160 00400100 c2f67d30
7d20: c001cf4c c001cfc0 20000013 ffffffff
[<c0008e74>] (__irq_svc+0x34/0x40) from [<c001cfc0>] (__do_softirq+0x84/0x1cc)
[<c001cfc0>] (__do_softirq+0x84/0x1cc) from [<c001d1b8>] (do_softirq+0x4c/0x58)
[<c001d1b8>] (do_softirq+0x4c/0x58) from [<c001d218>] (irq_exit+0x54/0x90)
[<c001d218>] (irq_exit+0x54/0x90) from [<c0009a00>] (handle_IRQ+0x34/0x84)
[<c0009a00>] (handle_IRQ+0x34/0x84) from [<c000855c>] (s3c24xx_handle_irq+0x90/0x140)
[<c000855c>] (s3c24xx_handle_irq+0x90/0x140) from [<c0008e74>] (__irq_svc+0x34/0x40)
Exception stack(0xc2f67da0 to 0xc2f67de8)
7da0: 00000000 00000039 c04aeab8 00000000 c04a7194 c2054d40 00000039 60000013
7dc0: c04a71c4 00000000 c201d90c c2046cc0 235e5c8f c2f67de8 c0053ff8 c00523dc
7de0: 40000013 ffffffff
[<c0008e74>] (__irq_svc+0x34/0x40) from [<c00523dc>] (__setup_irq+0x194/0x428)
[<c00523dc>] (__setup_irq+0x194/0x428) from [<c00528a8>] (request_threaded_irq+0xd8/0x158)
[<c00528a8>] (request_threaded_irq+0xd8/0x158) from [<c02168c0>] (net_open+0x88/0x488)
[<c02168c0>] (net_open+0x88/0x488) from [<c02bfa4c>] (__dev_open+0xb8/0x114)
[<c02bfa4c>] (__dev_open+0xb8/0x114) from [<c02bc8e4>] (__dev_change_flags+0x8c/0x134)
[<c02bc8e4>] (__dev_change_flags+0x8c/0x134) from [<c02bf95c>] (dev_change_flags+0x10/0x48)
[<c02bf95c>] (dev_change_flags+0x10/0x48) from [<c0310cfc>] (devinet_ioctl+0x674/0x784)
[<c0310cfc>] (devinet_ioctl+0x674/0x784) from [<c02abfdc>] (sock_ioctl+0x74/0x2a4)
[<c02abfdc>] (sock_ioctl+0x74/0x2a4) from [<c009fab4>] (do_vfs_ioctl+0x80/0x5f4)
[<c009fab4>] (do_vfs_ioctl+0x80/0x5f4) from [<c00a0064>] (SyS_ioctl+0x3c/0x60)
[<c00a0064>] (SyS_ioctl+0x3c/0x60) from [<c00091c0>] (ret_fast_syscall+0x0/0x2c)
handlers:
[<c0216cc0>] net_interrupt
Disabling IRQ #57 (Spurious.c (src\kernel\irq), 出現這個情況是中斷次數99000過多,沒有被處理)
cs89x0: eth0: using half-duplex 10Base-T (RJ-45)
cs89x0: net_open() succeeded
問題分析:
這與網絡驅動有關,我的是cs8900a網卡,代碼是內核自帶的,就以此說明。
網卡驅動相關文件為 cs89x0.c,cs89x0.h, cs89x0.txt。
從棧最底處的net_interrupt, 可以看出內核在[<c0216cc0>] net_interrupt 處崩潰。而在net_open() 中有ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev); 可見net_interrupt為網卡中斷處理函數。
從上述的打印棧可以看出問題出現時的函數調用順序,該調用順序就是中斷的處理流程,可以看我的另一篇文章,那里有中斷非常詳細的說明。
s3c24xx_handle_irq→handle_IRQ→generic_handle_irq→s3c_irq_demux→ generic_handle_irq→
handle_edge_irq→handle_irq_event→handle_irq_event_percpu→note_interrupt→__report_bad_irq→show_stack→unwind_backtrace;
而在note_interrupt函數中有:
if (unlikely(desc->irqs_unhandled > 99900)) {
/*
* The interrupt is stuck
*/
__report_bad_irq(irq, desc, action_ret);
…….
}
desc是中斷數組某個元素,其irqs_unhandled > 99900了,就是說有99900個中斷沒有處理了?
在note_interrupt→if (unlikely(action_ret == IRQ_NONE)) {…… desc->irqs_unhandled++; …….} 說明網卡中斷返回值為IRQ_NONE,才會irqs_unhandled++。網卡中斷返回值由handle_irq_event_percpu→res = action->handler(irq, action->dev_id)即net_interrupt得到,看該函數,可知while ((status = ioread16(lp->virt_addr + ISQ_PORT))) 循環必然條件為假,不然返回值不會是IRQ_NONE。
分析到這里基本明白了,cs8900a的中斷是硬件與s3c2440連接的,cs8900a只有實在產生了中斷,才會導致cpu進入中斷函數,但是網卡實際上是不可能產生那么頻繁的中斷的,那么猜想可能是中斷觸發類型設置不正確。
配上原理圖:
看s3c2440手冊:
EXTINT1寄存器的[6:4]控制了lan口中斷觸發類型。
在內核中添加代碼,打印EXTINT1寄存器的值,發現其被配置為低電平觸發中斷了,而在cs8900a的datasheet中,明確說了高電平表明是一個中斷。
到這里問題原因定位。
解決方案:
. 在MACH_START中mini2440_map_io修改,添加中斷支持
s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
//此處添加外部中斷控制EINT9, 高電平觸發,是cs8900中斷
unsigned long tmp = ioread32(S3C24XX_VA_GPIO + 0x8c); // EXTINT1寄存器
tmp &= ~0xf0;
tmp |= 0x90;
iowrite32(tmp , S3C24XX_VA_GPIO + 0x8c); // 設置為高電平觸發中斷
然后ifconfig, ping等命令在應用層都正常執行了。
感想:
驅動移植時,本身最后改的代碼就幾句話,但是卻要了解linux整個實現體系,包括設備總線驅動模型,platform driver,因為cs89x0驅動就是用這種架構,包括完整的中斷處理流程,包括s3c2440芯片本身,cs8900a芯片本身資料,cs8900a驅動源代碼,linux虛擬地址和物理地址映射等背景知識,真是折騰傷神啊,還好帶來點成就感,開發從此后就可以使用nfs文件系統了,方便了很多,也值得了。
-
EEPROM is configured for unavailable media
問題描述:
執行ifconfig eth0 up時,出錯。
EEPROM is configured for unavailable media
問題分析:
在cs89x0.c中,查找,發現出在net_open函數中,發現是lp->adapter_cnf沒有合適的賦值。
如cs89x0.txt描述, 在網卡驅動作為模塊加載時,在模塊加載時,可以傳遞參數,insmod cs89x0.o io=0x200 irq=0xA media=aui,以此確定媒介,會對lp->adapter_cnf賦值。
但是當make menuconfig,配置成CONFIG_CS89x0_PLATFORM=y時,網卡驅動作為非模塊開機自動加載, 不會自動對lp->adapter_cnf賦值。
解決方案:.
如<<cs89x0.txt>> 6.5 Kernel module parameters描述,可采用u-boot向kernel傳遞命令的方式,如cs89x0_media=rj45等為lp->adapter_cnf賦值。
另外就是直接修改源代碼:當然這種方式不通用。
在net_open中
修改
/* check to make sure that they have the "right" hardware available */
switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
為 lp->adapter_cnf = A_CNF_MEDIA_TYPE | A_CNF_10B_T;
/* check to make sure that they have the "right" hardware available */
switch (lp->adapter_cnf & A_CNF_MEDIA_TYPE) {