前言
本篇文章将从0开始,编译出uboot,kernel image, rootfs。虚拟机都是重装的。
文章将采用“ 遇到问题,解决问题 ”的叙述结构
希望可以对你有所帮助
准备工作
准备一块orangepi pc,以及相应的供电线,网线,usb转串口,读卡器,不小于1GB的SD卡。
下载uboot_2020.04源码https://github.com/orangepi-xunlong/u-boot-orangepi/tree/v2021.10-sunxi
下载kernel_5.4.6源码:https://github.com/orangepi-xunlong/linux-orangepi
访问慢的话,拉取到gitee里下载会快很多
下载busybox1.29.0 :https://busybox.net/downloads/busybox-1.29.0.tar.bz2
下载gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf编译器
:https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/9.2-2019.12/binrel/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz
全套打包放CSDN了https://download.csdn.net/download/qq_42039294/85535963?spm=1001.2014.3001.5501
下载完成后,我们会有如下文件
linux-orangepi-orange-pi-5.4.zip 232MB
u-boot-orangepi-v2020.04.zip 26.6MB
gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz 251 MB
busybox-1.29.0.tar.bz2 2.19 MB
一共0.5G,如果使用香橙派社区的工具包,下载一份几百兆的文件夹,运行其中的build.sh脚本,他会帮你下载源文件,配置编译器,但是体积会达到10个G。
准备一份装好了ubuntu的虚拟机,香橙派社区文档里推荐使用18.04版本,
安装gcc编译器,大家参考如下链接
https://blog.csdn.net/lengyuefeng212/article/details/119255594
最后测试使用指令
arm-none-linux-gnueabihf-gcc -v
uboot
编译uboot
解压,打开uboot源码顶层makefile,指定架构和交叉编译器
CROSS_COMPILE ?= arm-none-linux-gnueabihf-
ARCH ?= arm
指定编译目标, 编译
make orangepi_pc_defconfig
make
如果你是像我一样,从头安装的ubuntu 18.04, 在这里你会遇到一连串问题。你可以直接安装以下软件
sudo apt-get install bison -y
sudo apt-get install flex -y
sudo apt-get install python3-distutils -y
sudo apt install swig -y
sudo apt install python3-dev -y //版本输入python -V 查看
这些软件没有安装的话,对应的问题如下,按顺序对应
1:scripts/Makefile.lib:226: recipe for target 'scripts/kconfig/zconf.tab.c' failed
2:scripts/Makefile.lib:218: recipe for target 'scripts/kconfig/zconf.lex.c' failed
3:ModuleNotFoundError: No module named 'distutils.core'
4:unable to execute 'swig': No such file or directory
5:scripts/dtc/pylibfdt/libfdt_wrap.c:149:11: fatal error: Python.h: 没有那个文件或目录 # include <Python.h>
解决所有问题之后,编译出现以下文件就说明成功了
制作启动sd卡
首先,使用SD card formatter软件格式化SD卡
之后接入到虚拟机,umount卸载掉这张SD卡,
winston@winston-vm:~$ ls /media/winston/
DBC7-27AF
winston@winston-vm:~$ umount /media/winston/DBC7-27AF
winston@winston-vm:~$ ls /dev/sd*
/dev/sda /dev/sda1 /dev/sdb /dev/sdb1
使用fdisk将这张SD卡分为前200M、剩余空间两个分区
winston@winston-vm:~$ sudo fdisk /dev/sdb
[sudo] winston 的密码:
欢迎使用 fdisk (util-linux 2.31.1)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
命令(输入 m 获取帮助): d //删除SD card formatter创建的一个分区
已选择分区 1
分区 1 已删除。
命令(输入 m 获取帮助): n //创建新分区
分区类型
p 主分区 (0个主分区,0个扩展分区,4空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p):
将使用默认回应 p。
分区号 (1-4, 默认 1):
第一个扇区 (2048-15728639, 默认 2048):
上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-15728639, 默认 15728639): +200M
创建了一个新分区 1,类型为“Linux”,大小为 200 MiB。
命令(输入 m 获取帮助): n
分区类型
p 主分区 (1个主分区,0个扩展分区,3空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p):
将使用默认回应 p。
分区号 (2-4, 默认 2):
第一个扇区 (411648-15728639, 默认 411648):
上个扇区,+sectors 或 +size{K,M,G,T,P} (411648-15728639, 默认 15728639): //直接回车
创建了一个新分区 2,类型为“Linux”,大小为 7.3 GiB。
命令(输入 m 获取帮助): w
分区表已调整。
将调用 ioctl() 来重新读分区表。
正在同步磁盘。
winston@winston-vm:~$
前者格式化为vfat格式,后者格式化为ext4。
sudo mkfs.vfat /dev/sdb1
sudo mkfs.ext4 /dev/sdb2
使用lsblk -f查看一下
烧录,启动
进入uboot顶层目录,使用如下命令烧录,建议将这个命令做成脚本使用
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
注意,这里的烧录速度不应该太快,如果出现几百兆/s,一定是SD卡没连接到虚拟机。或者出现了僵尸文件/dev/sdb,手动删除/dev/sdb再插入SD卡就行
将烧录好的SD卡插入香橙派,上电,连接USB-TTL,
启动的时候按一下空格,不然它就要加载linux镜像了。串口助手打印的完整启动日志如下
U-Boot 2020.04 (Jun 03 2022 - 16:32:12 +0800) Allwinner Technology
CPU: Allwinner H3 (SUN8I 1680)
Model: Xunlong Orange Pi PC
DRAM: 1 GiB
MMC: mmc@1c0f000: 0
Loading Environment from FAT... *** Warning - bad CRC, using default environment
In: serial@1c28000
Out: serial@1c28000
Err: serial@1c28000
Net: phy interface0
eth0: ethernet@1c30000
starting USB...
Bus usb@1c1a000: USB EHCI 1.00
Bus usb@1c1a400: USB OHCI 1.0
Bus usb@1c1b000: USB EHCI 1.00
Bus usb@1c1b400: USB OHCI 1.0
Bus usb@1c1c000: USB EHCI 1.00
Bus usb@1c1c400: USB OHCI 1.0
Bus usb@1c1d000: USB EHCI 1.00
Bus usb@1c1d400: USB OHCI 1.0
scanning bus usb@1c1a000 for devices... 1 USB Device(s) found
scanning bus usb@1c1a400 for devices... 1 USB Device(s) found
scanning bus usb@1c1b000 for devices... 1 USB Device(s) found
scanning bus usb@1c1b400 for devices... 1 USB Device(s) found
scanning bus usb@1c1c000 for devices... 1 USB Device(s) found
scanning bus usb@1c1c400 for devices... 1 USB Device(s) found
scanning bus usb@1c1d000 for devices... 1 USB Device(s) found
scanning bus usb@1c1d400 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Autoboot in 2 seconds, press <Space> to stop
=>
让我们测试一下网络是不是好使的,在uboot里配置以下环境变量, 网段按照实际情况自己改
setenv ipaddr 192.168.137.88
setenv gatewayip 192.168.137.1
setenv netmask 255.255.255.0
setenv serverip 192.168.137.221
saveenv
设置完成,重启,ping一下虚拟机。重启不用拔线,输入reset就行
ping通,显示如下
uboot 其他设置
我们启动uboot的时候,会发现大部分时间都花在了扫描usb口的启动介质上了,我们从网络启动不需要这个功能。我们能从打印日志里看到扫描USB之前有一个starting USB…字符串,直接在uboot源码里搜索这个字符串,找到如下
这个do_usb函数应该就是负责这项功能的,直接在函数开头return 0 即可。
源码改完之后记得编译再烧录。删除这项功能之后,uboot启动就快得多
U-Boot 2020.04 (Jun 03 2022 - 17:33:16 +0800) Allwinner Technology
CPU: Allwinner H3 (SUN8I 1680)
Model: Xunlong Orange Pi PC
DRAM: 1 GiB
MMC: mmc@1c0f000: 0
Loading Environment from FAT... OK
In: serial@1c28000
Out: serial@1c28000
Err: serial@1c28000
Net: phy interface0
eth0: ethernet@1c30000
Autoboot in 2 seconds, press <Space> to stop
=>
kernel
编译内核
打开linux源码顶层makefile,指定编译器和架构
CROSS_COMPILE ?= arm-none-linux-gnueabihf-
ARCH ?= arm
指定编译目标,开始编译
make sunxi_defconfig
make
报错
/bin/sh: 1: mkimage: not found
安装
sudo apt-get install u-boot-tools
我的电脑CPU是5800H, 分配6核心12线程,初次编译耗时不到两分钟,这个比香橙派的工具快很多。编译完成,虚拟机出现以下日志
我们需要的镜像zImage,设备树文件sun8i-h3-orangepi-pc.dtb都出现了
虚拟机安装tftp nfs服务
tftp服务用来加载zImage和设备树文件,nfs服务用来挂在网络文件系统,在这里就一起做了
TFTP
sudo apt-get install tftp-hpa tftpd-hpa xinetd
新建一个文件夹,tftp会将这个文件夹共享出去
mkdir ~/Desktop/netpi/tftpboot -p
sudo chmod 777 ~/Desktop/netpi/tftpboot
新建文件/etc/xinetd.d/tftp,输入以下内容,
server tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /home/winston/Desktop/netpi/tftpboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
修改/etc/default/tftpd-hpa文件内容为如下
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/winston/Desktop/netpi/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-l -c -s"
注意,以上两个配置文件中的文件夹路径,不可以使用~代替/home/user
启动服务
sudo service tftpd-hpa start
service --status-all | grep tftpd-hpa //查看服务tftpd-hpa是否开启
+号代表已启动,-号代表未启动
uboot加载测试
将zImage和设备树文件复制到~/Desktop/netpi/tftpboot里,去uboot里面输入
tftp 42000000 zImage //zImage复制到内存的42000000处
tftp 43000000 sun8i-h3-orangepi-pc.dtb //设备树复制到内存的43000000 处
正常的话,出现如下内容
tftp测试完毕,直接保存到bootcmd里
setenv bootcmd 'tftp 42000000 zImage; tftp 43000000 sun8i-h3-orangepi-pc.dtb; bootz 0x42000000 - 0x43000000'
saveenv
此时直接输入boot启动的话,你会在日志里看到如下错误
......
[ 1.830518] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
[ 1.838032] Please append a correct "root=" boot option; here are the available partitions:
......
[ 2.289431] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---
这是由于我们没有挂载根文件系统而导致的,挂载根文件系统需要nfs服务
NFS
nfs服务用于加载网络操作系统,network file system
在虚拟机里安装软件
sudo apt-get install nfs-kernel-server rpcbind
新建共享文件夹nfs,并在共享文件夹nfs里创建一个空文件text用于测试
mkdir ~/Desktop/netpi/nfs
chmod 777 ~/Desktop/netpi/nfs
修改配置文件/etc/exports, 末尾追加
/home/winston/Desktop/netpi/nfs *(rw,sync,no_root_squash)
因为uboot支持的是nfs2,ubuntu18默认不支持,所以我们要修改虚拟机的配置文件,使其支持nfs2。修改/etc/default/nfs-kernel-server为如下(删除了一些注释)
RPCNFSDCOUNT="-V 2 8"
RPCNFSDPRIORITY=0
RPCMOUNTDOPTS="-V 2 --manage-gids"
NEED_SVCGSSD=""
RPCSVCGSSDOPTS="--nfs-version 2,3,4 --debug --syslog"
测试一下
nfs 48000000 192.168.137.221:/home/winston/Desktop/netpi/nfs/text
rootfs
编译rootfs
nfs目录下创建rootfs文件夹,chmod 777 权限
修改busybox源码顶层Makefile,指定编译器和架构
指定为默认配置,进入menuconfig
make defconfig
make menuconfig
修改如下项目,注意,如要支持中文还需要改一下其他地方还有源码,但是我基本上用不到,所以就不改了。
正点原子将rootfs编译为动态库,并且复制了编译器的一些库文件进去。本文使用的编译器和正点原子使用的不同,我不知道照做会不会出问题,编译为静态库应该会省事。orangpi-pc是1GB的内存,足够放入静态库了。
Location:
-> Settings
-> Build static binary (no shared libs) //编译为静态库
-> vi-style line editing commands //选中
-> Linux Module Utilities
-> Simplified modutils //取消选中
编译,指定输出目录
make
make install CONFIG_PREFIX=/home/winston/Desktop/netpi/nfs/rootfs
这样就算成功了
在uboot里指定bootargs,启动看看
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.137.221:/home/winston/Desktop/netpi/nfs/rootfs,proto=tcp rw ip=192.168.137.88:192.168.137.221:192.168.137.1:255.255.255.0::eth0:off'
saveenv
成功的话,日志中会有如下
[ 6.165249] VFS: Mounted root (nfs filesystem) on device 0:14.
[ 6.171461] devtmpfs: error mounting -2
[ 6.176708] Freeing unused kernel memory: 1024K
[ 6.223892] Run /sbin/init as init process
[ 6.240688] random: fast init done
can't run '/etc/init.d/rcS': No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty4: No such file or directory
......
完善rootfs
可以看到,rootfs已经挂载成功了,但是devtmpfs和初始化好像有点问题,前者是因为我们根文件目录少创建了很多文件夹,后者参考正点原子解决。
在nfs/rootfs里创建其他文件夹
mkdir dev proc mnt sys tmp root etc
在/etc文件夹下新建如下文件
fstab内容如下
#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
/init.d/rcS内容如下,注意给权限
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
inittab内容如下
#etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
重启香橙派
[ 6.243956] Run /sbin/init as init process
[ 6.260700] random: fast init done
/etc/init.d/rcS: line 11: can't create /proc/sys/kernel/hotplug: nonexistent directory
Please press Enter to activate this console. [ 36.323836] vcc3v0: disabling
[ 36.326819] vcc5v0: disabling
[ 36.329783] cam500b-avdd: disabling
[ 36.333266] cam500b-dovdd: disabling
[ 36.336858] cam500b-dvdd: disabling
[ 36.340343] usb0-vbus: disabling
/ #
shell 可以用了,但是hotplug有问题,应该是内核没有开启相关功能
打开Device Drivers > Generic Driver Options > Support for uevent helper
[ 6.171445] ALSA device list:
[ 6.174437] No soundcards found.
[ 6.186098] VFS: Mounted root (nfs filesystem) on device 0:14.
[ 6.192365] devtmpfs: mounted
[ 6.196671] Freeing unused kernel memory: 1024K
[ 6.234093] Run /sbin/init as init process
[ 6.249850] random: fast init done
Please press Enter to activate this console.
/ #
/ #
/ #
/ #
好用了。
后记
担心的问题:
静态库好用不好用?我也不知道到此为止能不能证明静态库好用了,大佬们知道的可以在底下说一声。
我的疑问:
rootfs是在内核阶段挂载的,为什么uboot里要测试好不好使?如果在uboot里关闭nfs服务,系统还能正常运行吗?
文章资源在这里https://download.csdn.net/download/qq_42039294/85535963?spm=1001.2014.3001.5501
参考:
【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5
香橙派全志H3烧入U-boot和Linux内核以及配置
OrangePi_PC_H3_用户手册_v3.2.pdf
——END