交叉编译工具链:arm-bcm2708-linux-gnueabi-
u-boot:u-boot-2015.10(http://www.denx.de/wiki/U-Boot/SourceCode)
Linux内核:linux-rpi-4.1.y (https://github.com/raspberrypi/linux/tree/rpi-4.1.y)
硬件单板:树莓派b
本文基于u-boot-2005和linux4.1.y,使用最新的DTS方式从外接U盘来引导树莓派b的Linux系统。
1 环境准备
1.1 u盘分区
树莓派的启动使用到了SD卡。这里为了调试方便,使用u-boot和U盘来引导Linux系统启动。首先准备一个U盘,并进行分区和格式化。具体步如下:
[apple@apple ~]$ sudofdisk /dev/sdb
WARNING: DOS-compatible mode is deprecated. It's stronglyrecommended to
switch off the mode(command 'c') and change display units to
sectors (command'u').
Command (m for help): p #查看现有分区
Disk /dev/sdb: 8004 MB, 8004304896 bytes
255 heads, 63 sectors/track, 973 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xcad4ebea
Device Boot Start End Blocks Id System
/dev/sdb4 * 1 974 7816576 c W95 FAT32 (LBA)
Partition 4 has different physical/logical endings:
phys=(972, 254, 63)logical=(973, 34, 21)
Command (m for help): d #删除分区
Selected partition 4
Command (m for help): n #添加第一个分区
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-1020,default 1): 1
Using default value 1
Last cylinder, +cylindersor +size{K,M,G} (1-1020, default 1020): 20
Command (m for help): n #添加第二个分区
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (21-1020,default 21): 21
Last cylinder, +cylindersor +size{K,M,G} (21-1020, default 1020): 1020
Command (m for help): p #再次查看分区信息
Disk /dev/sdb: 8004 MB, 8004304896 bytes
247 heads, 62 sectors/track, 1020 cylinders
Units = cylinders of 15314 * 512 = 7840768 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xcad4ebea
Device Boot Start End Blocks Id System
/dev/sdb1 1 20 153109 83 Linux
/dev/sdb2 21 1020 7657000 83 Linux
Command (m for help): w #写入分区
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
分区完成后查看/dev/目录下产生了两个分区:
[apple@apple ~]$ ls/dev/sdb*
/dev/sdb /dev/sdb1 /dev/sdb2
1.2 分区格式化
第一个分区sdb1用来存放u-boot需要加载的内核Image以及dtb文件,格式化为vfat文件系统;第二个分区sdb2用来存放根文件系统,格式化为ext4文件系统。具体步骤如下:
[apple@apple ~]$ sudo mkfs.vfat /dev/sdb1
[apple@apple ~]$ sudo mkfs.ext4 /dev/sdb2
2 安装u-boot
2015.10版的u-boot已经对树莓派有了较好的支持,不仅可以从SD卡加载引导内核,还可以从U盘和网络加载引导,因此选用该版本的u-boot。
2.1 编译u-boot
[apple@applebuild]$ tar xvf ../source/u-boot-2015.10.tar.bz2
在u-boot根目录的configs已经包含了树莓派的默认配置文件:
[apple@apple configs]$ ls rpi*
rpi_2_defconfig rpi_defconfig
这里直接使用rpi_defconfig即可,在u-boot根目录下编写一个简单的编译脚本:
[
[email protected]]$ vi build.sh
#!/bin/sh
make distclean
make rpi_config
make all
[[email protected]]$ chmod +x build.sh
然后执行编译(注意添加环境变量CROSS_COMPILE指定交叉编译工具):
[
[email protected]]$ ./build.sh
最后在根目录下生成u-boot.bin即是u-boot的二进制执行文件,将他放在SD卡的fat目录下即可引导启动(具体见《树莓派的启动引导方式》和《移植u-boot到树莓派》)。
2.2 配置u-boot环境变量
从u-boot的启动打印信息中可以看出,它会尝试从SD卡中获取u-boot配置文件"uboot.env"并读取其中的环境变量如果读取失败则使用默认的环境变量。该环境变量可以通过setenv和saveenv命令修改。
由于使用的是U盘引导,所以需要首先使能usb,同时扫描usb设备并读取内核image和dtb文件,所以修改环境变量如下并保存:
U-Boot> setenv bootcmd "usb start;fatload usb 0:1 ${fdt_addr_r}/bcm2708-rpi-b.dtb;fatload usb 0:1 ${loadaddr} /uImage;bootm ${loadaddr} -${fdt_addr_r}"
U-Boot> setenv ipaddr 192.168.0.20
U-Boot> setenv serverip 192.168.0.17
U-Boot> setenv bootargs "console=ttyAMA0,115200kgdboc=ttyAMA0,115200 root=/dev/sda2 rootfstype=ext4 rootwait"
U-Boot> saveenv
这里配置了内核的启动参数和引导命令,首先启动usb并扫描外挂器件,然后加载DTB和内核,最后引导内核启动。同时这里的bootargs参数会在引导启动时修改DTB中的chosen项并写入。
保存后就会在SD卡的fat目录下生成uboot.env文件了,下次启动u-boot时就可以直接读取了。注意不可以直接修改该文件,因为在uboot读取该文件时会做CRC校验。
3 内核及dtb编译
内核选用树莓派Linux4.1.12+版本内核,已经对LinuxDevice Tree有较好的支持了。
3.1 下载并配置内核
首先从github上下载内核4.1.y的分支:
[apple@apple RpiSource]$ sudo git clonehttps://github.com/raspberrypi/linux.git /linux-rpi-4.1.y
下载完成后启动配置,在arch/arm/configs/目录下包含了bcmrpi_defconfig,直接使用即可(指定交叉编译工具)。
[[email protected]]$ make bcmrpi_defconfig
[[email protected]]$ make menuconfig
查看如下配置,内核已经支持DTS:
General setup --->
(arm-linux-gnueabihf-)Cross-compiler tool prefix
System Type --->
ARM system type (Broadcom BCM2708 family) --->
Broadcom BCM2708 Implementations --->
[*] BCM2708 DeviceTree support
Bootoptions --->
-*-Flattened Device Tree support
[*] Support for the traditional ATAGS boot datapassing
上面配置文件中勾选了BCM2708Device Tree support,在内核编译dtb时会默认编译/arch/arm/boot/dts/bcm2708-rpi-*.dtb(详细可见Makefile)。
3.2 编译内核和DTB
创建目标生成目录,该目录用于存放编译后的内核镜像文件和内核:
[[email protected]]$ mkdir release
编写编译脚本build.sh:
#!/bin/sh
make uImage -j4
make dtbs
cp arch/arm/boot/uImage release/
cp arch/arm/boot/zImage release/
cp arch/arm/boot/dts/bcm2708-rpi-b.dtb release/
执行脚本编译,编译完成后在release目录下生成了uImage和bcm2708-rpi-b.dtb文件。将他们拷贝到U盘的第一个fat分区中,然后启动树莓派,uboot引导内核启动时输出打印如下:
reading /bcm2708-rpi-b.dtb
10212 bytes read in 26 ms (382.8 KiB/s)
reading /uImage
8115848 bytes read in 4252 ms (1.8 MiB/s)
## Booting kernel from Legacy Image at 00200000 ...
Image Name: Linux-4.1.15
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 8115784 Bytes = 7.7 MiB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum ... OK
## Flattened Device Tree blob at 00000100
Booting using the fdt blob at0x000100
Loading Kernel Image ... OK
Loading Device Tree to07b42000, end 07b477e3 ... OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
[ 0.000000] Booting Linuxon physical CPU 0x0
[ 0.000000] Initializingcgroup subsys cpuset
[ 0.000000] Initializingcgroup subsys cpu
……
至此内核启动成功。