1、尝试编译分析结果

配置编译下载尝试

(1)检查Makefile中ARCH和CROSS_COMPILE
(2)make xx_defconfig
(3)make menuconfig
(4)make -j4、

显示结构:Starting kernel ...后没有任何反应(...为uboot输出的最后信息)

结果分析:

(1)根据运行结果,分析发现:linux内核的自解压代码都没有运行(因为没有看到:Uncompressing Linux... done, booting the kernel.)
(2)说明zImage根本没有被解压成功,内核代码根本就没有被运行,当然没有输出信息了。所以问题出在解压相关的部分。
(3)问题出在内核配置的解压后代码放置的内存地址处。
(4)内核配置的解压地址应该等于连接地址,否则自解压之后内核无法运行。现在问题变成:第一,内核的连接地址等于多少?第二,内核中配置的解压地址是多少?
(5)这里面还有个问题:内核的连接地址是一个虚拟地址,而自解压代码解压内核时需要物理地址,因此上面说的等于,其实是连接地址对应的物理地址等于自解压地址。
(6)连接地址和他对应的物理地址在head.S中可以查到,分别是0xC0008000和0x30008000。那么自解压代码配置的解压地址应该是30008000.
(7)自解压代码对应的自解压地址在mach/Makefile.boot文件中。在其中修改,加入两行:
# override for SMDKV210
zreladdr-$(CONFIG_MACH_SMDKV210) := 0x30008000
params_phys-$(CONFIG_MACH_SMDKV210) := 0x30000100
(8)同步代码,并且编译,得到的zImage复制到/tftpboot,然后重新下载运行查看结果。
(9)结果就是:还是没运行,但是有效果。自解压代码解压打印信息已经出来了。但是内核还没运行

问题分析

定义的物理地址不对,从20000000改到30000000即可

2、分析错误提示启动内核

认识内核启动OOPS

(1)内核启动后会有打印信息,打印信息中隐藏了问题所在。认真的去分析这个打印信息,从中找到对的或者错误的一些信息片段,才能帮助我们找到问题,从而解决问题。
(2)内核启动中的错误信息有一些特征:
Unable to handle kernel NULL pointer dereference at virtual address 00000060
Internal error: Oops: 5 [#1] PREEMPT
PC is at dev_driver_string+0xc/0x44
LR is at max8698_pmic_probe+0x150/0x32c
(3)从以上错误信息中的PC和LR的值可以看出,程序是执行到dev_driver_string或者max8698_pmic_probe(这两个是函数或者汇编中的标号)符号部分的时候出错了。我们就从这两个符号出发去寻找、思考可能出错的地方然后试图去解决。

错误追溯及问题解决

(1)max8698_pmic_probe看名字是max8698这个电源管理IC的驱动安装函数部分出错了,应该是我们的开发板系统中配置了支持这个电源管理IC,于是乎启动时去加载他的驱动,结果驱动在加载执行的过程中出错了OOPS了。
(2)我们为什么要配置支持这个驱动?这个驱动加载为什么要出错?
(3)结合我们X210开发板的硬件实际情况来分析:我们X210开发板上根本就没有max8698这个电源管理IC,既然硬件都没有驱动执行了肯定会出错。
(4)回忆当时从三星版本的uboot移植的时候,在uboot的lowlevel_init.S中也有调用个电源管理IC初始化函数(PMIC_init),后来解决的办法就是屏蔽掉了这个函数的调用,uboot就成功运行下去了。
(5)为什么我们的uboot和内核中默认都调用了这个电源管理IC的初始化代码?原因就是三星的SMDKV210开发板中是用了max8698这个电源管理IC的,所以三星的uboot和kernel中都有默认支持这个。但是X210中是没用的,因此都需要去掉。
(6)怎么解决?在uboot中是直接改源代码屏蔽掉那个初始化函数解决的;在内核中不能这么干?因为linux kernel是高度模块化高度可配置的,内核中每一个模块都是被配置项条件编译了的,因此要去掉某个模块的支持,只需要重新配置去掉选项即可,不用改源代码。所以我们的关键就是要找它对应的配置项。
(7)我们做法:make menuconfig,然后/搜索"MAX8698"这几个关键字,然后看到这个配置项的路径,然后到路径下去按N键去掉这个模块的支持,保存,重新编译即可。
(8)实践证明问题被解决了,而且内核再次启动后直接运行到挂载rootfs才出错。

分析及总结

(1)分析:问题究竟是怎么被解决的?涉及哪几个方面
根本原因在于CONFIG_MFD_MAX8698这个配置宏。这个配置宏决定了很多东西
第一:这个配置宏决定了drivers目录下的max8698对应的驱动程序源代码是否被编译
第二:这个配置宏决定了kernel启动过程中是否会调用一些max8698的相关的代码

(2)总结:kernel是高度模块化和可配置化的,所以在内核中做任何事情(添加一个模块、更改一个模块、去掉一个模块)都必须按照内核设定的方案和流程来走。

3、inand问题

错误分析

(1)得到的内核错误信息:Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)。从错误信息字面意思来分析,就是内核试图挂载根文件系统时失败,失败的原因是unknown-block(不能识别的块设备)
(2)backstrace分析,可以得知错误信息的来源,再结合之前的内核启动流程分析,就更加确定了出错的地方。
(3)下一个问题:分析这个错误出现的原因。unknown-block(0,0)。在kernel启动时uboot会传给内核一个cmdline,其中用root=xx来指定了rootfs在哪个设备上,内核就会到相应的地方去挂载rootfs。譬如我们传参中:root=/dev/mmcblk0p2,这里的/dev/mmcblk0p2就是rootfs的设备地址,这个设备文件编号的含义就是mmc设备0的第2个分区(设备0就是在SD0通道上的设备,也就是iNand),这里的问题就是没找到mmc设备0的第2分区。
(4)下一步问题:为什么没找到mmc设备0的第2分区。一定是因为kernel启动过程中加载mmc驱动的时候有问题,驱动没有发现mmc设备0.问题定位在MMC相关的驱动方面。
(5)对比九鼎版本的内核启动信息,即可发现我们的内核启动并没有找到MMC设备(内置的iNand和外置的SD卡都没找到),没找到肯定是驱动的问题,这就要去移植MMC驱动了。

问题阐述

(1)SD/iNand本身都是由一个一个的扇区组成的,回忆裸机中讲到的210的启动时,BL1在SD卡的1扇区开始往后存放,SD卡的0扇区是不用的。SD卡的0扇区是用来放置MBR的。
(2)MBR就是用来描述块设备的分区信息的,事先定义了一个通用的数据结构来描述块设备的分区,我们只要按照这个标准将分区信息写入MBR中即可对该设备完成分区。MBR默认就是在块设备的第0个扇区上存放的。
(3)我们内核中读到iNand分4个分区,我们哪里分区的?uboot中有一个命令fdisk -c 0时就对iNand进行了分区。uboot的fdisk命令内部已经写死了iNand的分区表,到内核中时内核直接读取MBR就知道了分区。所以在uboot和内核之间iNand设备的分区信息是靠iNand自己传递的,所以uboot不用给内核传参时传递分区表信息。
(4)如果开发板用的是nandFlash的话,分区表一般是在内核中自己用代码构建的。所以nand版本的内核移植的时候一般都需要去移植更改nand分区表。

4、网卡驱动的移植和添加实验

启动信息

(1)网卡驱动移植ok时,启动信息为:
[ 1.452008] dm9000 Ethernet Driver, V1.31
[ 1.455870] eth0: dm9000c at e08f4300,e08f8304 IRQ 42 MAC: 00:09:c0:ff:ec:48 (platform data)
(2)当前内核中网卡驱动尚未移植,因此内核启动时有错误的打印信息:
[ 1.130308] dm9000 Ethernet Driver, V1.31
[ 1.133113] ERROR : resetting
[ 1.135700] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.140915] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.145941] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.150963] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.155992] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.161018] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.166041] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.171070] dm9000 dm9000.0: read wrong id 0x2b2a2928
[ 1.176092] dm9000 dm9000.0: wrong id: 0x2b2a2928
[ 1.180774] dm9000 dm9000.0: not found (-19).

make menuconfig中添加DM9000支持

(1)menuconfig中选择Y
(2)其实这一步本来就是Y,所以在我们这里是不用管的。但是你自己遇到的一个内核可能默认不是Y,因此要设置。

mach-smdkc110.c中逻辑分析

(1)mach-smdkc110.c中的smdkc110_machine_init是整个开发板的所有硬件的初始化函数,在这里加载了的硬件将来启动时就会被初始化,在这里没有的将来启动时就不管。
(2)smdkc110_devices和smdkc110_dm9000_set()这两个地方是和DM9000有关的,要分别去做移植。
(3)smdkc110_dm9000_set这个函数就是DM9000相关的SROM bank的寄存器设置,相当于uboot中dm9000移植时的dm9000_pre_init函数。只是读写寄存器的函数名称不同了。

修改相应的配置参数

(1)DM9000相关的数据配置在arch/arm/plat-s5p/devs.c中更改
(2)在arch/arm/mach-s5pv210/include/mach/map.h中定义了DM9000的IO基地址,和DM9000接在哪个bank有关。
(3)还有+2改成+4,IRQ_EINT9改成10即可。

杂记:内核中机器码的确定
1、MACHINE_START宏

(1)这个宏用来定义一个机器码的数据结构的。这个宏的使用其实是用来定义一个结构体类型为machine_desc类型的结构体变量,名为__mach_desc_SMDKV210。这个结构体变量会被定义到一个特定段.arch.info.init,因此这个结构体变量将来会被链接器链接到这个.arch.info.init段中。

static const struct machine_desc __mach_desc_SMDKV210 \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_SMDKV210, \
.name = "SMDKV210",
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkv210_map_io,
.init_machine = smdkv210_machine_init,
.timer = &s5p_systimer,
};
(2)经过分析,发现一个mach-xxx.c文件中定义了一个机器码的开发板的machine_desc结构体变量,这个结构体变量放到.arch.info.init段中后,那么就表示当前内核可以支持这个机器码的开发板。
(3)落实到当前开发板和当前内核中来分析,当前我们移植的目标开发板使用S5PV210的CPU,开发板名字叫X210.我们在三星官方版本的内核中是找不到mach-x210.c的,所以我们又不想从零开始去移植,因此我们的思路是在三星移植的mach-s5pv210目录下找一个mach-xx.c,这个开发板和我们的X210开发板最为接近,然后以此为基础来移植。
(4)经过查看,发现mach-s5pc110.c和mach-s5pv210.c和我们的X210开发板最为接近。我们一般确定的一个原则是:看我们的开发板和三星官方的哪个开发板最为相似。我们的X210开发板抄的是三星的SMDKV210,因此要找这个对应的那个文件。
(5)结合mach-s5pv210目录下的Makefile来分析,得知.config中定义了CONFIG_MACH_SMDKV210后,实际绑定的是mach-smdkc110.c这个文件。所以实际上mach-smdkv210.c这个文件根本没用到。启示就是不要光看名字。

2、硬件驱动的加载和初始化函数执行

(1).init_machine = smdkc110_machine_init,
(2)这个元素定义了一个机器硬件初始化函数,这个函数非常重要,这个函数中绑定了我们这个开发板linux内核启动过程中会初始化的各种硬件的信息。

从samsung提供内核进行移植的更多相关文章

  1. 愚人的linux内核2440移植札记(超曲折版)

    http://blog.csdn.net/dreambegin/article/details/6904822 原来文章叫--编译内核之初体验.后来想了想,这篇文章让我体验了好多遍.不该叫这么大气的名 ...

  2. linux 2.6 内核的移植

    内核移植过程   下载 linux 内核 从 http://www.kernel.org/pub/linux/kernel/v2.6/linux­2.6.14.1.tar.bz2 下载 linux­2 ...

  3. Linux内核3.0移植并基于Initramfs根文件系统启动

    Linux内核移植与启动 Target borad:FL2440 Bootloader:U-boot-2010.09 交叉编译器:buildroot-2012.08 1.linux内核基础知识 首先, ...

  4. 【转】 linux内核移植和驱动添加(三)

    原文网址:http://blog.chinaunix.net/uid-29589379-id-4708909.html 原文地址:linux内核移植和驱动添加(三) 作者:genehang 四,LED ...

  5. u-boot-2011.06在基于s3c2440开发板的移植之引导内核与加载根文件系统

    http://www.linuxidc.com/Linux/2012-09/70510.htm  来源:Linux社区  作者:赵春江 uboot最主要的功能就是能够引导内核启动.本文就介绍如何实现该 ...

  6. 1.移植3.4内核-分析内核启动过程,重新分区,烧写jffs2文件系统

    1.在上章-移植uboot里.我们来分析下uboot是如何进入到内核的 首先,uboot启动内核是通过bootcmd命令行实现的,在我们之前移植的bootcmd命令行如下所示: bootcmd=nan ...

  7. Linux2.6.32内核笔记(5)在应用程序中移植使用内核链表【转】

    转自:http://blog.csdn.net/Deep_l_zh/article/details/48392935 版权声明:本文为博主原创文章,未经博主允许不得转载. 摘要:将内核链表移植到应用程 ...

  8. LINUX为什么要进行内核移植 内核移植的作用

    LINUX为什么要进行内核移植 内核移植的作用,不移植能用么?   LZ的问题应该是为什么要重新编译内核吧.既然你已经可以跑了,证明你现在用的内核已经移植到你用的硬件上,自然你也不需要做什么移植.通常 ...

  9. linux内核调试指南

    linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 ...

随机推荐

  1. 基于MTCNN多任务级联卷积神经网络进行的人脸识别 世纪晟人脸检测

    神经网络和深度学习目前为处理图像识别的许多问题提供了最佳解决方案,而基于MTCNN(多任务级联卷积神经网络)的人脸检测算法也解决了传统算法对环境要求高.人脸要求高.检测耗时高的弊端. 基于MTCNN多 ...

  2. centos环境配置(nginx,node.js,mysql)

    1.安装 Install GCC and Development Tools on a CentOS yum group install "Development Tools" n ...

  3. html5 canvas绘制环形进度条,环形渐变色仪表图

    html5 canvas绘制环形进度条,环形渐变色仪表图                                             在绘制圆环前,我们需要知道canvas arc() 方 ...

  4. 最短路径——floyd(多源最短路径)

    #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> ...

  5. PHPCMS v9表单向导中怎么加入验证码

    表单想到比较简单,所以没有加入验证码的功能.网上的类似教程又大多数不准确.所以亲自测试了一下,发现下面的方法是可用的.希望对有需求的朋友们有所帮助. 1.首先是调用表单的页面加入验证码.表单js调用模 ...

  6. 开发iOS百度地图大头针可以重复点击

    [self.mapView deselectAnnotation:view.annotation animated:YES];

  7. TCP系列33—窗口管理&流控—7、Silly Window Syndrome(SWS)

    一.SWS介绍 前面我们已经通过示例看到如果接收端的应用层一直没有读取数据,那么window size就会慢慢变小最终可能变为0,此时我们假设一种场景,如果应用层读取少量数据(比如十几bytes),接 ...

  8. nginx 设置默认虚拟 host

    nginx 设置默认虚拟 host listren 80 default_server

  9. IIS安装出现“安装程序无法复制文件CONVLOG.EX_”的解决办法

    重新安装了一次IIS,结果就在重新安装的时候,出现安装程序无法复制文件CONVLOG.EX_,上网找了找资料,是因为secedit.sdb 数据库的问题,既然是因为这个文件的问题,那么我们就可以使用w ...

  10. 异常--try..catch

    class Program { static void Main(string[] args) { try { object obj = null; int N = (int)obj; } catch ...