KVMR0ck: Radxa ZERO 3W based KVM
В этом посте речь пойдет о сборке и установке PiKVM на Radxa ZERO 3W с HDMI-CSI bridge C790. Должен получится крепкий среднячок, а там как получится %)
Hardware: intro
KVMR0ck во всех смыслах довольно типичный DIY KVM девайс и мало чем отличается от официального гайда PiKVM V2. За исключением, пожалуй, использования Radxa ZERO 3W вместо Raspberry Pi Zero 2 W. Почему не RPI Zero 2 W? Все довольно просто:
- хотел одноплатник помощнее, на случай если KVMR0ck не взлетит
- хотел получше WiFi, потому-что это всегда хорошо
- хотел eMMC на борту, дабы SD card отдать под образы дисков
- не хотел малинку
Смотрите сами как они выглядят в сравнении:
Radxa Zero 3W | Raspberry Pi Zero 2 W | |
---|---|---|
CPU | Rockchip RK3566 64-bit SoC with quad‑core Arm Cortex‑A55 @ 1.6GHz | Broadcom BCM2710A1 64-bit SoC with quad-core Arm Cortex-A53 @ 1GHz |
RAM | 1GB, 2GB, 4GB, or 8GB LPDDR4 | 512MB LPDDR2 |
GPU | Arm Mali‑G52‑2EE | Broadcom VideoCore IV |
Ports | Micro HDMI (1080p@60fps), USB-C 2.0 OTG, USB-C 3.0 Host, MIPI CSI camera connector | Mini HDMI (1080p@30fps), micro USB 2.0 OTG, micro USB 2.0 power, MIPI CSI-2 camera connector |
Networking | Wi-Fi 6 and Bluetooth 5.4 with BLE | Wi-Fi 4 and Bluetooth 4.2 with BLE |
Storage | MicroSD card slot, optional on-board eMMC (8GB, 16GB, 32GB, or 64GB) | MicroSD card slot |
Price | $20-$100 | $20 |
Конкретно у меня Radxa Zero 3W с 4GB RAM и 32GB eMMC. По деньгам получилось около $70:
- Radxa Zero 3W, 4GB RAM, 32GB eMMC - $50 с доставкой
- HDMI to CSI-2 Board C790 - $15
- три Type-C коннектора и макетная платка - около $2-3
- какой-то корпус, который нашел в столе - пусть будет еще $2
Hardware: assemble
Тут сложно сделать что-то не так, ведь единственное, что предстоит изготовить - USB/Power Splitter. Можно было бы и найти готовый (e.g. USB/Power Splitter for Raspberry Pi BliKVM and PiKVM), но не вижу смысла, ведь это просто пара коннекторов с резисторами: Не уверен в острой необходимости pull-up/pull-down резисторов, но по стандарту они нужны - решил оставить.
Осталось дело за малым - запаять и подсобрать:
Software
С софтом тоже без причуд:
- Armbian в качестве дистрибутива
- KVMD For Armbian (порт PiKVM) для остального
Cтавим Debian 12 (Bookworm) Minimal на eMMC, делаем первичную настройку (WiFi, SSH, вот это все), топаем по SSH и…
Включаем USB OTG, добавив нужный Device Tree overlay:
root@kvmr0ck:~# mkdir -p /boot/overlay-user
root@kvmr0ck:~# cat << '_EOF_' > /boot/overlay-user/usb-otg.dts
/dts-v1/;
/plugin/;
/ {
metadata {
title = "Enable USB OTG";
compatible = "rockchip,rk3566", "rockchip,rk3568";
category = "misc";
exclusive = "usbdrd_dwc3-dr_mode";
description = "Enable USB OTG port";
};
};
&usbdrd_dwc3 {
status = "okay";
dr_mode = "otg";
};
_EOF_
root@kvmr0ck:~# armbian-add-overlay /boot/overlay-user/usb-otg.dts
Compiling the overlay
Copying the compiled overlay file to /boot/overlay-user/
Reboot is required to apply the changes
root@kvmr0ck:~# reboot
Затем поддержу HDMI-CSI. Мой C790, как и большинство подобных, выполнен на базе Toshiba TC358743, а для его поддержки какой-то добрый человек уже поработал (см. TC358743 Radxa Zero 3W Notes):
root@kvmr0ck:~# ls -la /dev/video*
ls: cannot access '/dev/video*': No such file or directory
root@kvmr0ck:~# cat << '_EOF_' > /boot/overlay-user/tc358743-hdmi-in.dts
/dts-v1/;
/plugin/;
/ {
metadata {
title = "TC358743 HDMI RX";
compatible = "radxa,zero3";
description = "Allow use of TC358743 HDMI -> CSI2 input.";
category = "video";
};
fragment@0 {
target-path = "/";
__overlay__ {
clk_cam_27m: external-camera-clock-27m {
status = "okay";
compatible = "fixed-clock";
clock-frequency = <27000000>;
clock-output-names = "clk_cam_27mhz";
#clock-cells = <0>;
};
camera_pwdn_gpio: camera-pwdn-gpio {
status = "okay";
compatible = "regulator-fixed";
regulator-name = "camera_pwdn_gpio";
regulator-always-on;
regulator-boot-on;
enable-active-high;
// gpio = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH> // Commented so no included needed.
gpio = <&gpio3 22 0>;
};
};
};
fragment@1 {
target = <&i2c2>;
__overlay__ {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c2m1_xfer>;
#address-cells = <1>;
#size-cells = <0>;
camera_tc358743: tc358743@f {
status = "okay";
compatible = "toshiba,tc358743";
reg = <0x0f>;
clocks = <&clk_cam_27m>;
clock-names = "refclk";
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "tc358743";
rockchip,camera-module-lens-name = "default";
port {
hdmi_rx_out: endpoint {
remote-endpoint = <&mipi_in_hdmirx0>;
clock-lanes = <0>;
clock-noncontinuous;
link-frequencies = /bits/ 64 <297000000>;
data-lanes = <1 2 3 4>;
};
};
};
};
};
fragment@2 {
target = <&csi2_dphy_hw>;
__overlay__ {
status = "okay";
};
};
fragment@3 {
target = <&csi2_dphy0>;
__overlay__ {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
mipi_in_hdmirx0: endpoint@1 {
reg = <1>;
remote-endpoint = <&hdmi_rx_out>;
data-lanes = <1 2 3 4>;
};
};
port@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
mipi_out_dphy0: endpoint@1 {
reg = <1>;
remote-endpoint = <&rkisp_mipi_in>;
data-lanes = <1 2 3 4>;
};
};
};
};
};
fragment@4 {
target = <&rkisp_vir0>;
__overlay__ {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
rkisp_mipi_in: endpoint@0 {
reg = <0>;
remote-endpoint = <&mipi_out_dphy0>;
};
};
};
};
fragment@5 {
target = <&rkisp>;
__overlay__ {
status = "okay";
};
};
fragment@6 {
target = <&rkisp_mmu>;
__overlay__ {
status = "okay";
};
};
fragment@7 {
target = <&rkcif_mmu>;
__overlay__ {
status = "okay";
};
};
fragment@8 {
target = <&rkcif>;
__overlay__ {
status = "okay";
};
};
};
_EOF_
root@kvmr0ck:~# armbian-add-overlay /boot/overlay-user/tc358743-hdmi-in.dts
Compiling the overlay
Copying the compiled overlay file to /boot/overlay-user/
Reboot is required to apply the changes
root@kvmr0ck:~# reboot
buglloc@kvmr0ck:~$ ls -al /dev/video*
crw-rw---- 1 root video 81, 0 Dec 14 19:12 /dev/video0
crw-rw---- 1 root video 81, 1 Dec 14 19:12 /dev/video1
crw-rw---- 1 root video 81, 2 Dec 14 19:12 /dev/video2
crw-rw---- 1 root video 81, 3 Dec 14 19:12 /dev/video3
crw-rw---- 1 root video 81, 4 Dec 14 19:12 /dev/video4
crw-rw---- 1 root video 81, 5 Dec 14 19:12 /dev/video5
crw-rw---- 1 root video 81, 6 Dec 14 19:12 /dev/video6
crw-rw---- 1 root video 81, 7 Dec 14 19:12 /dev/video7
crw-rw---- 1 root video 81, 8 Dec 14 19:12 /dev/video8
crw-rw---- 1 root video 81, 9 Dec 14 19:12 /dev/video9
Осталось установить KVMD For Armbian:
root@kvmr0ck:~# apt install -y git vim make python3-dev gcc xz-utils wget sudo
root@kvmr0ck:~# git clone --depth=1 https://github.com/srepac/kvmd-armbian.git
root@kvmr0ck:~# cd kvmd-armbian
root@kvmr0ck:~/kvmd-armbian# ./install.sh
Python 3.11 is supported.
Running part 1 of PiKVM installer script v3.4 by @srepac
Single Board Computer: Radxa ZERO 3
[...]
Press ENTER to continue or CTRL+C to break out of script.
Broadcast message from root@kvmr0ck on pts/1 (Sat 2024-12-14 19:37:20 MSK):
The system will reboot now!
root@kvmr0ck:~/kvmd-armbian# ./install.sh
Python 3.11 is supported.
Running part 2 of PiKVM installer script v3.4 by @srepac
[...]
Check kvmd devices
lrwxrwxrwx 1 root root 5 Dec 14 19:41 /dev/kvmd-hid-keyboard -> hidg0
lrwxrwxrwx 1 root root 5 Dec 14 19:41 /dev/kvmd-hid-mouse -> hidg1
lrwxrwxrwx 1 root root 5 Dec 14 19:41 /dev/kvmd-hid-mouse-alt -> hidg2
lrwxrwxrwx 1 root root 6 Dec 14 19:41 /dev/kvmd-video -> video0
You should see devices for keyboard, mouse, and video.
Point a browser to https://kvmr0ck
Please make sure kvmd services are running after reboot.
root@kvmr0ck:~/kvmd-armbian# reboot
Проверяем, ииии:
root@kvmr0ck:~# systemctl status kvmd
● kvmd.service - PiKVM - The main daemon
Loaded: loaded (/lib/systemd/system/kvmd.service; enabled; preset: enabled)
Active: active (running) since Sat 2024-12-14 19:42:14 MSK; 1min 14s ago
Main PID: 1081 (kvmd/main: /usr)
Tasks: 15 (limit: 82)
Memory: 78.4M
CPU: 15.639s
CGroup: /system.slice/kvmd.service
├─1081 "kvmd/main: /usr/bin/python /usr/bin/kvmd --run"
├─1094 "kvmd/hid-keyboard: /usr/bin/python /usr/bin/kvmd --run"
├─1095 "kvmd/hid-mouse: /usr/bin/python /usr/bin/kvmd --run"
├─1096 "kvmd/hid-mouse: /usr/bin/python /usr/bin/kvmd --run"
└─1123 "kvmd/streamer: /usr/bin/ustreamer --device=/dev/kvmd-video --persistent --format=mjpeg --resolution=1280x720 --desired-fps=40 --drop-same-frames=30 --unix=/run/kvmd/ustreamer.sock --unix-rm --unix-mode=0660 >
Dec 14 19:43:24 kvmr0ck kvmd[1081]: kvmd.apps.kvmd.streamer INFO --- => -- ERROR [85.192 ] -- CAP: Can't set device format: Invalid argument
Dec 14 19:43:25 kvmr0ck kvmd[1081]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [86.228 ] -- Using V4L2 device: /dev/kvmd-video
Как обычно что-то пошло не так :) Видимо формат не подходящий, cмотрим что нам говорит v4l2:
root@kvmr0ck:~# v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture Multiplanar
[0]: 'UYVY' (UYVY 4:2:2)
[1]: '422P' (Planar YUV 4:2:2)
[2]: 'NV16' (Y/UV 4:2:2)
[3]: 'NV61' (Y/VU 4:2:2)
[4]: 'YM16' (Planar YUV 4:2:2 (N-C))
[5]: 'NV21' (Y/VU 4:2:0)
[6]: 'NV12' (Y/UV 4:2:0)
[7]: 'NM21' (Y/VU 4:2:0 (N-C))
[8]: 'NM12' (Y/UV 4:2:0 (N-C))
[9]: 'YU12' (Planar YUV 4:2:0)
[10]: 'YM24' (Planar YUV 4:4:4 (N-C))
Переопределяем настройки стримера:
root@kvmr0ck:~# cat << '_EOF_' > /etc/kvmd/override.yaml
kvmd:
hid:
mouse_alt:
device: /dev/kvmd-hid-mouse-alt # allow relative mouse mode
msd:
type: disabled
atx:
type: disabled
streamer:
quality: 0
resolution:
default: 1280x720
available:
- 1920x1080
- 1600x1200
- 1360x768
- 1280x1024
- 1280x960
- 1280x800
- 1280x720
- 1024x768
- 800x600
- 720x576
- 720x480
- 640x480
cmd:
- "/usr/bin/ustreamer"
- "--device=/dev/kvmd-video"
- "--persistent"
- "--format=uyvy"
- "--resolution={resolution}"
- "--desired-fps={desired_fps}"
- "--drop-same-frames=30"
- "--unix={unix}"
- "--unix-rm"
- "--unix-mode=0660"
- "--exit-on-parent-death"
- "--process-name-prefix={process_name_prefix}"
- "--notify-parent"
- "--no-log-colors"
- "--jpeg-sink=kvmd::ustreamer::jpeg"
- "--jpeg-sink-mode=0660"
- "--slowdown"
_EOF_
И снова проверяем:
root@kvmr0ck:~# systemctl restart kvmd
root@kvmr0ck:~# systemctl status kvmd
● kvmd.service - PiKVM - The main daemon
Loaded: loaded (/lib/systemd/system/kvmd.service; enabled; preset: enabled)
Active: active (running) since Sat 2024-12-14 19:51:03 MSK; 48s ago
Main PID: 5151 (kvmd/main: /usr)
Tasks: 29 (limit: 82)
Memory: 66.7M
CPU: 10.147s
CGroup: /system.slice/kvmd.service
├─5151 "kvmd/main: /usr/bin/python /usr/bin/kvmd --run"
├─5156 "kvmd/hid-keyboard: /usr/bin/python /usr/bin/kvmd --run"
├─5157 "kvmd/hid-mouse: /usr/bin/python /usr/bin/kvmd --run"
├─5158 "kvmd/hid-mouse: /usr/bin/python /usr/bin/kvmd --run"
└─5511 "kvmd/streamer: /usr/bin/ustreamer --device=/dev/kvmd-video --persistent --format=uyvy --resolution=1280x720 --desired-fps=40 --drop-same-frames=30 --unix=/run/kvmd/ustreamer.sock --unix-rm --unix-mode=0660 ->
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.649 ] -- CAP: Using capture type: multi-planar
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.649 ] -- CAP: Using resolution: 1280x720
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.649 ] -- CAP: Using format: UYVY
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.649 ] -- CAP: Querying HW FPS changing is not supported
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.649 ] -- CAP: Using IO method: MMAP
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.654 ] -- CAP: Requested 5 device buffers, got 5
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.663 ] -- CAP: Capturing started
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.663 ] -- Using JPEG quality: 80%
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.663 ] -- Creating pool JPEG with 4 workers ...
Dec 14 19:51:50 kvmr0ck kvmd[5151]: kvmd.apps.kvmd.streamer INFO --- => -- INFO [591.665 ] -- Capturing ...
Выглядит как успех!
Demo
Коль все готово - почему бы не посмотреть в деле:
Closure
Стоит ли получившийся KVM своих денег, сложно сказать. Скорее нет, чем да. Но! Но он работает! Работает достаточно хорошо, чтобы делать траблшутинг любой сложности и в целом иметь в кармане довольно мощную железку. Да, есть заметный input lag и в игрушки не поиграешь, но так ли это важно для типичного ops и при цене одного вечера в пабе?
Вот что действительно расстроило, так это CSI разъем у Radxa Zero 3W. Какой-то он хлипкий и нуждается в улучшении, может доберусь до колхозинга, и вы прочтете еще один пост. Кто знает ;)
Небольшое сравнение с остальными представителями читайте в KVMBattle.