RK3528 Armbian系统 移植 树莓派 欧拉22系统

项目开发需要 欧拉22 SP4的 ARM64开发环境,X86-64 QEMU 模拟 ARM64 C/C++ 项目编译速度 性能慢到怀疑人生(而且还是纯终端无桌面版,就这么慢)。

偏逢 镁光、尔必达等 存储涨价,价格已经涨到天际。

大内存的树莓派 非常非常贵!!!

海鲜市场 找到 一款块 ARM64 电视盒子设备,RK3528A(瑞芯微) + 4G(DDR镁光) + 128G(EMMC三星) 100来块还包邮。

移植ARM64欧拉22 开干!!!

固件:RK3528 麻雀云PCDN镜像 网上自己下载。不要下载有锁版固件!

固件:树莓派 openEuler22 官网有下载地址。

树莓派 openEuler → RK3528 移植流程

输入:

  • RK3528-x88pro13.img — RK3528 麻雀云PCDN镜像 (Armbian, Kernel 6.1.141)
  • openEuler-22.03-LTS-SP4-raspi-aarch64.img — 树莓派 openEuler 镜像

输出:

  • 一个新的 IMG,烧录到 RK3528 开发板即可运行 openEuler

核心原理

1
最终 IMG = RK3528 引导链 + RK3528 内核 + RK3528 DTB + openEuler rootfs
  • 树莓派 Broadcom 引导链/内核/DTB 全部丢弃
  • 树莓派 rootfs (ARM64 用户态) 可以直接在 RK3528 上运行
  • 内核模块必须匹配运行的内核 (6.1.141-rk35xx-ophub)

步骤 1: 环境准备

1
2
3
4
5
6
# 安装必要工具
dnf install -y uboot-tools rsync

# 设置工作目录
WORKDIR=/root/rk3528
cd $WORKDIR

步骤 2: 挂载两个源镜像

1
2
3
4
5
6
7
8
# RK3528 原厂镜像
losetup -f -P --show $WORKDIR/RK3528-x88pro13.img # → /dev/loop0
mount /dev/loop0p1 /mnt/rk3528-p1 # boot 分区
mount /dev/loop0p2 /mnt/rk3528-p2 # rootfs 分区

# 树莓派 openEuler 镜像
losetup -f -P --show $WORKDIR/openEuler-22.03-LTS-SP4-raspi-aarch64.img # → /dev/loop1
mount /dev/loop1p3 /mnt/oe-p3 # rootfs 分区 (p3)

步骤 3: 创建新的 IMG 文件

1
2
3
4
5
6
cp $WORKDIR/RK3528-x88pro13.img $WORKDIR/rk3528-openeuler22.img
# 新镜像保留了 RK3528 的: GPT分区表 + 引导链(前16MB) + p1(boot) + p2(空rootfs)

losetup -f -P --show $WORKDIR/rk3528-openeuler22.img # → /dev/loop2
mount /dev/loop2p1 /mnt/new-p1
mount /dev/loop2p2 /mnt/new-p2

步骤 4: 替换 rootfs

1
2
3
4
5
6
7
8
9
10
# 清空 p2
rm -rf /mnt/new-p2/*

# 拷贝 openEuler rootfs
rsync -a /mnt/oe-p3/ /mnt/new-p2/

# 验证
cat /mnt/new-p2/etc/os-release
# NAME="openEuler"
# VERSION="22.03 (LTS-SP4)"

步骤 5: 安装 RK3528 内核模块

1
2
3
4
5
6
7
# 拷贝模块
cp -a /mnt/rk3528-p2/usr/lib/modules/6.1.141-rk35xx-ophub \
/mnt/new-p2/usr/lib/modules/

# 删除树莓派 Broadcom 模块 (不删也没事,但浪费空间)
rm -rf /mnt/new-p2/usr/lib/modules/5.10.*
rm -rf /mnt/new-p2/usr/lib/modules/6.6.*

步骤 6: 配置 /etc/fstab

1
2
3
4
5
6
7
8
9
10
# 获取分区 UUID
UUID_BOOT=$(blkid /dev/loop2p1 -s UUID -o value)
UUID_ROOT=$(blkid /dev/loop2p2 -s UUID -o value)

cat > /mnt/new-p2/etc/fstab << EOF
UUID=${UUID_BOOT} /boot ext4 defaults,noatime 0 1
UUID=${UUID_ROOT} / ext4 defaults,noatime 0 0
tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev 0 0
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,nodev 0 0
EOF

步骤 7: 配置串口登录 (headless)

1
2
3
4
5
6
# 启用 serial-getty@ttyS2 (RK3528 调试串口)
ln -sf /usr/lib/systemd/system/serial-getty@.service \
/mnt/new-p2/etc/systemd/system/getty.target.wants/serial-getty@ttyS2.service

# 删除 tty1 (无显示器)
rm -f /mnt/new-p2/etc/systemd/system/getty.target.wants/getty@tty1.service

步骤 8: 配置网络 (静态 IP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 删除树莓派遗留的无效配置
rm -f /mnt/new-p2/etc/sysconfig/network-scripts/ifcfg-eth0
rm -f /mnt/new-p2/etc/NetworkManager/system-connections/*

# 写入静态 IP (NM keyfile 格式)
mkdir -p /mnt/new-p2/etc/NetworkManager/system-connections
cat > /mnt/new-p2/etc/NetworkManager/system-connections/eth0.nmconnection << 'EOF'
[connection]
id=eth0
type=ethernet
interface-name=eth0
autoconnect=true
autoconnect-priority=100

[ipv4]
method=manual
addresses=192.168.1.1/24

[ipv6]
method=disabled
EOF
chmod 600 /mnt/new-p2/etc/NetworkManager/system-connections/eth0.nmconnection

步骤 9: 修复 boot.scr (去掉 splash 防 plymouthd 占 CPU)

1
2
3
4
5
6
7
8
9
10
11
12
# 编辑 boot.cmd 源码: 删除两行 splash
sed -i 's/setenv consoleargs "splash plymouth.ignore-serial-consoles ${consoleargs}"/setenv consoleargs "${consoleargs}"/' \
/mnt/new-p1/boot.cmd
sed -i 's/setenv consoleargs "splash=verbose ${consoleargs}"/setenv consoleargs "${consoleargs}"/' \
/mnt/new-p1/boot.cmd

# 重新编译 boot.scr
rm -f /mnt/new-p1/boot.scr
mkimage -C none -A arm -T script -d /mnt/new-p1/boot.cmd /mnt/new-p1/boot.scr

# 验证
strings /mnt/new-p1/boot.scr | grep splash # 应无输出

步骤 10: 修改 armbianEnv.txt (内核参数)

1
2
3
4
5
6
7
8
9
10
11
# 检查当前 armbianEnv.txt
cat /mnt/new-p1/armbianEnv.txt

# 修改 extraargs 行,追加三个参数:
# plymouth.enable=0 — 防止 initrd 启动 plymouth
# net.ifnames=0 — 强制网口叫 eth0 (不被 udev 改为 end1)
sed -i 's/^extraargs=.*/& plymouth.enable=0 net.ifnames=0/' /mnt/new-p1/armbianEnv.txt

# 验证
grep extraargs /mnt/new-p1/armbianEnv.txt
# extraargs=rw rootwait plymouth.enable=0 net.ifnames=0

步骤 11: 删除 dracut plymouth 模块

1
2
rm -rf /mnt/new-p2/usr/lib/dracut/modules.d/50plymouth
# 防止日后 dracut 重建 initramfs 时把 plymouth 打进去

步骤 12: 设置 root 密码和主机名

1
2
3
4
5
6
7
8
# 主机名
echo "rk3528-openeuler" > /mnt/new-p2/etc/hostname
echo "127.0.0.1 rk3528-openeuler" >> /mnt/new-p2/etc/hosts

# root 密码 (SHA-512 hash)
# 用 python3 生成: python3 -c "import crypt; print(crypt.crypt('openeuler', crypt.mksalt(crypt.METHOD_SHA512)))"
HASH='$6$CYTrNEriJxNCKLvI$0nW4Eq5Zr/HzOgVZk9prFFUNkDjK08ZPMdJWmU1W4QZ4DkGI0Frp5jFdFUC6vbmLQ2AfI/SfIjB1Tw9g89xSs0'
sed -i "s|^root:[^:]*|root:${HASH}|" /mnt/new-p2/etc/shadow

步骤 13: 卸载并完成

1
2
3
4
5
6
sync
umount /mnt/new-p1 /mnt/new-p2 /mnt/rk3528-p1 /mnt/rk3528-p2 /mnt/oe-p3
losetup -d /dev/loop0 /dev/loop1 /dev/loop2

ls -lh $WORKDIR/rk3528-openeuler22.img
# 3.5G,完成

步骤 14: 烧录

1
2
dd if=rk3528-openeuler22.img of=/dev/sdX bs=4M status=progress
sync

步骤 15: 首次启动验证

检查项 预期
串口连接 ttyS2, 1500000 baud
登录 root / openeuler
主机名 hostnamectl → rk3528-openeuler
网口名 ip link → eth0
IP 地址 ip addr → 192.168.1.1/24
plymouthd ps aux | grep plymouth 无进程
CPU 空闲 top → 99%+ idle
SSH systemctl status sshd → running
内核版本 uname -r → 6.1.141-rk35xx-ophub
系统版本 cat /etc/os-release → openEuler 22.03 LTS-SP4

关键避坑清单

现象 原因
plymouthd 占 4% CPU 内核参数 splash=verbose boot.scr 硬编码,需重编译
网口名叫 end1 树莓派 ifcfg-eth0 无效 systemd 可预测命名,需加 net.ifnames=0
DHCP 拿不到 IP 无法 SSH 进去 局域网无 DHCP,需预置静态 IP

适用性

本流程适用于任何 Rockchip RK35xx 系列开发板移植 openEuler,只需替换对应的 DTB 文件名即可:

  • RK3528: rk3528-x88pro13-1000m.dtb
  • RK3566: rk3566-*.dtb
  • RK3568: rk3568-*.dtb
  • RK3588: rk3588-*.dtb