OrangePi-3B 系列笔记:
- OrangePi-3B 折腾笔记 —— 认识开发板
- OrangePi-3B 折腾笔记 —— 准备构建环境
- OrangePi-3B 折腾笔记 —— 构建 U-Boot
- OrangePi-3B 折腾笔记 —— 构建 Kernel
- OrangePi-3B 折腾笔记 —— 点亮 LCD 屏幕
- OrangePi-3B 折腾笔记 —— 移植 WiFi & BT 驱动
- OrangePi-3B 折腾笔记 —— 构建文件系统镜像
温馨提示:
- OrangePi-3B 硬件版本 V1.1.1 的板子出现过有线网卡“无故”失灵的故障, 所以在进行操作前请确认开发板工作良好(修复这个问题需要更换 RK3566 芯片).
https://www.bilibili.com/read/cv33224126- 香橙派目前已经推出了硬件版本为 V2.1 的 OrangePi-3B, 有线网卡供应商更换为 RTL. 本系列文章没有针对 V2.1 的板子做过适配, 请根据实际情况操作(同时强烈谴责此种不负责任的行为, 如考虑购买此型号板子商用, 建议换个型号避坑).
- 本系列文章最后更新时间: 2024年11月02日.
编译环境
- 主板: OrangePi-3b_V1.1.1
- 芯片: RK3566
- 环境: Debian:12_x86_64(Docker)
内容说明
把 U-Boot
搞到差不多了,现在转战 Kernel
。
和 U-Boot
类似,OrangePi-3B
的 Kernel
供应商正经的也有三家:
- OrangePi
板子供应商,有最贴合板子的适配,拿来即用,版本有5.10
和6.1
可选; - Rockchip
芯片供应商,有比较贴合芯片的适配,但没有板子相关的适配,版本只有5.10
,是OrangePi
的5.10
Kernel
的上游。 - Mainline
主线内核,瑞芯微会不定时向主线合入对芯片的适配代码。支持度一般,但版本不受限制。
三种开源 Kernel
构建类似,但 Rockchip
和 OrangePi
提供了构建脚本,以下内容以主线 Kernel
为主。
构建
OrangePi
克隆代码
cd ~/projects/
git clone https://github.com/orangepi-xunlong/linux-orangepi.git -b orange-pi-5.10-rk35xx kernel_orangepi
启动容器
docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
- 关于镜像
build-linux
的内容请参考之前的笔记,其中已经安装构建所需要的软件包。
启动编译
cd /projects/kernel_orangepi/
# 清除缓存[可选]
rm -rf out
make ARCH=arm64 clean
make ARCH=arm64 mrproper
make ARCH=arm64 distclean
# 清除缓存[可选]
rm -rf out
make ARCH=arm64 O=out clean
make ARCH=arm64 O=out mrproper
make ARCH=arm64 O=out distclean
# 应用配置
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out defconfig
# 图形化配置
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out menuconfig
# 编译
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out -j8
构建产物
vmlinux
Linux
内核编译出来的原始的内核文件,未做压缩处理的elf
格式;arch/arm64/boot/Image
使用objcopy
处理vmlinux
后生成的二进制内核映像;arch/arm64/boot/Image.lz4
使用lz4
压缩Image
后生成的压缩文件(不带自解压头),ARM
的U-Boot
默认支持这种格式并且U-Boot
负责解压内核;arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtb
设备树文件;
Rockchip
克隆代码
cd ~/projects/
git clone https://github.com/rockchip-linux/kernel.git -b develop-5.10 kernel_rockchip
启动容器
docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
- 关于镜像
build-linux
的内容请参考之前的笔记,其中已经安装构建所需要的软件包。
启动编译
cd /projects/kernel_rockchip/
# 清除缓存[可选]
rm -rf out
make ARCH=arm64 clean
make ARCH=arm64 mrproper
make ARCH=arm64 distclean
# 构建镜像
./make.sh CROSS_COMPILE=aarch64-linux-gnu- orangepi-3b-rk3566
- 使用
make.sh
可以快捷编译,也支持使用make
命令编译;make.sh
能够生成ATF
镜像。Rockchip
的Kernel
源码中没有包含OrangePi-3B
的设备树和配置,需要从OrangePi
的Kernel
中移植。
构建产物
vmlinux
Linux
内核编译出来的原始的内核文件,未做压缩处理的elf
格式;boot.img
编译脚本ATF
处理过的内核镜像,需要配合OrangePi
的U-Boot
启动;arch/arm64/boot/Image
使用objcopy
处理vmlinux
后生成的二进制内核映像;arch/arm64/boot/Image.lz4
使用lz4
压缩Image
后生成的压缩文件(不带自解压头),ARM
的U-Boot
默认支持这种格式并且U-Boot
负责解压内核;arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtb
设备树文件;
Mainline
克隆代码
cd ~/projects/
git clone https://github.com/torvalds/linux.git -b linux-rolling-stable kernel
- 使用滚动的稳定版本分支;
启动容器
docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
- 关于镜像
build-linux
的内容请参考之前的笔记,其中已经安装构建所需要的软件包。
设备树
板子的设备树拷贝的大名鼎鼎 Armbian
的源文件:
cd /projects/kernel/
# 下载设备树文件
DTS_URL=https://raw.githubusercontent.com/armbian/build/main/patch/kernel/archive/rockchip64-6.9/dt/rk3566-orangepi-3b.dts
wget ${DTS_URL} -O arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dts
实测适配 EMMC
模块不太稳定,在此基础上做了一点调整:
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dts b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dts
index ac4822641039..d2183ba0eee3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dts
@@ -724,11 +724,13 @@ &saradc {
};
&sdhci {
- bus-width = <8>;
- max-frequency = <200000000>;
+ max-frequency = <150000000>;
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
non-removable;
pinctrl-names = "default";
- pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>;
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe>;
status = "okay";
};
- 将频率从
200MHz
降到150MHz
;
配置文件
我这没有抄作业,新建了一个基础的配置文件,命名为 arch/arm64/configs/orangepi-3b.config
,用于修改 defconfig
配置:
#
# General setup
#
CONFIG_LOCALVERSION_AUTO=y
CONFIG_LOCALVERSION="-orangepi-3b"
#
# Platform selection
#
# CONFIG_ARCH_ACTIONS is not set
# CONFIG_ARCH_SUNXI is not set
# CONFIG_ARCH_ALPINE is not set
# CONFIG_ARCH_APPLE is not set
# CONFIG_ARCH_BCM is not set
# CONFIG_ARCH_BCM2835 is not set
# CONFIG_ARCH_BCMBCA is not set
# CONFIG_ARCH_BCM_IPROC is not set
# CONFIG_ARCH_BERLIN is not set
# CONFIG_ARCH_BRCMSTB is not set
# CONFIG_ARCH_EXYNOS is not set
# CONFIG_ARCH_K3 is not set
# CONFIG_ARCH_LAYERSCAPE is not set
# CONFIG_ARCH_LG1K is not set
# CONFIG_ARCH_HISI is not set
# CONFIG_ARCH_KEEMBAY is not set
# CONFIG_ARCH_MEDIATEK is not set
# CONFIG_ARCH_MESON is not set
# CONFIG_ARCH_MVEBU is not set
# CONFIG_ARCH_NXP is not set
# CONFIG_ARCH_MXC is not set
# CONFIG_ARCH_NPCM is not set
# CONFIG_ARCH_QCOM is not set
# CONFIG_ARCH_RENESAS is not set
CONFIG_ARCH_ROCKCHIP=y
# CONFIG_ARCH_S32 is not set
# CONFIG_ARCH_SEATTLE is not set
# CONFIG_ARCH_INTEL_SOCFPGA is not set
# CONFIG_ARCH_SYNQUACER is not set
# CONFIG_ARCH_TEGRA is not set
# CONFIG_ARCH_TESLA_FSD is not set
# CONFIG_ARCH_SPRD is not set
# CONFIG_ARCH_THUNDER is not set
# CONFIG_ARCH_THUNDER2 is not set
# CONFIG_ARCH_UNIPHIER is not set
# CONFIG_ARCH_VEXPRESS is not set
# CONFIG_ARCH_VISCONTI is not set
# CONFIG_ARCH_XGENE is not set
# CONFIG_ARCH_ZYNQMP is not set
#
# Soc drivers
#
# CONFIG_ROCKCHIP_PX30 is not set
# CONFIG_ROCKCHIP_RK3036 is not set
# CONFIG_ROCKCHIP_RK3066 is not set
# CONFIG_ROCKCHIP_RK3128 is not set
# CONFIG_ROCKCHIP_RK3188 is not set
# CONFIG_ROCKCHIP_RK322X is not set
# CONFIG_ROCKCHIP_RK3288 is not set
# CONFIG_ROCKCHIP_RK3308 is not set
# CONFIG_ROCKCHIP_RK3328 is not set
# CONFIG_ROCKCHIP_RK3368 is not set
# CONFIG_ROCKCHIP_RK3399 is not set
CONFIG_ROCKCHIP_RK3568=y
# CONFIG_ROCKCHIP_RK3588 is not set
# CONFIG_ROCKCHIP_RV1108 is not set
# CONFIG_ROCKCHIP_RV1126 is not set
网络 & NFS
配置
如果要挂载 NFS
为 rootfs
,需要启动网卡。除了要修改设备树之外重点要打开 DWMAC
的配置(让我一顿好找):
#
# Wired NIC driver
#
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
CONFIG_DWMAC_GENERIC=y
CONFIG_DWMAC_ROCKCHIP=y
#
# Network FileSystem Support
#
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V2=y
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_NFS_SWAP=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
CONFIG_NFS_V4_1_MIGRATION=y
CONFIG_NFS_V4_SECURITY_LABEL=y
CONFIG_NFS_USE_LEGACY_DNS=y
CONFIG_NFS_USE_KERNEL_DNS=y
CONFIG_NFS_DISABLE_UDP_SUPPORT=y
CONFIG_NFS_V4_2_READ_PLUS=y
CONFIG_PNFS_FILE_LAYOUT=y
CONFIG_PNFS_BLOCK=y
CONFIG_PNFS_FLEXFILE_LAYOUT=y
CONFIG_ROOT_NFS=y
启动编译
cd /projects/kernel/
# 清除缓存[可选]
rm -rf out
make ARCH=arm64 O=out clean
make ARCH=arm64 O=out mrproper
make ARCH=arm64 O=out distclean
# 应用配置
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out defconfig orangepi-3b.config
# 图形化配置
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out menuconfig
# 编译
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out -j8
# 单编内核
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out Image.gz -j8
# 单编设备树
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out dtbs -j8
# 单编模块
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out modules -j8
# 联合编译
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out Image.gz dtbs modules -j8
# 导出模块(自定义输出路径)
rm -rf out/lib/modules/
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out INSTALL_MOD_PATH=. INSTALL_MOD_STRIP=1 modules_install -j8
# 查看内核签名版本
# out/include/generated/utsrelease.h
make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 O=out kernelrelease
- 使用
make
的O=out
参数重定向的编译输出产物的目录为out
。- 构建配置文件时带上交叉编译链,不然启动编译时会有编译选项需要手动确认。
- 细节配置可以参考
armbian-build
仓库main
分支中的config/kernel/linux-rockchip*
配置文件。- 其中一个
cpio
依赖的问题让我迷茫好一阵: https://github.com/Frogging-Family/linux-tkg/issues/147;
编译产物
out/vmlinux
Linux
内核编译出来的原始的内核文件,未做压缩处理的elf
格式;out/arch/arm64/boot/Image
使用objcopy
处理vmlinux
后生成的二进制内核映像;out/arch/arm64/boot/Image.gz
使用gzip
压缩Image
后生成的压缩文件(不带自解压头),ARM
的U-Boot
默认支持这种格式并且U-Boot
负责解压内核;out/arch/arm64/boot/dts/rockchip/rk3566-orangepi-3b.dtb
设备树文件;out/lib/modules/*
内核模块,需要整合进rootfs
或initramfs
系统功能才会完整(比如网络);
针对 OrangePi 3B
的改动记录
https://github.com/lx0758/linux/commits/orangepi-3b/
调试
在没有文件系统的情况下可以通过 U-Boot
走 NFS
协议远程加载 Kernel
测试。
# 挂载 NFS 为 ROOTFS
setenv bootargs "earlycon console=ttyS2,1500000n8 root=/dev/nfs ro nfsroot=192.168.8.13:/home/liux/projects/buildfs/rootfs/,vers=4 ip=dhcp rootwait"
# 通过 NFS 加载 Kernel
setenv ipaddr 192.168.8.21
nfs 0x4000000 192.168.8.13:/home/liux/projects/buildfs/rootfs/boot/Image.gz
nfs 0x2000000 192.168.8.13:/home/liux/projects/buildfs/rootfs/boot/initramfs.img
nfs 0x1000000 192.168.8.13:/home/liux/projects/buildfs/rootfs/boot/dts/rockchip/rk3566-orangepi-3b.dtb
booti 0x4000000 0x2000000 0x1000000
U-Boot
的 NFS 协议只能支持2
,为了兼容给NFS
服务器的3
协议关了。但是Kernel
使用NFS
的默认协议是3
,这里强制指定为4
。- 还有种设置写法:
nfsroot=192.168.8.13:/home/liux/projects/buildfs/rootfs/,proto=tcp,v4,rw
。