项目开发需要 欧拉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
9
10
# 主机名
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

删除 pi 用户 # 删用户 + 家目录 + 邮件

步骤 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

进入系统后的配置

系统优化记录 — rk3528-openeuler22

日期: 2026-05-09
硬件: Rockchip RK3528, 无 RTC, 无网关, HTTP 代理 192.168.16.XXX:1080
系统: openEuler 22, kernel 6.1.141-rk35xx-ophub


0. Linux命令自动补全

1
dnf install bash-completion -y

1. SSH 登录 .bashrc 不生效

诊断

1
2
3
4
5
6
# SSH 启动的是 login shell
shopt login_shell

# 检查存在的登录配置文件
ls -la ~/.bash_profile ~/.bash_login ~/.profile
# 输出: No such file or directory(三个都不存在)

根因: login shell 按顺序找 ~/.bash_profile~/.bash_login~/.profile,读了第一个就停。三者皆空,.bashrc 被跳过。

修复

1
2
3
cat > /root/.bash_profile << 'EOF'
[ -f ~/.bashrc ] && . ~/.bashrc
EOF

2. 时间同步方案(无 RTC + 无网关)

背景

  • timedatectl 显示 RTC time: n/a
  • 每次重启时间归 1970-01-01
  • 无默认网关,NTP (UDP 123) 出不去
  • 只有 HTTP 代理 192.168.16.XXX:1080
  • 时间错误 → SSL 证书验证失败 → 无法联网 → 鸡生蛋蛋生鸡

方案设计

HTTPS Date 头获取时间 → 设置系统时钟 → SSL 可用 → 一切正常。
同时保留 NTP,网关恢复后自动补位。

文件清单

(1) /usr/local/sbin/fake-hwclock

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
26
27
28
29
30
cat > /usr/local/sbin/fake-hwclock << 'SCRIPT'
#!/bin/bash
STAMP_FILE=/var/lib/fake-hwclock.data
HTTPS_URL="https://www.baidu.com"

# Source user config for proxy vars
[ -f /root/.bashrc ] && source /root/.bashrc

set_time_from_http() {
local d
d=$(curl -sI --proxy "$http_proxy" --max-time 10 "$HTTPS_URL" 2>/dev/null | grep -i '^date:' | sed 's/[Dd]ate: //' | tr -d '\r')
[ -n "$d" ] && date -s "$d" >/dev/null 2>&1 && return 0
return 1
}

case "$1" in
restore)
set_time_from_http && exit 0
[ -f "$STAMP_FILE" ] && date -s "@$(cat "$STAMP_FILE")" >/dev/null
;;
sync)
set_time_from_http && date +%s > "$STAMP_FILE"
;;
save)
date +%s > "$STAMP_FILE"
;;
esac
SCRIPT

chmod +x /usr/local/sbin/fake-hwclock

(2) fake-hwclock-restore.service — 开机恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat > /etc/systemd/system/fake-hwclock-restore.service << 'EOF'
[Unit]
Description=Restore clock from HTTPS or saved timestamp
DefaultDependencies=no
After=local-fs.target network-online.target
Wants=network-online.target
Before=time-sync.target
Conflicts=shutdown.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/fake-hwclock restore
RemainAfterExit=yes

[Install]
WantedBy=sysinit.target
EOF

(3) fake-hwclock-sync.service — 定时同步

1
2
3
4
5
6
7
8
9
10
cat > /etc/systemd/system/fake-hwclock-sync.service << 'EOF'
[Unit]
Description=Sync clock via HTTPS
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/fake-hwclock sync
EOF

(4) fake-hwclock-sync.timer — 每小时触发

1
2
3
4
5
6
7
8
9
10
11
cat > /etc/systemd/system/fake-hwclock-sync.timer << 'EOF'
[Unit]
Description=Periodically sync clock via HTTPS

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target
EOF

(5) fake-hwclock-save.service — 关机保存

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /etc/systemd/system/fake-hwclock-save.service << 'EOF'
[Unit]
Description=Save fake hardware clock
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/fake-hwclock save

[Install]
WantedBy=halt.target reboot.target poweroff.target
EOF

启用

1
2
3
4
5
6
7
mkdir -p /var/lib
/usr/local/sbin/fake-hwclock save # 首次存档
systemctl daemon-reload
systemctl enable fake-hwclock-restore.service
systemctl enable fake-hwclock-sync.timer
systemctl start fake-hwclock-sync.timer
systemctl enable fake-hwclock-save.service

NTP 共存

systemd-timesyncd 保持启用,网关恢复后 NTP (UDP 123) 自动生效。


3. SSH 登录加速

诊断

1
2
3
grep -E 'GSSAPIAuthentication|UseDNS' /etc/ssh/sshd_config
# GSSAPIAuthentication yes ← 无 Kerberos 会超时等待
# #UseDNS no ← 默认 yes,DNS 反向查询慢

修复

1
2
3
sed -i 's/^GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#UseDNS no/UseDNS no/' /etc/ssh/sshd_config
sshd -t && systemctl reload sshd

4. root 子 shell 提示符异常

现象

1
2
[root@host ~]# bash
bash-5.1#

诊断

1
2
3
4
5
6
7
8
9
# pi 用户正常的原因
cat /home/pi/.bashrc
# [ -f /etc/bashrc ] && . /etc/bashrc ← 有这行

# root 缺少这行
cat /root/.bashrc
# export PATH=...
# export http_proxy=...
# ...(没有 source /etc/bashrc)

/etc/bashrc 第 43 行是设置 PS1 提示符的地方,.bashrc 不 source 它就会用 bash 默认值 bash-5.1#

修复

/root/.bashrc 末尾追加:

1
[ -f /etc/bashrc ] && . /etc/bashrc

验证

1
2
bash
# [root@rk3528-openeuler22 ~]# ← 正常

最终时间同步架构

1
2
3
4
5
6
7
8
9
10
开机
├─ fake-hwclock-restore → HTTPS (via proxy) 对时 ✓
│ └─ 失败 → 回退本地文件
├─ systemd-timesyncd → NTP (UDP) 静默等待网关

定时 (每小时)
└─ fake-hwclock-sync → HTTPS 对时 + 存档

关机
└─ fake-hwclock-save → 保存时间戳到 /var/lib/fake-hwclock.data