博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
原厂内核移植流程
阅读量:3738 次
发布时间:2019-05-22

本文共 3795 字,大约阅读时间需要 12 分钟。

原厂内核移植流程

今天开始移植三星原厂的kernel,做一下笔记,以备日后所需

移植的时候有一点感想,就是最好别注释掉不对的源码,定义的地方千万别动,尽量修改调用的地方,这样可以极大的避免出错;此外加上自己代码的时候应该后面用特殊的注释标注一下,这样通过编辑器搜索就很容易定位自己改过的地方

1.先烧录看现象

先烧到板子里试试看,看看有什么现象,再做分析

  • 解压源码后,先看看Makefile中的交叉编译工具链架构信息有没有问题。先在Makefile中搜索CROSS_COMPILE,发现架构信息和交叉编译工具链在同一处,如图:
    这里写图片描述
    它们都是用复杂的表达式来定义的,在此,我们注释掉它们,然后添加我们自己的工具链
#sjh_comment#ARCH       ?= $(SUBARCH)#CROSS_COMPILE  ?=#CROSS_COMPILE  ?= $(CONFIG_CROSS_COMPILE:"%"=%)#end#sjh_addARCH = armCROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-#end
  • 接下来要进行编译前的板级配置,我们要找到一个合适的xxx_defconfig,进入arch/arm/configs目录下发现里面都是xxx_defconfig文件,我们选择smdkv210_android_defconfig。然后make smdkv210_android_defconfig,完成配置
  • 由于kernel启动会根据U-boot传过来的机器码来进行硬件配置,所以我们要选择一个合适的机器码,按照的方法查找,找一个合适的机器码,我们选择smdkv210(机器码为2456),并且确保U-boot传递的机器码和其相同
  • 最后 make -j4 编译,编译得到的zImage在 arch/arm/boot下,把它用tftp下载到板子上启动,发现:
    这里写图片描述
    可知内核启动没有成功

2.解决底层问题,尝试看到打印信息

已知正常情况的打印信息如下:

这里写图片描述
Starting kernel是U-boot打印的,Uncompressing 这句是zImage的自解压头部打印的,后面那句是kernel打印的

  • 由上一步现象里,连zImage的自解压头部都没打印出来信息….分析可知,zImage没有被解压,内核根本就没有被运行,所以问题出在解压相关的部分
  • 参考文章末尾的几种情况,我们基本上可以断定,问题的原因是kernel链接地址与加载地址以及zImage自解压地址三者不相等导致的,已知我们U-boot加载kernel的地址是30008000,那么我们就来检查kernel链接地址与zImage自解压地址
  • 首先进入head.S,按照中的方法查看kernel的物理链接地址,发现是20008000,我们直接将其改成30008000;然后我们再进入arch/arm/mach-s5pv210/Makefile.boot文件中查看自解压地址,发现:
    这里写图片描述
    zreladdr-y的意思就是自解压地址,params_phys-y的意思是存放参数的地址。有上图可知,后面两组都是对的,而第一组有问题,我们直接改掉就行
#sjh_comment#zreladdr-y := 0x20008000#params_phys-y  := 0x20000100#end#sjh_addzreladdr-y  := 0x30008000params_phys-y   := 0x30000100#end

然后直接make即可,因为kernel的Makefile写的非常好,所以不用每次都make distclean,编译完了千万记得把zImage放到/tftpboot中。烧录,发现:

这里写图片描述
kernel成功启动!虽然后面还有一堆问题,但是已经基本有了雏形

3.确定mach-xxx.c

mach-xxx.c是和板级初始化相关的一个文件,在kernel启动后,有很多的初始化是由它来负责的,可以说mach-xxx.c是移植的关键

  • 首先可以确认,我们使用的mach-xxx.c一定是在arch/arm/mach-s5pv210目录下,但是这个目录下有很多mach-xxx.c,比如mach-goni.c、mach-smdkc110.c、mach-smdkv210.c,这些文件代表了不同的开发板(板子上的cpu都是s5pv210),那么我们到底使用的是哪一个呢?如果选择mach-smdkv210.c那就大错特错了,其实这个mach-xxx.c在我们配置时make xxx_defconfig产生的.config决定的,打开arch/arm/mach-s5pv210下的Makefile,发现
obj-$(CONFIG_MACH_SMDKV210)    += mach-smdkc110.oobj-$(CONFIG_MACH_SMDKC110)    += mach-smdkc110.oobj-$(CONFIG_MACH_GONI)        += mach-goni.o
  • 果然,编译哪个mach-xxx.c是由.config决定的,查看.config,发现我们定义了CONFIG_MACH_SMDKV210。由此可知,我们使用的是mach-smdkc110.c;其实还有一种简单粗暴的方法,直接编译,arch/arm/mach-s5pv210目录下去看看生成了哪个.o文件,也可以确定mach-xxx.c。不得不说三星的工程师这一块做的很不好,居然mach-smdkv210.c是废的…..挖了一个大坑…..

4.根据错误进行menuconfig

根据上上步可知,kernel最后没有启动成功,那么现在就来分析打印信息,看看哪里出问题:

这里写图片描述

  • 仔细分析打印信息后,发现kernel后面打印了一大堆如上图所示的乱码,感觉毫无头绪。由此可以猜测,这些打印信息是出错引发的,所以应该从头往下找,看看这些乱码从哪里出现的,或许可以找到问题的发生地点
  • 一开始打印信息都很正常,直到:
    这里写图片描述
    从i2c操作后面开始就有了混乱的苗头,Internal error:表示内核出错了,后面还打印了pc和lr,PC is at dev_driver_string+0xc/0x44 这句表示pc当前位于一个和设备驱动有关的地址;LR is at max8698_pmic_probe+0x150/0x32c 而这句则表示LR当前位于一个和max8698_pmic有关的地址,pmic是powermanage ic的意思
  • 这些信息就有点意思了,i2c、电源管理芯片、驱动。以前U-boot挂掉的时候就是因为和电源管理芯片通信时i2c挂掉导致的,所以我们这里也可以推测出一个结论:smdkv210这块评估板配置了电源管理芯片,系统启动时便去加载其驱动,而我们板子上没这个芯片,所以驱动(i2c协议)挂了
  • 那么如何解决?以前在U-boot我们可以直接屏蔽相关的函数,但是kernel不可以,因为kernel是高度模块化的,随便修改里面的内容会造成很大的风险,正规的做法是使用menuconfig功能。直接make menuconfig,进入界面后输入/MAX8698 来搜索,搜索结果为:
    这里写图片描述
    可知,有两个和MAX8698有关的,第一个和电源管理相关,第二个和整流器相关,根据上图的我们不仅可以知道他们在哪个菜单内,还能知道第二个依赖于第一个。于是我们进入那个菜单,按N屏蔽即可。烧录,虽然还有问题,但是电源管理驱动上的错误已经被解决了:
    这里写图片描述

5.解决flash的问题

由上一步得到的打印信息可知,文件系统挂载失败了

  • 仔细分析那几句打印信息,发现有一句Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) 意思是无法挂载根文件系统,未知块设备0
  • 这可能是驱动的问题,以后再来补充

6.解决网卡问题

再来看看当前的打印信息,发现DM9000的驱动失败了:

这里写图片描述
于是我们来检查一下kernel中DM9000初始化的部分

  • 首先先检查一下menuconfig中有没有选用DM9000,发现已经选择了,驱动代码没问题,看来是初始化和驱动用到的配置值有问题
  • 首先修改初始化,进入mach-smdkc110.c的 smdkc110_machine_init函数,检查DM9000相关的部分,发现调用了smdkc110_dm9000_set函数来初始化DM9000,其定义:
    这里写图片描述
    发现里面有很多的设置是错的,具体寄存器设置方法参见 中网卡配置部分
  • 然后再修改驱动的配置值,在smdkc110_machine_init的开头处可以找到一行platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
    里面的smdkc110_devices便是驱动配置值的数据结构,进去寻找,发现s5p_device_dm9000,再往里挖一层,里面有一个s5p_dm9000_resources,这是dm9000驱动配置值的数据结构:
    这里写图片描述
你可能感兴趣的文章
DOM编程案例——innerHTML innerText操作div和span、去除字符串的前后空白trim
查看>>
JavaScript的正则表达式(Regular Expression)
查看>>
共享资源文件
查看>>
BootStrap的响应式布局
查看>>
BootStrap的全局CSS样式(按钮、图片、表格、表单)
查看>>
BootStrap组件:导航条和分页条和插件: 轮播图
查看>>
jQuery的概念与核心函数$的理解
查看>>
jQuery 对象和 dom 对象
查看>>
jQuery 选择器——基本选择器
查看>>
jQuery 选择器——层级选择器
查看>>
jQuery 选择器——过滤选择器
查看>>
Vue-cli安装及使用
查看>>
jQuery选择器——jQuery 元素筛选
查看>>
jQuery 的属性操作
查看>>
jQuery中DOM 的增删改
查看>>
jQuery中CSS 样式操作
查看>>
jQuery 动画
查看>>
jQuery 事件操作
查看>>
Git的安装与卸载
查看>>
JavaWeb的概念
查看>>