嵌入式linux开发中如果没有在挂载根文件系统时碰到“Kernel panic - not syncing”的问题,我想他肯定还没有开始动手入门。
这个问题可能由两种原因造成的,一个是ABI接口,一个是ECC。
关于ABI(application binary interface)接口的原因跟gcc编译器版本和kernel的配置选项都有关。这篇博文《ABI/EABI/OABI详解及ARM-linux 浮点运算解析与配置》(http://www.cnblogs.com/andrew-wang/archive/2012/12/15/2819819.html)详解了ABI接口的知识,给出了一些重要文档的链接,这在嵌入式底层OS开发中非常重要。一般来说需要选用版本较高的Gcc编译器(比如4.3 、4.4 、4.5各版本),在内核编译时选择“EABI优先&OSBI兼容”,这样在ABI接口方面一般问题不大。
即在配置内核时,在KernelFeatures下选上两项内容,即
Kernel Features --->
[*]Use the ARM EABI to compile the kernel
[*]Allow old ABI binaries to run with this kernel (EXPERIMENTAL)
关于ECC(Error Correcting Code 错误检查和纠正)方面的一些问题,这主要是内核的ecc机制与文件系统ecc机制的不兼容导致的,一般来说嵌入式领域常用在nand存储器上的yaffs等文件系统的驱动,其本身就有ecc方法,则往往内核不需要开启ecc。推荐看一下这篇博文 http://blog.csdn.net/hongjiujing/article/details/1820601,这里稍作引用:
“
1、"mount_devfs_fs(): unable to mount devfs, err: -2"一个困扰了我很久的问题,主要是ecc的问题。在此我把我的理解说一下好了:
搞清楚你在driver/mtd/nand/s3c2410.c文件中有没有把NAND_ECC_SOFT改成NAND_ECC_NONE,这个网上不少的人都会做(听说会与yaffs文件系统有冲突,但我发现反而和cramfs文件系统有冲突)。
假设你把NAND_ECC_SOFT改成NAND_ECC_NONE,那[*] Lets Yaffs do its own ECC 这一步是必需的。
如果你把NAND_ECC_SOFT改成NAND_ECC_NONE的话,那你下载yaffs文件系统的时候就不应该加上-e的参数了。
最后给点建议:先让内核挂载cramfs试试看(记得把NAND_ECC_SOFT改成NAND_ECC_NONE哦),因为这个文件系统只要用下载内核的命令下载就行。
2 确保devfs修改正确.由于linux 2.6.12后取消了devfs,因此你自己在fs/kconfig里面添加devfs的支持。
”
注意用uboot烧写yaffs到nand上的命令是“ nand write.yaffs xxxxx ”,而像cramfs这样的只读的简单系统只需要普通的“ nand write ”方法就行了,内核也一样。这是因为yaffs文件系统利用的nand中的oob校验区,因为nand相比nor虽然价廉物美,但却可能发生位反转。
http://blog.csdn.net/lanmanck/article/details/4355412 这篇博文也从yaffs源代码层面讲解了一些ecc机制。
=======================================================================
另外一个在底层调试中,内核启动常遇到的问题是驱动加载崩溃出可爱的Oops信息,比如故意修改错误一下网卡驱动,内核启动时Oops如下:
“... ...
Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)
Unable to handle kernel paging request at virtual address e000030a
pgd = c0004000
[e000030a] *pgd=00000000
Internal error: Oops: 805 [#1]
Modules linked in:
CPU: 0
PC is at cs8900_probe+0x11c/0x344
LR is at 0xe0000300
pc : [<c00183f0>] lr : [<e0000300>] Not tainted
sp : c02f1f44 ip : c3cf6bf4 fp : c02f1f64
r10: 00000000 r9 : 00000000 r8 : 00000000
r7 : 00000000 r6 : 00000002 r5 : c01f3a84 r4 : 00000000
r3 : e000030a r2 : 00000000 r1 : c3d09600 r0 : e000030a
Flags: NzCv IRQs on FIQs on Mode SVC_32 Segment kernel
Control: 717F Table: 30004000 DAC: 00000017
Process swapper (pid: 1, stack limit = 0xc02f0198)
Stack: (0xc02f1f44 to 0xc02f2000)
1f40: c0152b48 00000000 c01f3a84 c02f0000 00000000 c02f1f80 c02f1f68
1f60: c0152c58 c00182e4 00000000 c01f3a84 c02f0000 c02f1f98 c02f1f84 c0152f7c
1f80: c0152bd8 c01f3a84 c001c394 c02f1fac c02f1f9c c00182c8 c0152f24 c001c8c4
1fa0: c02f1ff4 c02f1fb0 c001f0b4 c00182b4 00000000 00000000 c001f02c c00381ec
1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
1fe0: 00000000 00000000 00000000 c02f1ff8 c00381ec c001f03c 64342520 6c616320
Backtrace:
[<c00182d4>] (cs8900_probe+0x0/0x344) from [<c0152c58>] (register_netdevice+0x9) r7 = 00000000 r6
= C02F0000 r5 = C01F3A84 r4 = 00000000
[<c0152bc8>] (register_netdevice+0x0/0x34c) from [<c0152f7c>] (register_netdev+) r6 = C02F0000 r5
= C01F3A84 r4 = 00000000
[<c0152f14>] (register_netdev+0x0/0x7c) from [<c00182c8>] (cs8900_init+0x24/0x3) r5 = C001C394 r4
= C01F3A84
[<c00182a4>] (cs8900_init+0x0/0x30) from [<c001f0b4>] (init+0x88/0x260)
r4 = C001C8C4
[<c001f02c>] (init+0x0/0x260) from [<c00381ec>] (do_exit+0x0/0x724)
r7 = 00000000 r6 = 00000000 r5 = 00000000 r4 = 00000000
Code: e28e000a e3500201 e1a03000 328334f2 (e1c340b0)
<0>Kernel panic - not syncing: Attempted to kill init!”
虽然最后也是打印Kernel panic - not syncing信息,但是这种情况很明显是内核驱动错误,与上面讲的挂载文件系统接口错误是不同的。