项目开发需要 欧拉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 开发板原厂镜像 (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: 配置串口和显示器登录

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

# 保留 getty@tty1 (HDMI 显示器 + USB 键盘)
ln -sf /usr/lib/systemd/system/getty@.service \
/mnt/new-p2/etc/systemd/system/getty.target.wants/getty@tty1.service

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

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

# 写入 NM keyfile:静态 192.168.1.1/24 始终生效,DHCP 自动获取上网 IP
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
wait-device-timeout=5

[ipv4]
method=auto
addresses=192.168.1.1/24
may-fail=yes
dhcp-timeout=10

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

步骤 9: 禁止等待网络就绪 (防开机卡住)

1
2
# mask NetworkManager-wait-online — headless 系统不需要等网络才进登录界面
ln -sf /dev/null /mnt/new-p2/etc/systemd/system/NetworkManager-wait-online.service

步骤 10: 修复 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 # 应无输出

步骤 11: 修改 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

步骤 12: 删除 dracut plymouth 模块

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

步骤 13: 设置 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

步骤 14: 设置默认启动目标为纯终端

1
2
3
rm -f /mnt/new-p2/etc/systemd/system/default.target
ln -sf /usr/lib/systemd/system/multi-user.target /mnt/new-p2/etc/systemd/system/default.target
# 避免 graphical.target 拉无用的图形服务

步骤 15: 卸载并完成

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-oe22.img

步骤 16: 烧录

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

步骤 17: 首次启动验证

  • HDMI+键盘 — 显示器显示登录界面,键盘可输入
  • 串口连接 — ttyS2, 1500000 baud 可登录
  • 登录 — root / openeuler
  • 启动时间 — 不插网线也能秒进登录界面
  • 主机名hostnamectl → rk3528-openeuler
  • 网口名ip link → eth0
  • IP 地址ip addr → 192.168.1.1/24 静态,另有 DHCP IP
  • plymouthdps aux | grep plymouth 无进程
  • CPU 空闲top → 99%+ idle
  • 默认目标systemctl get-default → multi-user.target
  • SSHsystemctl 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
  • 不插网线卡开机 — Network Manager Wait Online 阻塞,需 mask 该 service
  • HDMI+键盘无反应 — tty1 getty 被误删,必须保留 getty@tty1
  • DHCP 拿不到 IP — 无法 SSH 进去,需预置静态 IP + may-fail=yes + dhcp-timeout

适用性

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

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