尝试运行
首先也是一样的,去配置编译后尝试运行。修改Makefile,添加ARCH和CROSS_COMPILE的值,然后在arch/arm/configs/目录下选择一款与我们开发板最相近的一个配置,这里我们选择“smdkv210_android_defconfig”。make smdkv210_android_defconfig后也没有必要menuconfig,直接make。生成的zImage烧录运行后发现运行到解压代码后程序就挂了。
解决链接地址与解压地址问题
这种情况下,首先怀疑链接地址和解压地址有问题。
1、链接地址在哪里?
链接地址是一个虚拟地址,但是我们现在要找到是一个物理地址,因为解压地址也必定是一个物理地址(解压是还没有操作系统,还有没开启MMU)。这个运行时的物理地址在head.S中可以查到是0x20008000,解压地址可以在mach/Makefile.boot中查到,也是0x20008000。
按理说这两个地址是一致的,但是要注意的是,我们的uboot在初始化DDR的时候,将bank1的首地址配到了3开头的地址,因此这两个地方均需要改成0x30008000才行。
解决Oops错误
启动内核后出现了如下问题,内核遭遇了野指针。
看PC和LR的地址来看,内核应该是在加载max8698的驱动(probe函数),这是一款PMIC芯片。
因为三星的SMDKV210开发板中是用了max8698这个电源管理IC的,所以三星的uboot和kernel中都有默认支持这个。但是我们的开发板X210中是没用的,因此都需要去掉。
在uboot中是直接改源代码屏蔽掉那个初始化函数解决的。但是在内核中不能这么干,因为内核是通过probe来初始化驱动的,无法直接屏蔽,而且也不一定能屏蔽干净,况且kernel是高度模块化高度可配置的,只要去掉这个模块的支持,不需要改代码。因此在menuconfig中搜索,并选择去除即可。
有2个跟max8698相关的,但是下面那个REGULATOR_MAX8698可以看到依赖于 MFD_MAX8698,因此关掉 MFD_MAX8698即可。这样同时就去掉.config中该模块相关的宏定义了,也就去掉了这个模块的支持了。
挂载根文件系统VFS相关问题
启动后发现VFS挂载失败了(通过Backtrace中的函数符号),因为我使用的是网络文件系统(root=/dev/nfs),而且往上翻可以看到有DM9000的报错,因此先修复DM9000的驱动。
驱动的修改分两个部分:
分别是smdkc110_machine_init中对DM9000需要用到的内部外设进行初始化;
以及smdkc110_devices中platform_device s5p_device_dm9000中的resource;
按照之前uboot中的DM9000初始化参数修改即可。最终的效果是,DM9000的报错(dm9000 dm9000.0: not found (-19).)消除了,但是VFS的报错(VFS: Cannot open root device “nfs” or unknown-block(0,255))依然还在。
因此,我尝试将root=改成iNand的(set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3),依然还是VFS的问题,报错(VFS: Cannot open root device “mmcblk0p2” or unknown-block(0,0))。
对照正确的内核启动信息发现,内核启动并没有找到MMC设备(内置的iNand和外置的SD卡都没找到),没找到肯定是驱动的问题,这就要去移植MMC驱动了。
至此先告一段落,后期移植了驱动再来解决这里的问题。
总结
1、内核在C语言阶段(大量打印刷出来了)时的出错,一般都是驱动出错了。就像上面三个问题(PMIC驱动、网卡驱动、MMC驱动),因此一般都要去移植驱动了。移植驱动有的很简单,比如在配置中增加或去除某个驱动的支持;有的需要修改驱动配置时的数据即可;而有的可能需要全局移植驱动代码了。
2、内核启动第一阶段就挂掉了的话,是没有过多的打印的,可能连解压代码的打印都没有。一种调试方法就是在内核启动的第一阶段,添加汇编操作led点亮/熄灭的方法来标明代码运行的轨迹(注意操作led的寄存器不要使用r0、r1、r2,以及stext中已经使用的r9、r10、r5、r8)。
led_off:
ldr r3, =0x11111111
ldr r4, =0xE0200240
str r3, [r1]
ldr r3, =0xff
ldr r4, =0xE0200244
str r3, [r1]
mov pc, lr