注:以下内容来自朱老师物联网大讲堂课件
1. 内核移植初体验
1.1 三星官方移植版内核获取
从网盘下载源码包,这个文件最初是来自于三星的SMDKV210开发板附带的光盘资料
1.2 构建移植环境
(1)删除多余的文件(主要是arch下的无关文件),Windows下建立SI工程
(2)ubuntu下解压
1.3 配置编译下载尝试
(1)检查并更改Makefile中ARCH和CROSS_COMPILE
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
(2)在/arch/arm/configs目录下找到合适的配置文件
我们选择:smdkv210_android_defconfig
如果在配置过程中出现在x86文件夹中找不到文件,则是我们的ARCH ?= arm没有起作用,我们只需要屏蔽掉之前的ARCH赋值即可。
?= 如果变量前面并没有赋值过则执行这条赋值,如果前面已经赋值过了则本行被忽略。
(3)make menuconfig
(4)make -j4
默认情况下直接make则会直接单线程编译。但是如果make -j4则会4线程编译。
注意:如果之前的CROSS_COMPILE没有注释掉,就会出现编译报错,因为我们使用的?=赋值。
(5)使用tftp下载生成的镜像zImage到开发板
实验现象是只显示了uboot最后的代码,kernel部分的代码没有执行,并且解压缩的信息也是没有的。
2. 自解压代码未运行
实验现象:linux内核的自解压代码都没有运行(因为没有看到:Uncompressing Linux… done, booting the kernel.)
问题分析:
(1)说明zImage根本没有被解压成功,内核代码根本就没有被运行,当然没有输出信息了。所以问题出在解压相关的部分。
(2)问题出在内核配置的解压后代码放置的内存地址处。
(3)内核配置的解压地址应该等于连接地址,否则自解压之后内核无法运行。现在问题变成:第一,内核的连接地址等于多少?第二,内核中配置的解压地址是多少?
(4)这里面还有个问题:内核的连接地址是一个虚拟地址,而自解压代码解压内核时需要物理地址,因此上面说的等于,其实是连接地址对应的物理地址等于自解压地址。
(5)连接地址和他对应的物理地址在head.S中可以查到,分别是0xC0008000和0x30008000。那么自解压代码配置的解压地址应该是30008000.
通过我们之前的memory map 和我们实际的硬件连接,我们的DRAM物理地址是从0x30000000开始的。
#if defined(CONFIG_MACH_SMDKV210)
#define PHYS_OFFSET UL(0x30000000) //之前是0x20000000
#else
#define PHYS_OFFSET UL(0x30000000)
#endif
(6)自解压代码对应的自解压地址在mach/Makefile.boot(/arch/arm/mach-s5pv210/Makefile.boot)文件中。通过我们的查看发现缺少我们210的配置。
解决方法:添加SMDKV210的配置代码到Makefile.boot
实验验证:我们的自解压已经完成并且有kernel的信息输出,但是启动过程会reboot。
3. 内核中机器码的确定
我们在uboot阶段已经将机器码存储在r1中,那么kernel是如何进行校验的?
3.1 MACHINE_START宏
按理说我们就应该使用mach-smdkv210.c这个文件所代表的开发板进行移植,但是实际我们发现我们的mach-smdkv210.c这个文件没有被编译(无.o文件生成),查看该文件夹下的Makefile发现CONFIG_MACH_SMDKV210是使用的smdkc110.c
obj-$(CONFIG_MACH_SMDKV210) += mach-smdkc110.o
obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o
//mach-smdkv110.c
#ifdef CONFIG_MACH_SMDKC110
MACHINE_START(SMDKC110, "SMDKC110")
#elif CONFIG_MACH_SMDKV210
MACHINE_START(SMDKV210, "SMDKV210")
#endif
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.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 = smdkc110_map_io,
.init_machine = smdkc110_machine_init,
.timer