这三个月主要精力都在智能家居软件的ARM移植上。近期任务基本搞定,喘口气把移植阶段各个小结给发一下。
这段时间查阅了上百篇技术帖子,过程之艰辛不提,听说这个问题有同志烦恼了大半年之久,希望能给同样在飞凌这块板子上进行学习的初学者们一些帮助。
【常见kernel panic错误1】(文件系统结构错误、内部文件缺失或其他错误)
Failed to execute /linuxrc. Attempting defaults...
Kernel panic - not syncing: No init found. Try passing init= option to kernel. .
[<c003bca8>] (unwind_backtrace+0x0/0xfc) from [<c04f4718>] (dump_stack+0x18/0x1c)
[<c04f4718>] (dump_stack+0x18/0x1c) from [<c04f477c>] (panic+0x60/0x1ac)
[<c04f477c>] (panic+0x60/0x1ac) from [<c00355dc>] (init_post+0xc8/0x140)
[<c00355dc>] (init_post+0xc8/0x140) from [<c00084c8>] (kernel_init+0xf4/0x130)
[<c00084c8>] (kernel_init+0xf4/0x130) from [<c0036a34>] (kernel_thread_exit+0x0/)
【常见kernel panic错误2】(内核不支持该文件系统或没有在正确的位置烧写正确的文件系统镜像)
yaffs: passed flags ""
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,3)
[<c0040ca8>] (unwind_backtrace+0x0/0xfc) from [<c0552534>] (dump_stack+0x18/0x1c)
[<c0552534>] (dump_stack+0x18/0x1c) from [<c0552598>] (panic+0x60/0x1ac)
[<c0552598>] (panic+0x60/0x1ac) from [<c0008f88>] (mount_block_root+0x1bc/0x25c)
[<c0008f88>] (mount_block_root+0x1bc/0x25c) from [<c00090b0>] (mount_root+0x88/0xd0)
[<c00090b0>] (mount_root+0x88/0xd0) from [<c0009204>] (prepare_namespace+0x10c/0x1a8)
[<c0009204>] (prepare_namespace+0x10c/0x1a8) from [<c00084c4>] (kernel_init+0xf0/0x130)
[<c00084c4>] (kernel_init+0xf0/0x130) from [<c003ba34>] (kernel_thread_exit+0x0/0x8)
【原因分析】
原因可能有三个:
1、烧写方法步骤错误
2、内核选项勾选错误,导致编译出来的内核不兼容
3、文件系统寻址与运行出现问题
可以看到导致这个问题的原因分为3类起码10种以上!所以如果要解决的话,必须先锁定到底是那一类问题!
刚开始遇到,我当时查找到许多资料,每个人说法都不一样而且单独使用的话都不管用,也是脑袋混乱了几乎整天,第二天早上才确定了锁定问题的思路:
控制变量法。
首先你要找出没有问题的内核和文件系统各一个(比方说,通常在买板子的时候附带的文件系统和内核是没有问题的,虽然上面啥都没有),然后进行烧写。如果这时候出现kernel panic,那么说明你的烧写方法是有问题的,从这个方面开始考虑。
如果没有问题的话,那么将自己编译的内核+没问题的文件系统、没问题的内核+自己制作的文件系统各进行烧写看看情况。就能锁定问题属于哪一类。
其实最后确定下来,我三个部分都有一些问题 (新人,基础不扎实= =#) 所以不能靠一种方法简单解决。
下面罗列下我了解的问题和对应解决方法,蓝字是针对我的问题有效果的做法,欢迎补充:
【对应解决步骤】
1、烧写方法
1) 一键烧写
飞凌的一键烧写必须把流程整个执行完,如果中间中断必须从头开始烧,不然就算烧写的东西是对的,也会出这个错误。
参考 《【配置】SD卡一键烧写》
2)/mnt/disk烧写(飞凌2012.9以后的板子的mmc等不再支持这一功能)
用/mnt/disk(而不是制作镜像并烧写)来烧写文件系统时,不要直接压缩root文件夹。而要将里边的东西全选之后压缩(总之不能直接看到root在里边,而是压缩文件应该打开就是一堆文件)
2、关于内核编译
1)provide old way to pass kernel parameters
http://blog.sina.com.cn/s/blog_69d6931501011b8j.html
在网上搜了很久,各种方法都试过,还是这个问题。
突然想起来参考的移植说明上,在内核的配置中,有一个配置选项我没有选上,或许就是这个问题导致的吧!我试了下,果然就是这个问题。但此时又出现了新的问题。真是一波刚平一波又起啊!
哎!到底该选项怎么影响到linuxrc的执行,还不清楚,先记录下来,以备后来查看!有曾经做过这方面的大牛,或是正在路上的小牛,希望能和小弟一块交流学习。
该选项就是在kernel features下provide old way to pass kernel parameters,有图有真相,呵呵...如下:
2)filesystem
内核要支持你烧写的文件系统,相应的选项也要勾上
这个如果不能保证,内核启动时会出现类似如下错误:VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)Please append a correct "root=" boot option
如果 内核支持文件系统 以及 下边讲的文件系统寻址 这两点能保证,就可以挂接上文件系统,出现类似下面的字样时,革命已经成功了80%:VFS: Mounted root (cramfs filesystem) readonly.Freeing init memory: 116K
3)
在内核中,把网卡加进去就可以了
4)Verify nand page writes
Comment 1 by project member changbin.du@gmail.com, Jun 17, 2012
enable MTD "write verify" option.
Status:Fixed
5)重新配置内核
如果以上都不行,只能这样了——飞凌光盘上有内核代码,这个编译完是可以直接用的。那么,在这个配置的基础上,再勾选后来你需要添加的选项(比方说USB转串口驱动等),进行内核编译。
3、关于文件系统
1)在正确的位置烧写正确的文件系统映象:
引用 http://www.100ask.net/forum/showtopic-15.aspx 2楼 韦东山先生:(a). 正确的位置
(使用飞凌一键烧写就不担心这些,这部分可以跳过) 嵌入式开发中,常通过bootloader烧写文件系统映象,假设写在flash的地址A处。 内核启动时,显然要从地址A处读取文件系统,内核是怎么知道的呢?通过命令行参数,比如“root=/dev/mtdblock2 ”。
/dev/mtdblock2 又是怎么和地址A对应上的呢?内核将flash划分为几个分区,这是在代码中固定的。/dev/mtdblock2是第3个分区,它的开始地址必须是A。 在内核启动时,可以看到这些分区的开始地址、结束地址,比如内核启动时会有类似下面的信息:Creating 3 MTD partitions on "NAND 64MiB 3,3V 8-bit":0x00000000-0x00030000 : "bootloader"0x00050000-0x00250000 : "kernel"0x00250000-0x03ffc000 : "root" 对于上面的内核信息,/dev/mtdblock2对应root分区,开始地址为0x00250000,使用bootloader写文件系统映象时,烧写的地址必须是0x00250000 所以,要保证3点:
① bootloader烧到地址A,
② 地址A是内核某个分区的开始地址,
③ 命令行参数“root=/dev/mtdblockXXX ”是这个分区
(b). 正确格式的文件系统映象 不同的bootloader支持的烧写的文件系统映象格式不同、使用的烧写命令也可能不同,请注意这点。 另外,马大哈们制作文件系统映象时,使用的工具也不要弄错了。 最后,请保证这个文件系统映象是“真的烧写了”,因为如果flash只是擦除而没有烧写,它也是“正确的、可以挂接的文件系统”──有人碰到这个问题,我和他答非所问地折腾了很久。 这个问题如果不能保证,内核启动时会出现类似如下错误:VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)Please append a correct "root=" boot option 如果文件系统寻址以及内核支持文件系统这两点能保证,就可以挂接上文件系统,出现类似下面的字样时,革命已经成功了80%:VFS: Mounted root (cramfs filesystem) readonly.Freeing init memory: 116K
2)文件系统的内容要完备
(如果是在之前验证过可以烧写成功的文件系统基础上进行开发,没有删除文件或修改关键链接,那么这个部分可以跳过)
挂接文件系统后,内核就会读取、执行文件系统中的某个文件,通过它来启动应用程序。这个文件要么通过命令行参数“init=xxxx”来指定,要么取默认的文件(下面说明)。 一般制作文件系统映象时,都是在一个目录(假设目录名为rootfs)下放好各种东西:bin/,sbin/,lib/等目录,etc/fstab等文件,然后将这个目录制作为文件系统映象。 可以想象,如果这个目录中的东西不对、不全,即使制作出了文件系统映象,也只是能识别出来,挂接上去;但是启动不了──所谓启动,不就是执行文件系统中的程序嘛? 这时会有类似以下的错误:Failed to execute /linuxrc. Attempting defaults...Kernel panic - not syncing: No init found. Try passing init= option to kernel. 它说得很明显,"Failed to execute /linuxrc"──执行/linuxrc失败:它为什么要执行/linuxrc,还不是因为你在命令行中加入了“init=/linuxrc”这个参数。 它为什么会失败?原因有二:一、你制作文件系统映象时,rootfs目录下有linuxrc这个文件吗?二、rootfs目录的linuxrc文件是正确的吗? 请好好确定这两点,大多数是没有linuxrc文件──linuxrc是busybox自动生成的,只要配置好就可以。 如果有linuxrc,那么就是它无法执行了(解决方法在下面)。 不用linuxrc行不行?当然行!看看内核文件init/main.c,有如下字样:run_init_process("/sbin/init");run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");panic("No init found. Try passing init= option to kernel."); 就是说,它会依次尝试执行/sbin/init、/etc/init、/bin/init、/bin/sh这些文件,都失败后才打印出错信息"No init found. Try passing init= option to kernel."。 所以,出现这个出错信息时,就表明了没有或是无法执行这些文件:命令行参数“init=xxxx”来指定的xxx文件、/sbin/init、/etc/init、/bin/init、/bin/sh。一、请检查你的rootfs目录,看看这点些文件是否存在二、使用file命令看看它们是什么文件类型,是否可执行。使用busybox时,这些文件是到/bin/busybox文件的链接,那就看看busybox的文件类型,可以使用下面的命令:$ file linuxrclinuxrc: symbolic link to `bin/busybox'$ file bin/busyboxbin/busybox: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.4.3, dynamically linked (uses shared libs), stripped
2)换一个文件系统制作工具。
比方说飞凌的mkyaffs2image-nand2g和mkyaffs2image-nand256m可能不太能用(待仔细测试)。改用以前mkcramfs则是可以的。但这会生成cramfs文件,所以得要用回 旧的mmc (2012.9之前买的飞凌ok6410光盘附带那个)才能进行一键烧写。
参考http://blog.csdn.net/ayangke/article/details/6280400
我刚开始以为我的linuxrc没有执行权限,一查看,是有的。
上网一搜,发现好多兄弟都遇到类似的问题,那些回答问题的都说是linuxrc没有加执行权限啊,busybox没有选中shell选项啊,我一看,全是乱说,busybox默认就是选中shell的,除非你手动把他取消掉了,还有生成linuxrc默认就是有可执行权限的。
我把原厂的根文件系统源码拿来编译一次,下载进去还是同样的错误,于是我就朝着mkyaffs2image这个yaffs2文件系统镜像制作工具上去,一搜发现,原来我用的是这个工具不支持128M的nand,有一个哥们对其进行了修改,并使之支持了128M
3)NFS文件系统连接中产生的问题
·无法挂载问题一:
dm9000 dm9000.0: eth0: link up, 100Mbps, full-duplex, lpa 0x41E1
VFS: Mounted root (nfs filesystem) on device 0:14.
devtmpfs: error mounting -2
Freeing init memory: 172K
Failed to execute /linuxrc. Attempting defaults...
Kernel panic - not syncing: No init found. Try passing init= option to kernel.
See Linux Documentation/init.txt for guidance.
[<c0039ca8>] (unwind_backtrace+0x0/0xfc) from [<c049fd9c>] (dump_stack+0x18/0x1c)
[<c049fd9c>] (dump_stack+0x18/0x1c) from [<c049fe00>] (panic+0x60/0x1ac)
[<c049fe00>] (panic+0x60/0x1ac) from [<c00335dc>] (init_post+0xc8/0x140)
[<c00335dc>] (init_post+0xc8/0x140) from [<c00084c8>] (kernel_init+0xf4/0x130)
[<c00084c8>] (kernel_init+0xf4/0x130) from [<c0034a34>] (kernel_thread_exit+0x0/0x8)
解决:
1)没有在指定目录下给个文件系统,应将用户基础资料光盘中“linux2.6.28/filesystem/OK6410_yaffs2_v1.0.tgz”压缩文件拷贝到这个目录下并解压
2)ARM启动参数bootargs设置错误,printenv应该有
bootargs =root=dev/nfs nfsroot=192.168.0.10:/forlinx/root rw noinitrd init=/linuxrc ip=192.168.0.232:192.168.0.10:192.168.0.255:255.255.255.0 console=ttySAC0,115200
·无法挂载问题二:
本来已经连上NFS了,本机(win7)开了网络查询东西,之后板子重新启动时出错
dm9000 dm9000.0: eth0: link down
dm9000 dm9000.0: eth0: link up, 100Mbps, full-duplex, lpa 0x41E1
VFS: Unable to mount root fs via NFS, trying floppy.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
[<c0039ca8>] (unwind_backtrace+0x0/0xfc) from [<c049fd9c>] (dump_stack+0x18/0x1c)
[<c049fd9c>] (dump_stack+0x18/0x1c) from [<c049fe00>] (panic+0x60/0x1ac)
[<c049fe00>] (panic+0x60/0x1ac) from [<c0008fd0>] (mount_block_root+0x204/0x25c)
[<c0008fd0>] (mount_block_root+0x204/0x25c) from [<c00090b0>] (mount_root+0x88/0xd0)
[<c00090b0>] (mount_root+0x88/0xd0) from [<c0009204>] (prepare_namespace+0x10c/0x1a8)
[<c0009204>] (prepare_namespace+0x10c/0x1a8) from [<c00084c4>] (kernel_init+0xf0/0x130)
[<c00084c4>] (kernel_init+0xf0/0x130) from [<c0034a34>] (kernel_thread_exit+0x0/0x8)
解决:断开当前本机网络,重试
*********
以上的思路应该能解决相当一部分kernel panic的问题了。