一、编译U-boot
u-boot作为开源项目,可在其官网下载源码,官网地址:https://www.denx.de/wiki/U-Boot/ki/U-Boot/
但在实际开发过程中,我们不会直接去u-boot官网下载源码,并在这个源码基础上修改,因为这样工作量太大。
一般来说Soc厂商会为其发布的每一款Soc设计一块开发板,以便使用者学习,这块开发板被称之为公板。同时厂商也会为该公板修改出一套相适应的u-boot。 s3c2440的公板名为smdk2440,由三星公司设计,mini2440是在smdk2440的基础上,由友善之臂修改而来。
(1)编译过程:
- 进入u-boot源码顶层目录
- 执行make smdk2440_config将编译目标设置为smdk2440
- 执行make
- 之后就能编译出适合mini2440的u-boot.bin文件,而smde2440配置文件在board/samsung目录下
(2)流程分析:
1、编译后的u-boot会在顶层目录下保留一个名为u-boot.lds文件, uboot第一行代码在哪,可以从这里看出来。u-boot.lds第3行,表明第一条指令是从_start处开始的。
2、打开arch/arm/cpu/arm920t/start.S,在40行找到了_start。可以看到跳转到了start_code中。
3、在这个过程中,异常向量表初始化、关闭看门狗、关闭DCache等操作。之后跳转到SDRAM:打开dcache等。
二、编译uImage
(1)编译过程:
-
下载linux内核源码压缩包linux-2.6.32.2-mini2440-20150709.tgz并解压缩
-
进入linux-2.6.32.2源码顶层目录
-
执行cp config_mini2440_td35 .config .config是makefile的默认配置文件
-
执行make menuconfig 去选择需要的驱动,进入后如下图所示,选择Device Drivers。
-
选择Device Drivers——Character devices,选项旁边的符号 空格、M 和 * 分别表示不同的配置状态,之后进行保存。
(1)星(内建,Built-in): 表示该功能或驱动将被内建到内核中,编译后的内核中会直接包含该功能或驱动,不需要额外加载模块。
(2)空格(未选中): 表示该功能或驱动未被启用,内核编译时不会包含该功能或模块,相关代码也不会被编译进内核。
(3)M(模块化,Module): 表示该功能或驱动将被编译为 可加载模块(.ko 文件),在运行时,这些模块可以按需加载到内核中,而不需要重新启动系统或重新编译整个内核。
-
make uImage执行得到。
(2)流程分析:
三星公司同样为smdk2440定制了一套linux源码,友善之臂稍作修改后提供给我们, 文件名: linux-2.6.32.2-mini2440-20150709.tgz,将该文件解压后如图所示及其不同文件夹下面的解释说明。
上图中的目录一起构成了linux源码,这些源码必须经过编译才能够在开发板上运行。同理要编译源码就要在编译前进行配置。linux源码公板配置文件在arch/arm/configs下,理论上我们直接使用该目录下的s3c2410_defconfig文件就可以。但是由于mini2440在公板基础上做了一点修改,而修改后的配置文件就在linux源码顶层目录中,那些名为config_mini2440_xxx的文件都是。
为什么有这么多?是因为mini2440适配的屏可能是lcd,还可能是vga,还不确定尺寸多大。所以搞出来一堆。这里最适合我们使用的是config_mini2440_td35。 接下来问题是编译时怎么才能让makefile清楚我们要用config_mini2440_td35这个文件配置呢?其实虽然配置文件很多,但其实makefile只认一个配置文件: .config。我们可以用下面命令来设置.config为我们需要的配置文件。
cp config_mini2440_td35 .config
.config文件中配置内容非常多,所有驱动的、环境的、功能的、架构的配置都在这里,看起来非常不方便。好在linux社区提供了一种图形化方式来提高配置的可视化: make menuconfig ,退出前保存一下,如果不保存,编译时会出现很多选项让我们去选。之后就是make uImage,经过漫长的等待之后编译输出Image arch/arm/boot/uImage is ready就表示编译完成编译之后主要生成三个文件Image、 zImage、 uImage而那个uImage文件就是我们之前下载用的那个,可以将新编译好的uImage下载到开发板中,尝试一下能否正常启动,理论上这个uImage是不能使用的,系统会出现复位。
解决uImage不能使用的方法是打开arch/arm/boot/Makefile文件,找到第64行将STARTADDR改为0x30008040,再次编译重新下载之后问题就能解决。要解释这个问题出现的原因,我们要分析一下编译出的三个文件的区别。
Image:这个才是真正的镜像文件,大小约为4MB多一点
zImage:是Image压缩后的文件大小为2332580字节
uImage:也是Image压缩后的文件,不过它比zImage大了64字节,大小为2332644
多出的64字节是因为uImage中增加的一些文件信息,譬如linux版本,编译时间等等。很明显这些信息是不能够被执行的。问题在于之前编译好的内核我们下载到了0x30008000处,并且这个地址也是第一条指令的地址,称为入口地址。入口地址存放
的不是arm指令,就造成了arm指令异常,产生复位。上面的修改将入口地址向后偏移了0x40=64个字节,而这恰好就正在的指令了,问题也就解决了。