对于一个完整的linux系统,其由三部分组成:
- bootloader
- kernel
- rootfile system
bootloader相当于pc机上的bios,负责引导进入kernel,而rootfile system负责文件的存放与用户的交互。对于bootloader,这里使用uboot;对于rootfs,使用buildroot。
一、编译工具的准备
这里需要使用的交叉编译工具链为:arm-linux-gnueabi-。我们使用它来编译u-boot和kernel。而rootfs则使用musl完成。
二、u-boot
这里根据自己的需求下拉u-boot,这里使用licheepi nano的800*480分支。
git clone -b nano-lcd800480 https://github.com/LicheePiNano/u-boot.git
因为本次系统存放在SD卡上,所以使用licheepi_nano_defconfig
,然后在menuconfig里面修改一些启动参数。如果使用spi flash,则使用licheepi_nano_spiflash_defconfig
。配置文件保存在/u-boot/configs/
下。
make ARCH=arm licheepi_nano_defconfig
make menuconfig
2.1 u-boot参数配置
2.1.1 bootcmd
这里主要添加bootargs和bootcmd。bootcmd主要执行三条命令
- load mmc 0:1 0x80008000 zImage;
- load mmc 0:1 0x80c08000 suniv-f1c100s-licheepi-nano.dtb;
- bootz 0x80008000 - 0x80c08000;
load mmc负责将kernel编译出来的zImg、dtb加载到内存;bootz负责启动linux zImg。
因此,bootcmd中添加如下内容:
load mmc 0:1 0x80008000 zImage;load mmc 0:1 0x80c08000 suniv-f1c100s-licheepi-nano.dtb;bootz 0x80008000 - 0x80c08000;
2.1.1 bootargs
console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw
console=ttyS0,115200
,表示终端为ttyS0即串口0,波特率为115200;panic=5
,设置kernel恐慌时间;rootwait
, 该参数是告诉内核挂在文件系统之前需要先加载相关驱动,这样做的目的是防止因mmc驱动还未加载就开始挂载驱动而导致文件系统挂载失败;root=/dev/mmcblk0p2
,表示根文件系统的位置在mmc的0:2分区处,/dev
是设备文件夹,内核在加载mmc中的时候就会在根文件系统中生成mmcblk0p2设备文件,这个设备文件其实就是mmc的0:2分区(这里对应TF卡的第二个分区:rootfs),这样内核对文件系统的读写操作方式本质上就是读写/dev/mmcblk0p2
该设备文件;earlyprintk
,参数是指在内核加载的过程中打印输出信息,这样内核在加载的时候终端就会输出相应的启动信息。rw表示文件系统的操作属性,此处rw表示可读可写。
2.2 编译u-boot
在配置完成bootargs和bootcmd之后,开始编译:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8
在编译完成之后,/u-boot/
下生成了输出文件——u-boot-sunxi-with-spl.bin
。在使用dd创建启动盘之前,先对SD卡进行初始化。
三、SD卡分区设置
我们在ubuntu下使用GParted来实现SD卡分区设置,如果没有安装,则可以直接使用apt来安装,sudo apt-get install gprated
。SD卡分区设置如下:
第一个分区为fat16,用来存放kernel内容;第二分区为ext4,用来存放rootfs内容。
四、kernel
我们在kernel.org下载内核,同时将linux-licheepi_nano_defconfig放入/arch/arm/configs/
中。
make ARCH=arm linux-licheepi_nano_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8 INSTALL_MOD_PATH=out modules
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8 INSTALL_MOD_PATH=out modules_install
之后输出的zImg文件在/arch/arm/boot/
下;设备树dtb文件在/arch/arm/boot/dts/
下。
五、buildroot
在buildroot.org下载源码,解压后准备配置:
make clean
make menuconfig
5.1 Target options
这里需要注意的配置有:目标架构为arm小端,即ARM (little endian)
;同时架构变体为arm926t
;浮点运算选择soft float
软浮点。详细的配置如下图2所示。
5.2 Build options
这里将库设置为动态化静态库,如下图3所示。
5.3 Toolchain
这里编译工具选择musl以减少体积,同时选择Thread library debugging
和Enable xxxx
一堆选项。
5.4 System configuration
这里主要配置root登录的密码:
之后直接使用make
开始编译,第一次编译需要下载一些组件,所以时间比较长。编译完成后,在/output/images/
下有输出文件,rootfs.tar
。
六、移植
在第三节中,我们对SD卡进行了分区,之后将开始移植。首先使用dd将u-boot文件拷贝到SD卡作为启动项,以图1中的设备为例,此处为/dev/sdb
,即:
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
之后将zImg和dtb文件拷贝到SD卡的boot分区;将rootfs.tar解压到SD卡的rootfs分区:
sudo tar -xvf rootfs.tar -C /media/<你的用户名>/rootfs/