8 мин на чтение

В этом посте речь пойдет о сборке и установке PiKVM на Radxa ZERO 3W с HDMI-CSI bridge C790. Должен получится крепкий среднячок, а там как получится %)

cover

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:

Hardware: assemble

Тут сложно сделать что-то не так, ведь единственное, что предстоит изготовить - USB/Power Splitter. Можно было бы и найти готовый (e.g. USB/Power Splitter for Raspberry Pi BliKVM and PiKVM), но не вижу смысла, ведь это просто пара коннекторов с резисторами: cover Не уверен в острой необходимости pull-up/pull-down резисторов, но по стандарту они нужны - решил оставить.

Осталось дело за малым - запаять и подсобрать: cover

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.

Разделы: ,

Дата изменения: