OrangePi zero 最小软件系统构建过程记录 / 全志 SOC / WhyCan Forum(哇酷开发者社区) | 您所在的位置:网站首页 › 系统构建的过程 › OrangePi zero 最小软件系统构建过程记录 / 全志 SOC / WhyCan Forum(哇酷开发者社区) |
一下是我最近摸索构建一个最简单用于 OrangePi zero 的系统的过程,笔记是我从自己 OneNote 复制的,图片丢失,语言表述,格式等恐存在问题,见谅。也算踩了很多的坑,有些问题比较奇葩,网上搜索,qq群请教无果,最后也在本论坛上得到了帮助: https://whycan.cn/t_3243.html#p27998 也就把自己记录分享出来。 1. 大致流程 a. u-boot 编译,启用 ethernet 以太网,烧写到 sd 卡,验证 网络能用 b. 编译内核生成 zImage 和 dtb,放在开发机上的 tftp 目录, u-boot 端通过 tftp 下载内核和dt,并启动内核 c. 有了 u-boot 和 内核,还需要构建根文件系统 -- rootfs,使用 buildroot 构建, 并部署到开发机的 nfs 目录,避免重复插拔 sd 卡;u-boot 启动内核并通过 bootargs 传递 cmd line 给内核,内核通过nfs挂载rootfs。 d. 验证系统可用性 e. 烧写到 sd 卡 2. u-boot a. 源码 opz 和 友善 nanopi duo 都是用 h2+,orangepi 技术支持太糟糕,所以采用友善 nanopi h3 的源码: git clone https://github.com/friendlyarm/u-boot.git -b sunxi-v2017.x --depth 1 参考: http://wiki.friendlyarm.com/wiki/index.php/Building_U-boot_and_Linux_for_H5/H3/H2%2B b. 配置编译 i. 默认配置 1) make ARCH=arm nanopi_h3_defconfig 2) configs/ 下有几个 h2+ soc 相关的 a) orangepi_zero_defconfig 是 orangepi zero 的配置 b) nanopi_h3_defconfig 是 nanopi h3 的配置,但是兼容 h2+ 虽然我板子是 orangepi zero,但是这份源码是 友善修改过适配 h3 的,所以选择 nanopi_h3_defconfig 作为初始配置 ii. u-boot bootcmd 设置,bootcmd value : fatload mmc 0:1 ${scriptaddr} boot.scr; source ${scriptaddr} 这个 bootcmd 命令会在 u-boot 指定 boot 命令时执行,或者自动加载时执行(倒计时之后) 它做的事: 1) 从 mmc 0:1 分区,也就是 sd 卡 fat 分区(boot) 加载 boot.scr 文件到 内存,地址由环境变量 scriptaddr 决定 2) 执行boot.scr 脚本 3) boot.scr 后面我们会看到,它就是加载内核的 4) 所以,u-boot 能够移到内核,这一个命令起到了关键的作用 编译为 boot.scr mkimage -C none -A arm -T script -d boot.cmd boot.scr iii. 配置以太网卡 1) > Device Drivers > Network device support Allwinner Sun8i Ethernet MAC support 打勾 iv. 选择 u-boot dts 文件:不能使用 nanopi 的因为板级外设不同 Device Tree Control-> sun8i-h2-plus-orangepi-zero 注意不需要后缀 v. 保存配置文件 make ARCH=arm savedefconfig 会生成 defconfig 文件 mv defconfig configs/opz_defconfig vi. 编写编译脚本 rebuild.sh #!/bin/sh time make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 2>&1 | tee build.log vii. 编译 ./rebuild.h viii. 生成 u-boot-sunxi-with-spl.bin c. 烧写 u-boot i. 把 sd 读卡器接入 vmware 虚拟机 ii. 烧写u-boot 镜像 ls /dev/sd* 查看sd卡的磁盘标号 一般是 sdb,sdb1,sdb2 dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8sync && eject /dev/sdb d. 上电测试 i. 串口插上,查看日志 ii. 验证网卡 1) 插入网线到路由器 路由器网段 192.168.1.1/24 2) 设置关闭自动加载 setenv autoload no (不然dhcp会触发自动从tftp 加载,但是我们还没配置) 3) dhcp 正常的话,会输出 bound to ip地址的日志 4) ping 192.168.1.1 会显示 host is alive 3. tftp 配置 a. tftp 是 u-boot 支持的网络文件共享方式,用于从另一个PC下载文件 b. 配置 ubuntu 运行 tftp 服务端 i. vmware 里的 ubuntu 增加桥接网络 —— 虚拟机接入路由器,拥有独立ip,开发板才能通过ip地址访问到 ii. 安装配置 tftp 服务 https://www.davidsudjiman.info/2006/03/27/installing-and-setting-tftpd-in-ubuntu/ 1) sudo apt-get install xinetd tftpd tftp 2) 创建配置文件 /etc/xinetd.d/tftp service tftp { protocol = udp port = 69 socket_type = dgram wait = yes user = nobody server = /usr/sbin/in.tftpd server_args = /tftpboot disable = no } 3) 创建共享目录 /tftpboot $ sudo mkdir /tftpboot $ sudo chmod -R 777 /tftpboot $ sudo chown -R nobody /tftpboot 4) 启动服务 $ sudo /etc/init.d/xinetd start 5) 在 /tftpboot 放置测试文件 touch /tftpboot/hello c. 在 u-boot 命令行,测试 tftp i. 服务端地址环境变量设置 setenv serverip 192.168.1.76 ii. tftp 0x41000000 hello 日志显示下载到文件 4. linux 内核 a. 源码 opz 和 友善 nanopi duo 都是用 h2+,orangepi 技术支持太糟糕,所以采用友善 nanopi h3 的源码: git clone https://github.com/friendlyarm/linux.git -b sunxi-4.14.y --depth 1 参考: http://wiki.friendlyarm.com/wiki/index.php/Building_U-boot_and_Linux_for_H5/H3/H2%2B 源码版本比荔枝派源码更新 b. 选择基础配置 i. 只有 sunxi_defconfig 可选 make ARCH=arm sunxi_defconfig c. 配置内核 make ARCH=arm menuconfig i. System Type ii. Device Drivers > Network device support > Ethernet driver support 为什么全志的网卡跟 ST 是关联的? iii. File Systems > Network File Systems 使能 nfs d. 保存配置 make ARCH=arm savedefconfig mv defconfig arch/arm/configs/opz_defconfig e. 创建编译脚本, 编译完成,拷贝镜像文件到 result_image/ 目录,方便导出 #!/bin/sh make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16 &&\ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16 INSTALL_MOD_PATH=out modules &&\ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16 INSTALL_MOD_PATH=out modules_install &&\ mkdir ./result_image -p &&\ cp arch/arm/boot/zImage ./result_image &&\ cp arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dtb ./result_image/opz.dtb f. 编译 ./rebuild.sh g. 在 result_image/ 生成了 zImage 和 opz.dtb, dtb 复制的是orangepi-zeror 的与开发板对应 h. 测试 uboot tftp 加载内核 i. u-boot 正常的启动流程 1) boot.cmd 会被编译成 boot.scr,存放在sd 卡 boot 分区里 2) u-boot 环境变量 bootcmd,上一节提到的,它的作用就是去sd卡上加载 boot.scr 并执行 3) boot.cmd -> boot.scr #boot.scr setenv bootargs console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk2p2 rootfstype=ext4 earlyprintk rw load mmc 0:1 0x41000000 zImage load mmc 0:1 0x41800000 opz.dtb bootz 0x41000000 - 0x41800000 第一行设置的是 bootargs 环境变量,是传递给内核的参数 第二行从mmc0 分区1 也就是 mmcblk0p1 加载 zImage 文件到内存 0x41000000 地址处,也就是把zImage 从 sd卡 boot 分区拷贝到内存 第三行把 opz.dtb 加载到内存 0x41800000 地址处 第四行,跳转到 0x41000000 运行内核,也就是启动 linux 内核, u-boot 会把 bootargs 的值传给内核 mkimage -C none -A arm -T script -d boot.cmd boot.scr ii. 改用 tftp 启动 上面我们摸清了 u-boot 从sd卡的引导内核的流程,下面我用 tftp 的方式来代替 1) 设置 bootargs 原来 bootargs 是在 boot.scr 脚本里设置的,当然我们也可以通过 tftp 加载 boot.scr;不过,这种情况,直接设置 bootargs 环境变量即可: => setenv bootargs console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk2p2 rootfstype=ext4 earlyprintk rw => saveenv # 没有改变,只是手动设定,并保存 2) 设置 bootcmd 环境变量 我们不需要 boot.scr 了,所以,bootcmd 可以直接代替 boot.scr 的功能 => setenv bootcmd tftp 0x41000000 zImage; tftp 0x41800000 opz.dtb; bootz 0x41000000 - 0x41800000 => saveenv 1) 加载 zImage, 从 serverip:/tftpboot/ 下载 zImage 2) 加载 dtb, 从 serverip:/tftpboot/ 下载 opz.dtb 3) 启动内核 3) 启动,执行boot 命令,则会执行 bootcmd 并, 传递 bootargs boot 4) linux 下 tftp命令 : tftp 192.169.1.76 -g -r zImage -l zImage 5. 根文件系统 —— 使用 buildroot 构建根文件系统 a. buildroot 源码 https://buildroot.org/download.html https://buildroot.org/downloads/buildroot-2019.02.7.tar.gz git clone git://git.buildroot.net/buildroot -b 2019.02.x buildroot 不光可以构建根文件系统,还可以连内核,uboot 一键构建,最主要是用来把系统依赖的软件包打包进去根文件系统 b. 配置 make ARCH=arm menuconfig i. Target options ii. Toolchain 1) 使用外部工具链: buildroot 可以支持内建交叉工具链(连工具链都给你准备好了 ?),但是我们这里使用跟编译u-boot 和 内核相同的外部工具链就可以 2) Custom toolchain 自定义的工具链 3) 工具链路径 /opt/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/ 4) 工具链前缀 arm-linux-gnueabihf 5) 工具链 gcc 版本 6.x 查看工具链目录就知道 6) 头文件版本,查看 cat /opt/gcc-linaro-6.3.1-2017.05-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) ms dos blablabla -> * iv. 恢复 u-boot bootcmd 默认引导 setenv bootcmd "load mmc 0:1 ${scriptaddr} boot.scr; source ${scriptaddr}" fatload 改为 load , load 支持其他格式文件系统 v. 调试技巧 1) 从 tftp 加载 boot.scr,并启动 setenv bootcmd "tftp ${scriptaddr} boot.scr; source ${scriptaddr}" saveenv boot 2) 从 tftp 更新 zImage setenv bootcmd "tftp ${scriptaddr} boot.scr; source ${scriptaddr}" setenv serverip 192.168.1.76 setenv ipaddr 192.168.1.172 tftp 命令需要先设置好ip 3) 在linux系统里从 tftp 下载文件 tftp -g -r boot-mmc.scr 192.168.1.76 8. 内核模块拷贝进入根文件系统 a. 内核编译生成目录 i. 编译模块 make ARCH=arm modules ii. 安装模块 INSTALL_MOD_PATH 指定安装的目录,我们安装到源码目录下 make INSTALL_MOD_PATH=out modules_install iii. 得到 out/lib/modules/4.14.111-g08b7e83/ b. 拷贝 一般编译的是时候,文件系统没有挂载到主机上,所以需要多一步 把 p2 挂载到 /mnt,再把上一步生成的目录拷贝到目标根文件系统上。 sudo mkdir -p /mnt/lib/modules/$VERSION/ &&\ sudo cp modules/* /mnt/lib/modules/$VERSION -r &&\ $VERSION 是目标内核的版本号 通过 uname -r 查看 c. 疑问 i. 文件夹的名字需要改么,生成的 modules 带后缀 https://unix.stackexchange.com/questions/231500/difference-between-lib-module-uname-r-and-sys-module -需要相同 ii. 内核模块安装错误 appledisplay: version magic '4.14.111-g08b7e83 SMP mod_unload ARMv7 p2v8 ' should be '4.14.111-g25f7b00-dirty SMP mod_unload ARMv7 p2v8 ' 编译版本和运行版本不是一样的 http://billauer.co.il/blog/2013/10/version-magic-insmod-modprobe-force/ 1) include/generated/utsrelease.h 里记录了自动生成的版本号 2) include/linux/vermagic.h 决定了随机的版本号 3) 编译菜单 General setup -> Automatically append version information to version string 去勾选,会去掉 版本后面的随机串,但是最后有个加号 4) 加号来源是版本控制系统,当前版本处于改动中就会自动附上+ http://smilejay.com/2012/07/kernel-version-plus-sign/ iii. 内核如何决定是否使用 这些模块,开机使用还是需要手动 应该是在内核使用到相应的功能时,会自动去查找安装 最近编辑记录 kernelpanic (2019-11-19 15:03:22) |
CopyRight 2018-2019 实验室设备网 版权所有 |