引言
熟悉我的朋友们都知道,我在23年3月拿大创经费报销了一块香橙派5,当时rk3588是瑞芯微的主打产品,又是吹8nm工艺,又是吹性能强,不亚于主流手机。我看着那烧个windows arm巨卡无比的树莓派4B心里直痒痒,所以就买了一块,本来想放在实验室当服务器用,奈何当时生态太拉跨,且实验室有xa的电脑一直不关机,也用不上我搭服务器了,于是就吃灰到现在。现在我工作了,租了自己的房子,老家有黑群晖NAS,而租的房子为了省电,电脑不天天开着,需要一台服务器方便我随时连回去,所以就把吃灰的香橙派翻出来,让他物尽其用吧。看看两年过去了,瑞芯微的生态发展的怎么样了,两天爆肝万字长文(一个汉字占两个字符)把香橙派5打造成全能低功耗AIB
省流助手:还那b样,但是比全志强
安装系统
选择系统
首先,不要选择官方的系统,不要选择官方的系统,不要选择官方的系统
官方系统的内核严重落后,不提供更新,而且最重要的一点是它用的是arm的闭源gpu驱动,只支持opengl es,不支持opengl,所以很多东西都跑不起来
考虑到对rk3588的支持已经进入armbian主线,所以在无特殊需求的情况下,Linux优先推荐armbian,Android优先推荐fyde(openfyde也行)
但是,总有人会像我一样,就是喜欢折腾,选择了ubuntu-rockchip,这个系统胜在和armbian相比适配Ubuntu适配的比较好,更接近于原生Ubuntu的体验,而问题在于维护不是很积极,且使用的人太少,例如下面搭建Android容器就需要自己编译内核,没法用现成的
我安装的是Ubuntu 24.04,按照香橙派手册中的方法和官方系统镜像一样直接烧录即可
https://github.com/Joshua-Riek/ubuntu-rockchip/releases/tag/v2.3.2
不插显示器远程控制(配置多用户)
就像Windows一样,Ubuntu也内置了一套远程桌面服务,不仅支持VNC还支持RDP连接,如果你是日常连显示器鼠标键盘用电脑,只在临时需要远程连接的时候连,那么这套方案已经完全足够了
但如果只通过远程连接,gnome自带的远程桌面就显现出局限性了,gnome考虑到安全性,他的远程桌面只能在主机正在运行桌面系统且已解锁时连接,如果是一个无头的服务器,未启动桌面环境或用户未登录,远程桌面就无法连接了
很显然这样是不行的,我希望香橙派作为一个服务器能随时远程过去,甚至多用户能同时开不同的session,那么gnome自带的远程桌面就做不到了,需要寻找其他解决方案
① 修改gnome远程桌面配置(未成功)
我的第一个想法是看看gnome远程桌面的文档,看能不能允许从远程桌面登录,结果搞了好长时间没搞成功
https://gitlab.gnome.org/GNOME/gnome-remote-desktop
然后又在StackOverflow搜到要装一个插件禁用掉不允许通过远程登录的特性:Allow Locked Remote Desktop – GNOME Shell Extensions,但是还是不行
② HDMI诱骗器(香橙派不支持)
然后zsf提醒了我,那搞个HDMI诱骗器,让香橙派默认能进桌面不就能远程了,所以我到某宝买了个便宜的,结果插上一看,嘿,i2c报错,hdmi不认,开机之前插会kernel panic,开机之后来回拔插也会kernel panic,但是插到电脑是是正常的,后来搜发现rk3588就是会有一些显示器无法识别的问题,疑似是vop2驱动有问题,遂放弃,还是找软件解决方案吧
③ 使用TigerVNC的无头模式(成功)
最后我在网上搜到了一篇文章,说vnc有无头模式,可以在远程桌面连接时自动起一个session,并只在该session中显示桌面系统,这不正好符合我要做服务器的需求,于是赶快尝试一下
Ubuntu Desktop 实践 25、多用户、多桌面、远程桌面和虚拟桌面 – 知乎
成功!而且启动桌面session后gnome的rdp远程桌面服务也能用,就是比tigervnc卡多了,所以我又给关掉了
和直接显示器接板子相比,这种方式启动的桌面环境似乎是软件渲染的,所以有些卡,但好在rk3588 cpu够强,所以也没有那么卡,况且我只是用来当服务器,卡点问题也不大
后来发现TigerVNC起的session是X11,不是Wayland
其他问题
远程桌面进入的session无论怎么设置都是英文,无法改为中文,经过一番研究发现LANG环境变量一直都是C,然后发现我没装en_US语言包,装了之后LANG会被设成en_US.UTF-8,但是还是设不为zh_CN.UTF-8,所以干脆在.xsessionrc里强制把LANG设成中文好了
$ echo "export LANG=zh_CN.UTF-8" > ~/.xsessionrc
救砖
在折腾这些东西的过程中,尤其是配置内核相关的东西的时候,我把系统干崩了无数次,所以很有必要总结下我的救砖经验,供后人参考
瑞芯微soc的启动流程
maskrom--->spi flash->sd card/emmc/nvme/sata/usb...
\
->bootloader->烧录
maskrom是固化在芯片rom中的启动程序,无法修改,他会在上电后自动运行spi flash中的程序(对香橙派来说,如果你是别的板子还可能是nand之类的),如果按住了板子上的maskrom键再上电则会进入maskrom模式,该模式下会等待电脑端上位机RKDevTool发送bootloader,将bootloader放到内存中并执行,所以rk3588的启动流程是一个典型的二阶段加载SSB(似乎国产芯片都这样?)
因此我们需要备份的就是spi flash和你使用的存储器里的内容,这里我使用的是nvme固态硬盘
ubuntu-rockchip的镜像格式
ubuntu-rockchip也很有意思,为了方便随时更换系统无需使用RKDevTool烧写flash,这个ubuntu镜像并非像官方的镜像一样,把uboot烧录在spi flash中,把整个系统分区烧录在存储器中,而是在存储器开头16MB放置了uboot的镜像,后面是一个ext4格式的EFI分区(真的是EFI),启动时会先从maskrom跳转到spi flash里的rkspi_loader,然后跳转到存储器中的uboot分区,再从ext4分区中加载系统内核,最后启动
所以需要注意的是备份系统时不要忘记备份和恢复uboot分区,不然起不来啦
备份和还原整块硬盘
这个简单,dd整块硬盘就行,dd是直接按扇区复制的,没有压缩,所以电脑上记得留充足的空间
可以使用fdisk工具查看系统使用的存储设备名 $ fdisk -l 直接复制到文件 $ dd if=/dev/<存储设备名> of=ubuntu_backup.img bs=4M status=progress 只备份uboot分区 $ dd if=/dev/<存储设备名> of=uboot_backup.img bs=512 count=32 也可以在复制时用管道进行压缩 $ dd if=/dev/<存储设备名> bs=4M | gzip > ubuntu_backup.img.gz 从镜像恢复 $ dd if=ubuntu_backup.img of=/dev/<存储设备名> 只恢复uboot分区 $ dd if=uboot_backup.img of=/dev/<存储设备名> 从压缩的镜像恢复 $ gzip -dc ubuntu_backup.img.gz | dd of=/dev/<存储设备名>
备份和还原文件
因为我的硬盘是256GB的,而且是块19年的三星硬盘,发热量巨大,我就只备份了装系统的分区
还是用fdisk工具查看分区名 $ fdisk -l 挂载分区 $ mkdir -p /mnt/media $ sudo mount /dev/nvmexnxpx /mnt/media 备份分区所有文件 $ cd /mnt/media $ tar --acls --xattrs -cpvf ~/rootfs_backup.tar ./ 还原分区所有文件 $ tar --acls --xattrs -xpvf ~/rootfs_backup.tar -C /mnt/media
结果实际恢复之后系统起不来,有一大堆坑,以后还是老老实实备份硬盘吧,如果你也和我一样不幸只备份了文件,然后重新烧录了镜像并恢复了文件,那就接着看下一节吧
我忘了备份uboot,怎么办QAQ
首先说结论,其实只备份和还原文件最终是能起来的,只是需要像电脑一样修复一下引导,但是由于arm架构的soc没有UEFI(虽然有edk2的移植,但是还不完善,我没用),也没有grub,更没有livecd,导致修引导极其地费劲。而且内存盘的命令行还只显示在屏幕上,调试串口中没有,导致我一度以为内核挂死修不好了,折腾了好几天
最关键的一点其实在于重装系统后分区的UUID会变,而恢复根文件系统后的/boot/extlinux/extlinux.conf启动配置中还是旧的分区的UUID,导致内核找不到要启动的分区,从而只能进到initramfs的命令行中
这里似乎还有驱动bug,如果我没在进入initramfs前接显示器并切换过去,那无论怎么敲回车屏幕都没有画面,这也是我以为内核挂死的原因之一
首先在命令行中输入exit可以获取系统启动失败的原因,我的原因就是找不到指定UUID的分区
然后使用blkid查看当前各分区的UUID
$ blkid /dev/nvme0n1p1: LABEL="desktop-rootfs" UUID="977077f9-5d15-4766-802f-99dd34d4f78a" BLOCK_SIZE="4096" TYPE="ext4" PARTLABEL="primary" PARTUUID="7d82bd51-86d5-4adf-b37c-5eb3d5efb1af"
从输出的信息中可以看到系统分区的UUID为977077f9-5d15-4766-802f-99dd34d4f78a,把他记下来,然后把硬盘换到一台装了linux系统的电脑上(windows和mac也行,能想办法打开ext4分区就行)
编辑/boot/extlinux/extlinux.conf和/etc/fstab,把分区的UUID全换成刚才的那个,然后硬盘插回去就能成功启动了
最后别忘了sudo u-boot-update更新一下extlinux.conf
部署服务
我打算充分压榨(划掉)利用香橙派的每一份算力,所以打算在上面跑一大堆服务,这些服务单独跑很简单,但要让他们同时正常工作在一个arm架构的soc上还是太吃实力了,遇到了很多坑啊,光重装系统就不下几十次
基础设施
1. Docker
apt install docker docker-compose
最简单的一集
docker desktop商业化太重了,所以管理界面本来打算用podman来着,但是没研究明白,后来改用面板的容器管理功能了
2. Win11虚拟机
使用了bvm,门槛很低,基本上是一键配置,就是很卡
https://github.com/Botspot/bvm
3. WINE/box86
win11虚拟机太卡了,装b用可以,真要跑windows程序还得是wine或者box86这种转译
参考:在 openFyde 和 FydeOS ARM64 设备上安装 Box86、Steam 和 Wine | FydeOS 帮助中心
sudo apt install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross git clone https://github.com/ptitSeb/box86 cd box86 mkdir build && cd build cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo make -j4 sudo make install # 打包deb DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc
sudo apt install binfmt-support git clone https://github.com/ptitSeb/box64 cd box64 mkdir build && cd build cmake .. -D ARM_DYNAREC=ON -D RK3588=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo -D BOX32=ON -D BOX32_BINFMT=ON make -j4 sudo make install sudo systemctl restart systemd-binfmt # 打包deb DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc
$ sudo vi /usr/share/binfmts/box86 package box86 interpreter /usr/local/bin/box86 magic \x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00 mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff $ sudo vi /usr/share/binfmts/box64 package box64 interpreter /usr/local/bin/box64 magic \x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00 mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff $ sudo update-binfmts --import $ sudo update-binfmts --enable box86 $ sudo update-binfmts --enable box64 $ sudo update-binfmts --display $ sudo systemctl restart systemd-binfmt
echo 'export STEAMOS=1 export STEAM_RUNTIME=1 export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1' | sudo tee /etc/profile.d/steam.sh source /etc/profile.d/steam.sh ./box86/install_steam.sh sudo apt install libx11-6:armhf libgl-dev:armhf libxrandr2:armhf sudo apt install libayatana-appindicator3-1 libglib2.0-0t64 libgtk-3-0t64 # libappindicator1 steam killall -9 steam steamwebhelper rm -rf ~/.local/share/Steam/
事实上我并没有成功,暂时放弃了,等以后有空了再研究
4. Android容器
为了做某个已经停更的游戏的每日任务,我希望跑一个Android容器,每天自动化执行挂机任务
在试了一大堆Android容器后,发现最好用的还是CNflysky/redroid-rk3588,但是这个容器依赖自定义的linux内核,如果是armbian有大佬编好的直接拿来用即可,而用ubuntu-rockchip的就只能好好折腾一番了
① 编译内核
需要按照CNflysky/redroid-rk3588的README所述,调整内核选项,如果内核版本是6.1还要打dma-buf驱动的补丁,考虑到这个步骤比较繁琐,我已经把我验证过的内核代码上传到了github,直接编译即可
https://github.com/DawningW/linux-rockchip
然后按照linux-rockchip文档的步骤编译内核
https://github.com/Joshua-Riek/linux-rockchip/wiki#building-the-kernel
export $(dpkg-architecture -aarm64) export CROSS_COMPILE=aarch64-linux-gnu- export CC=aarch64-linux-gnu-gcc export LANG=C fakeroot debian/rules clean binary-headers binary-rockchip do_mainline_build=true
编译完毕后会在上一级目录中生成含有内核模块的deb包,直接用apt安装即可
如果懒得编译或者实在编译不过可以下载我编好的内核
https://github.com/DawningW/linux-rockchip/releases/tag/6.1.0-1027.27%2Bredroid.2
参考:https://www.nyanners.moe/post/fix-rk3588-redroid-azur-lane-crash.html
② 安装容器
把CNflysky/redroid-rk3588拉到本地,修改下docker-compose.yml里的配置,然后
sudo docker-compose up
③ 原神启动 修复其他环境问题
再装个adb和scrcpy,然后就可以启动了…吗
事实上,如果直接启动我玩的某游戏,开屏界面后会闪退,logcat报以下错误:
The property "ro.build.fingerprint" has a value with length 95 that is too large for __system_property_get()/__system_property_read(); use __system_property_read_callback() instead.
这是因为游戏使用了__system_property_get接口读取指纹属性,而这个接口最大只能读95个字符,镜像默认的指纹是redroid/redroid_arm64/redroid_arm64:13/TQ3A.230901.001/eng.flysky.20241107.005346:user/dev-keys,超过了95个字符
但是这是一个只读属性,直接用setprop改会失败,怎么办呢
诶,我灵机一动,这个镜像里有magisk,也就是说镜像已经root了,正好magisk提供了一个resetprop的命令用于修改任何属性,用它改不就行了,一试结果还真行
https://github.com/topjohnwu/Magisk/blob/master/docs/tools.md#resetprop
$ su # resetprop ro.build.fingerprint redroid/redroid_rk/redroid:13/TQ3A.230901.001/flysky.20241107.005346:user/dev-keys
游戏顺利启动,性能也不错,居然能跑满60帧,挂机脚本也能流畅运行 🙂
应用服务
1. 面板
研究了许多面板,最后发现市面上能用的还是只有宝塔和1panel,宝塔是php写的直接排除,那就来装1panel吧
按官方文档一键安装即可:https://1panel.cn/docs/v2/installation/online_installation/
bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"
进程守护功能需要安装supervisor
sudo apt install supervisor
最后再通过1panel的定时任务功能定时执行挂机脚本(所以我装个面板只是为了定时任务和进程守护吗
2. DDNS
经典ddns-go
3. tailscale
sudo apt install tailscale
4. HomeAssistant
我现在租的房子有小米全屋智能,那当然得接入一下HA了
我选择了通过docker-compose方式安装:https://www.home-assistant.io/installation/alternative/#docker-compose
services:
homeassistant:
container_name: homeassistant
image: "ghcr.io/home-assistant/home-assistant:stable"
volumes:
- <你的homeassistant配置目录>:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
privileged: true
network_mode: host
然后启动
$ sudo docker-compose up -d
打开 http://<host>:8123 并进行配置
添加 Home Assistant Community Store 源:https://hacs.xyz/docs/use/download/download/#to-download-hacs-container
$ sudo docker exec -it homeassistant bash wget -O - https://get.hacs.xyz | bash -
然后在集成中添加HACS
安装官方米家集成:https://github.com/XiaoMi/ha_xiaomi_home/blob/main/doc/README_zh.md
HACS > 在搜索框中输入 Xiaomi Home > 点击 Xiaomi Home ,进入集成详情页 > DOWNLOAD
然后在集成中添加Xiaomi Home,再登录小米账号即可
用vivo智慧生活控制HA:https://github.com/vivo/ha_vivohomebridge
安装后在集成中添加vivohomebridge,然后用vivo智慧生活添加HA中控即可
添加MQTT设备:TODO
添加ESPHome设备:TODO
换更好看的主题:TODO
5. Gitea Runner
按照官方文档按照act runner,因为我是想直接在香橙派本机上跑测试,需要用到sensor等外设,所以没有使用容器部署的方式,而是直接运行,通过1panel的进程守护功能在后台运行(实际是supervisor)
https://docs.gitea.com/zh-cn/usage/actions/act-runner
不过我跑执行器是为了给OurIPC跑门禁,那就需要在板端支持sensor和isp server,ubuntu-rockchip默认并没有开启这些功能,毕竟一般人用不到,下面将介绍如何通过dtbo(设备树覆盖)来实现加载sensor驱动并启动rkisp-server
https://github.com/Joshua-Riek/ubuntu-rockchip/wiki/Ubuntu-24.04-LTS#system-customization
首先加载sensor的设备树,我用的是ov13855,接在cam1上,所以进入到/lib/firmware/$(uname -r)/device-tree/rockchip/overlay目录中找对应的dtbo,经过一番查找,我需要加载的dtbo是orangepi-5-ov13855-c1.dtbo
编辑/etc/default/u-boot,将U_BOOT_FDT_OVERLAYS_DIR设置为"/lib/firmware/",将U_BOOT_FDT_OVERLAYS设置为"device-tree/rockchip/overlay/orangepi-5-ov13855-c1.dtbo",最后运行sudo u-boot-update更新/boot/extlinux/extlinux.conf启动配置
如果需要修改内核启动参数,可以编辑/etc/kernel/cmdline,在里面加上你需要的启动参数,最后别忘了u-boot-update
重启后使用gstreamer已经能够预览sensor的视频流,但因为没有过isp,图像是发绿的,几乎什么都看不清,所以接下来还需要安装并启动瑞芯微的rkaiq_3A_server
$ apt search rkaiq camera-engine-rkaiq-rk3588/noble,now 6.0x6.1-3~noble arm64 3A libraries match Rockchip rkisp v30(rk3588). $ sudo apt install camera-engine-rkaiq-rk3588 $ sudo systemctl enable rkaiq_3A.service $ sudo systemctl start rkaiq_3A.service
然后就可以用gstreamer从isp的节点拉流,图像就正常啦,你可以用gstreamer甚至自己写个程序把香橙派变成一个IPC,这实在是太酷啦!
其他操作,如3A算法参数调节等可以参考瑞芯微官方提供的手册
6. rkllm
rk3588的一大特点就是有算力高达6T的NPU,那能不能用来跑一些小大模型呢,诶,当然是可以的,官方推出了针对大语言模型优化的rkllm库以及预转换好的模型,我们可以直接拿来用
https://github.com/airockchip/rknn-llm
ubuntu-rockchip的5.10和6.1内核中都应该已经自带了RKNPU的内核驱动,且默认开启,应该不需要任何配置就能工作,我们只需要将rknn-llm克隆到板端,下载模型,运行例程即可使用
下面运行推理使用DeepSeek-R1蒸馏的Qwen-7B模型(int8量化)效果如下(我的版本有点旧了,现在库上最新版本可能目录结构有区别,以官方文档为准)
$ cd rknn-llm/examples/DeepSeek-R1-Distill-Qwen-1.5B_Demo/deploy $ ./build-linux.sh $ cd install/demo_Linux_aarch64 $ export LD_LIBRARY_PATH=$(pwd)/lib $ ./llm_demo <下载的模型目录>/DeepSeek_R1_Distill/DeepSeek-R1-Distill-Qwen-7B_W8A8_RK3588.rkllm 1024 4096 rkllm init start I rkllm: rkllm-runtime version: 1.1.4, rknpu driver version: 0.9.7, platform: RK3588 rkllm init success **********************可输入以下问题对应序号获取回答/或自定义输入******************** [0] 现有一笼子,里面有鸡和兔子若干只,数一数,共有头14个,腿38条,求鸡和兔子各有多少只? [1] 有28位小朋友排成一行,从左边开始数第10位是学豆,从右边开始数他是第几位? ************************************************************************* user: hello robot: <think> </think> Hello! How can I assist you today? 😊 user: 你是谁 robot: <think> </think> 您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何任何问题,我会尽我所能为您提供帮助。 user: ^C程序即将退出
输出token的速度好慢,我们有没有什么办法查看NPU的使用率呢,有的兄弟有的,rknpu驱动在sysfs下提供了几个用于查看NPU占用率的设备
$ sudo cat /sys/kernel/debug/rknpu/load NPU load: Core0: 0%, Core1: 0%, Core2: 0%,
如果想要持续观测可以使用watch命令
watch -n 1.0 sudo cat /sys/kernel/debug/rknpu/load
除了NPU占用率,温度也是需要关注的,可以通过以下命令获取
$ cat /sys/class/thermal/thermal_zone*/type pe soc-thermal bigcore0-thermal bigcore1-thermal littlecore-thermal center-thermal gpu-thermal npu-thermal $ cat /sys/class/thermal/thermal_zone*/temp mp 46230 47153 47153 46230 44384 43461 44384
获取的温度值是乘了1000的,例如上述的46230是46.23°C,可以看到我的香橙派温度还行
如果想要更以人类可读的方式查看传感器温度,可以安装lm-sensors库来查看
$ sudo apt install lm-sensors $ sensors
那如果想要可视化地查看NPU占用率呢,正好我前段时间在GitHub逛的时候发现了一个脚本,用起来还行
https://github.com/Tang-JingWei/watchload-for-rk3588
直接克隆到本地安装依赖后即可运行
$ git clone https://github.com/Tang-JingWei/watchload-for-rk3588.git $ cd watchload-for-rk3588 $ pip install -r requirements.txt $ ./watchload
这个脚本除了TUI外还支持使用matplotlib绘制NPU占用率曲线图,很有意思
上述的例程只能在命令行中输入对话,怎么作为服务对接聊天机器人或各类LLM工具呢,答案是GitHub上有个毛子写的Python脚本,为rkllm推理套了一层openai的api接口
由于原脚本很长时间没有维护了,这里选择了他的一个汉化分支,并在该分支基础上修改:https://github.com/kylin7226/rkllm_server_openai_api
这样就能使用任何兼容openai api接口的客户端使用rkllm进行推理啦~
7. napcat(?)
Docker镜像部署:https://github.com/NapNeko/NapCat-Docker
暂时不跑,有空再搬过去
未来展望
等到rk36883788甚至3888是不是就可以上虚拟化了,虽然现在rk3588已经有移植的esxi,但是不够完善,且rk3588性能还是太差,如果能上虚拟化,且算力足够,就能取代x86的AIO,实现一个集软路由、NAS、各种服务、虚拟机、NVR、大模型推理于一体的超级AIO,且功耗对x86有显著优势
现在是幻想时间