【树莓派学习笔记】树莓派4B上运行uboot并从网络启动linux内核(下)

上期入口:

【树莓派学习笔记】树莓派4B上运行uboot并从网络启动linux内核(上)



参考:

  1. https://hechao.li/2021/12/20/Boot-Raspberry-Pi-4-Using-uboot-and-Initramfs/
  2. https://www.raspberrypi.com/documentation/computers/

5. U-boot在树莓派4B上的运行

5.1 树莓派4B的启动流程

  1. 树莓派启动时会先读取板载的EEPROM,进行一些基础的设置,之后启动VideoCore;
  2. VideoCore执行start4.elf,如果未在config.txt中指定kernel=xxx,那么start4.elf执行完毕会启动kernel8.img
    一般我们只需要将编译好的linux内核命名成kernel8.img就可以启动linux了,而且树莓派4B的设置本身也支持网络启动。但是相比u-boot而言,上述方式缺少了u-boot源码编译的灵活性而且增加了树莓派网络启动的学习成本,所以本文中仍然使用u-boot启动的方式。

5.2 将u-boot.bin与固件写入SD卡中

# 拷贝 u-boot.bin
$ sudo cp u-boot.bin /mnt/boot
$ mkdir ~/raspberry4B/firmware; cd ~/raspberry4B/firmware
# 下载树莓派的官方固件
$ svn checkout https://github.com/raspberrypi/firmware/trunk/boot
# 树莓派4B不再需要bootcode.bin 经过实测如果不拷贝dtb设备树文件树莓派无法启动
$ sudo cp boot/start4.elf boot/bcm2711-rpi-4-b.dtb /mnt/boot
$ cat << EOF > config.txt
enable_uart=1
arm_64bit=1
kernel=u-boot.bin
total_mem=1024
EOF
$ sudo mv config.txt /mnt/boot/

enable_uart=1 :树莓派4B中的primary UART是mini UART,设备名称为/dev/ttyS0,通过该语句可以使能mini UART,我们需要使用该UART输出调试信息并且作为linux控制台使用。
arm_64bit=1 :64位的固件需要使用该语句
kernel=u-boot.bin :5.1节提到默认的启动文件名为kernel8.img,通过该语句将文件名更改为我们刚刚编译好的u-boot.bin
total_mem=1024 :这一句不加后续内核会报错。

5.3 u-boot.bin运行测试

5.3.1 硬件准备

  • 将SD卡从读卡器取出,装入树莓派的SD卡槽(树莓派连接显示器和键盘的直接跳转到第4步)

  • 使用杜邦线将树莓派上的GND,TXD,RXD分别与USB转TTL模块的GND,RXD,TXD三根pin相连(注意:RX接TX,TX接RX)
    树莓派pin脚图

  • 将USB转TTL模块的USB端插入电脑(注意不要连接到虚拟机),在设备管理器中找到对应的COM口,本例中为COM10
    USB转TTL模块的端口描述

  • 给树莓派4B连接显示器,键盘,网线连接至路由器(使用串口调试只连接网线即可)

5.3.2 软件准备

使用显示器,键盘和网线的可忽略本小节。

  • 在电脑端打开一款串口监控软件,本例中使用MobaXterm,设置参数如下图所示(本例中为COM10),设置完成后开启串口监控
    串口参数设置

5.3.3 u-boot运行

将树莓派接通电源并打开电源开关可观察现象如下图所示,此时u-boot运行成功。
u-boot初步运行

6. Linux内核的配置与编译

本例中使用linux内核版本为rpi-5.17.y

6.1 下载linux源码

$ cd ~/raspberry4B
$ git clone --depth=1 -b rpi-5.17.y https://github.com/raspberrypi/linux.git
$ cd linux

6.2 配置并编译内核

$ KERNEL=kernel8
# 选择树莓派4B的芯片bcm2711
$ make ARCH=arm64 CROSS_COMPILE=aarch64-rpi4-linux-gnu- bcm2711_defconfig
  • 如果需要串口控制台,需要使用menuconfig进行详细配置:
$ make ARCH=arm64 CROSS_COMPILE=aarch64-rpi4-linux-gnu- menuconfig

依次进入Device drivers —> Character devices —> Serial drivers ,将Number of 8250/16550 serial ports to register at runtime前的数字由0更改为1,退出并保存。
串口控制台参数修改

# 正式编译内核,过程会比较长
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image.gz modules dtbs -j${nproc}

编译完成后将镜像文件Image与设备树文件bcm2711-rpi-4-b.dtb拷贝入tftp服务端的文件夹内(篇幅所限,tftp服务器的配置本文不做详细介绍)。

$ sudo cp arch/arm64/boot/Image ~/tftp
$ sudo cp arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dtb ~/tftp

7. 根文件系统的构建linux运行

linux想要运行一个根文件系统是必不可少的,本章节主要介绍构建一个根文件系统。

7.1 新建文件夹

$ mkdir -p ~/raspberry4B/nfs/rootfs
$ cd ~/raspberry4B/nfs/rootfs
$ mkdir bin dev etc home lib64 proc sbin sys tmp usr var
$ mkdir usr/bin usr/lib usr/sbin var/log
# 创建lib64的快捷方式lib
$ ln -s lib64 lib
# 将目录的所有者改为root
$ sudo chown -R root:root *

7.2 下载编译安装Busybox

# 下载busybox源码
$ cd ~/raspberry4B/
$ wget https://busybox.net/downloads/busybox-1.33.2.tar.bz2
$ tar xf busybox-1.33.2.tar.bz2
$ cd busybox-1.33.2/

# 默认配置
$ make CROSS_COMPILE=aarch64-rpi4-linux-gnu- defconfig
# 修改安装目录
$ sed -i 's%^CONFIG_PREFIX=.*$%CONFIG_PREFIX="/home/fyh/raspberry4B/nfs/rootfs"%' .config

注:其中/home/fyh/为楼主自己的home路径,需要更换为自己的

# 编译并安装至路径
$ make CROSS_COMPILE=aarch64-rpi4-linux-gnu-
$ sudo make CROSS_COMPILE=aarch64-rpi4-linux-gnu- install

拷贝一些必要的库文件

$ export SYSROOT=$(aarch64-rpi4-linux-gnu-gcc -print-sysroot)
$ cd ${SYSROOT}
$ sudo cp -L ld-linux-aarch64.so.1 libm.so.6 libresolv.so.2 libc.so.6 ~/raspberry4B/nfs/rootfs/lib

7.3 生成设备节点

$ cd ~/raspberry4B/nfs/rootfs
$ sudo mknod -m 666 dev/null c 1 3
$ sudo mknod -m 622 dev/console c 5 1

7.4 其他文件的准备

$ cd ~/raspberry4B
# 下载三个文件
$ git clone https://github.com/fyhfir/rootfs-required-files
$ cd rootfs-required-files
$ sudo mkdir ~/raspberry4B/nfs/rootfs/etc/init.d
$ sudo cp fstab inittab ~/raspberry4B/nfs/rootfs/etc/
$ sudo cp rcS ~/raspberry4B/nfs/rootfs/etc/init.d/

注:连接屏幕和键盘的童鞋可以将文件inittab中的ttyS0字样替换为console

8. U-boot的配置

第5章我们仅仅实现了在树莓派4B上运行u-boot,想要实现u-boot引导网络启动linux还需要对u-boot进行配置,本章主要介绍u-boot的配置,以下的命令均在树莓派4B上运行,不再运行于Ubuntu虚拟机。

8.1 建立与主机的网络连接

# 设置ip地址
setenv ipaddr 192.168.1.101
# 设置网关
setenv gatewayip 192.168.1.1
# 设置子网掩码
setenv netmask 255.255.255.0
# 设置服务器ip:即ubuntu的网络ip地址,本例中为192.168.1.108
setenv serverip 192.168.1.108
# 保存环境变量
saveenv

成功会显示:

Saving Environment to FAT… OK

# 测试与服务器通信 本例中为192.168.1.108
ping 192.168.1.108

成功会显示:

Using ethernet@7d580000 device
host 192.168.1.108 is alive

8.2 设置网络启动参数

# 用tftp下载镜像Image和设备树至指定地址,使用booti启动linux内核
setenv bootcmd "tftp ${kernel_addr_r} Image;tftp ${fdt_addr_r} bcm2711-rpi-4-b.dtb;booti ${kernel_addr_r} - ${fdt_addr_r}"
# 设置控制台的串口 设置网络挂载的根文件系统的路径 设置ip地址,服务器地址,网关,子网掩码,网络设备号
setenv bootargs "console=ttyS0,115200 console=tty1 root=/dev/nfs rw nfsroot=192.168.1.108:/home/fyh/raspberry4B/nfs/rootfs ip=192.168.1.101:192.168.1.108:192.168.1.1:255.255.255.0::eth0:off"
saveenv

上文中主要通过nfs网络挂载根文件系统,由于篇幅限制,nfs的配置也不做详细介绍了。
启动linux:

boot

启动后现象如下:
linux网络启动

完结

Logo

更多推荐