制作根文件系统 rootfs
获取buildroot
我使用了buildroot-2022.11最终版本,文件地址是
http://buildroot.uclibc.org/downloads/buildroot-2022.11.tar.xz
下载后解压到 .../v3s/buildroot 目录下。
配置buildroot
cd .../v3s/buildroot
make licheepi_zero_defconfig
make menuconfig
开始配置buildroot。
Target options
设置好的Target options如下截图。
Toolchain
配置好的Toolchain选项如下图所示。我使用外部编译工具的配置,请注意External toolchain gcc version为6.x,External toolchain kernel headers series 是 4.6.x。
使用如下方法获得External toolchain kernel headers series的值。
cat /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/linux/version.h
#define LINUX_VERSION_CODE 263680
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
看到 LINUX_VERSION_CODE 的值为263680,等于十六进制数 0x040600,可得到其点分割格式的值为 4.6.0。
C library 仍然选用 glibc,使用uclibc可减小根文件系统的尺寸,但必须自行编译uclibc,我就没有再去折腾。
必须选中 Toolchain has C++ support。
Build options
配置好的 Build options 如下图。请注意三点:
- Location to save buildroot_config 我使用了绝对路径,这样保险一些。
- 选中 [*] strip target binaries,以减小rootfs的尺寸。
- gcc optimization level 使用 optimize for size,理由同上。
其它的选项没有做修改。
System configuration
配置好的 System configuration 选项如下图所示。
- System hostname,为主机起一个名字,运行时可用 hostname 命令显示出来。
- Init system 使用 Busybox
- 选中 [*] Enable root login with password,然后为root设置一个密码
- busybox‘ default shell 使用 /bin/sh,如果没有特别需求,也可以选择 bash
- 选中 [*] Purge unwanted locales
- 选中 [*] Install timezone info,设置 default local time为 Aisa/Shanghai
Kernel清空,Bootloaders清空
已经单独编译了u-boot和linux kernel,就不需要 buildroot 再次编译内核和bootloader了。
Target packages
考虑到应用的需要,这里只列出我所需要的选项,其余我都清空了。
- Libraries -> Compression and decompression 选中 zlib support。
- Libraries -> Crypto,选中 openssl support。
- Libraries -> Database,选中 sqlite。
- Networking applications,选中 dropbear,选择 client program, optimize for size
- Networking applications,选中 ifupdown scripts
- Networking applications,选中 ntp,选择 ntpdate 即可
Filesystem images
选择 ext2/3/4 root filesystem 和 tar the root filesystem。
配置Busybox
使用
sudo make busybox-menuconfig
配置busybox。之所以使用sudo是因为在我的开发环境中,没有sudo的话会出错。
使用默认配置可以满足绝大多数情况的需要。
保存退出 busybox-menuconfig 以后,要执行如下指令,使之生效。
sudo make busybox-menuconfig
sudo make busybox-update-config
编译
make -j16
# or use
# sudo make -j16
我使用了sudo。
期间需要下载应用软件包,如果下载失败,可以使用迅雷等软件将下载链接的文件事先下载好,拷贝到.../v3s/buildroot/dl 目录下,然后继续 make,buildroot 会自动识别。
编译完成后,在 .../v3s/buildroot/output/images 目录下生成三个文件:rootfs.ext2,rootrs.ext4和rootfs.tar,其中rootfs.tar就是我们所需要的。
制作flashimg.bin
为了方便,创建了一个新的文件夹 .../v3s/target,将所需文件全部都拷贝到这个文件夹中,文件列表如下:
- u-boot-sunxi-with-spl.bin,编译好的 u-boot 可执行映像
- sun8i-v3s-licheepi-zero.dtb 和 sun8i-v3s-licheepi-zero-dock.dtb,编译好的设备树
- zImage,编译好的 linux 内核
- rootfs.tar,编译好的根文件系统压缩包
我又编写了一个mkimg脚本,内容如下。
#!/bin/bash
if [ ! -e rootfs.tar ]; then
echo "Need rootfs.tar"
exit -1
fi
echo "Extracting rootfs..."
if [ ! -d rootfs ]; then
mkdir rootfs
fi
cd rootfs; rm -rf *; tar -xvf ../rootfs.tar > /dev/null 2>&1; cd ..
echo "Preparing customer-tailored scripts..."
cp template/etc/network/interfaces rootfs/etc/network/interfaces
rm -f rootfs/etc/resolv.conf
cp template/etc/resolv.conf rootfs/etc/resolv.conf
cp template/etc/profile.d/dir.sh rootfs/etc/profile.d/dir.sh
rm -f rootfs/etc/localtime
cp template/etc/localtime rootfs/etc/localtime
echo "Making jffs..."
mkfs.jffs2 -s 0x100 -e 0x10000 -p 0x1AF0000 -d rootfs/ -o jffs2.img
echo "Making flash image..."
dd if=/dev/zero of=flashimg.bin bs=1M count=32
dd if=u-boot-sunxi-with-spl.bin of=flashimg.bin bs=1K conv=notrunc
dd if=sun8i-v3s-licheepi-zero-dock.dtb of=flashimg.bin bs=1K seek=1024 conv=notrunc
dd if=zImage of=flashimg.bin bs=1K seek=1088 conv=notrunc
dd if=jffs2.img of=flashimg.bin bs=1K seek=5184 conv=notrunc
echo "Transtoring images..."
cp flashimg.bin $TFTP_ROOT/.
scp flashimg.bin fileserver:~/../smbshare/Buffer/flashimg.0531.bin
echo "[Done]"
exit 0
脚本的最后一段是将 flashimg.bin 文件拷贝到了 TFTP 服务器中以备下载使用。
烧录
将核心板的 uart0 和上位机连接好,在上位机打开 secureCRT 窗口,然后将核心板上电,当出现进入 u-boot 提示时,打回车键,进入到 u-boot,然后使用如下命令将 flashimg.bin 烧录到 Flash 中。
setenv serverip 192.168.0.104
setenv ipaddr 192.168.0.101
tftp 0x41800000 flashimg.bin
sf probe 0
sf update 0x41800000 0 0x2000000
setenv bootargs console=ttyS0,115200 earlyprintk panic=5 rootwait mtdparts=spi0.0:1M(uboot)ro,64k(dtb)ro,5M(kernel)ro,-(rootfs) root=31:03 rw rootfstype=jffs2
setenv bootcmd=sf probe 0; sf read 0x41800000 0x100000 0x10000; sf read 0x41000000 0x110000 0x500000; bootz 0x41000000 - 0x41800000
我这里使用的 ip 地址段是 192.168.0.x,根据网络环境分配具体的 ip 地址。
待上述命令全部正确执行后,打入 boot 命令,一切顺利的话,就可以正常启动了。
总结
为了正确地驱动超过 16MB 的 SPI-NOR flash,使用 SPI-NOR flash 启动V3s核心板,需注意以下的要点:
- 事先做好 flash 的分区,按照分区计算好 u-boot 的 bootargs 和 bootcmd.
- 修改 ./u-boot/arch/arm/dts/sun8i-v3s-licheepi-zero.dts 和 ./u-boot/arch/arm/dts/sun8i-v3s.dts 设置好 spi,emac 节点以使 u-boot 支持 SPI Flash 和 网络。
- 修改 linux kernel 的设备树,增加所使用的 flash 型号。
- linux-4.13.y 编译后的尺寸小于4M,linux-5.2.y 的尺寸大于4M