Я давно использую одноплатные компьютеры Repka Pi. У меня есть Repka Pi 3 и Repka Pi 4, и обе платы используются не только для экспериментов.
Repka Pi 3 у меня уже работает как небольшой сервер, а Repka Pi 4 я начал рассматривать как более универсальную платформу: сервер, рабочий стол, тестовая машина и стенд для работы с Linux.
В какой-то момент я понял, что хочу не просто установить систему на карту памяти и пользоваться тем, что есть. Мне хотелось получить нормальную воспроизводимую платформу, которую можно собирать самому, обновлять, патчить и получать удовольствие.
Так появилась идея сделать полноценную поддержку Repka Pi 4 в Armbian.
Я учусь на программной инженерии, поэтому этот проект для меня оказался хорошей возможностью выйти за пределы обычной разработки приложений и посмотреть, как на практике устроены загрузчик, Device Tree, ядро Linux, графический стек, ALSA и сборка Linux-дистрибутива.
Почему вообще Armbian #
У Repka есть собственная RepkaOS, и для обычного пользователя это самый простой вариант.
Записал образ, загрузился и работаешь.
Но есть проблемы которые слабо решаются в данной RepkaOS
А именно:
- Старое ядро
- Не возможность установить с SD карты на eMMC меньшего размера
- и другие мелочи
Мне хотелось:
- использовать современную Debian-based систему
- самостоятельно собирать Server и Desktop образы
- контролировать версию ядра
- обновлять U-Boot
- иметь воспроизводимый набор патчей
- отдельно собирать обычное и PREEMPT_RT ядро
Armbian для такой задачи подходит заметно лучше.
Самое важное здесь для меня то, что итоговая система теперь получается из исходников и набора понятных изменений.
Если я через полгода захочу понять, почему была добавлена конкретная настройка, я могу посмотреть Git history, а не вспоминать, какую команду когда-то вводил вручную на уже установленной системе.
U-Boot и память #
Одной из первых интересных проблем стала DRAM.
В разных сборках я увидел отличия в частоте памяти.
RepkaOS использовала более агрессивную конфигурацию, а стандартный U-Boot для H6 работал консервативнее.
В процессе экспериментов появлялась конфигурация:
CONFIG_DRAM_CLK=936
Но выяснилось, что это изменение существовало только внутри рабочего build tree и не было нормально зафиксировано в репозитории.
То есть получалась плохая ситуация:
Git repository != фактически собранный U-Boot
Для проекта, который должен быть воспроизводимым, так оставлять нельзя.
В итоге частоту я решил снизить до более консервативных:
CONFIG_DRAM_CLK=816
Это дает DDR3-1632.
Для нее был сделан отдельный U-Boot patch:
0002-set-repka-pi4-dram-clock-816.patch
Самая сложная проблема: Mali-T720 и Panfrost #
Графика оказалась самым большим приключением.
Repka Pi 4 использует:
Allwinner H6
Mali-T720
Mesa Panfrost
Сам GPU нормально определяется ядром:
Mali-T720 (Panfrost)
direct rendering: Yes
Accelerated: yes
HDMI также способен работать в:
3840x2160@60
Поэтому сначала казалось, что основная часть работы уже закончена.
Но в LXQt начали появляться графические артефакты.
В журнале ядра при этом возникали ошибки:
js=0
INSTR_INVALID_PC
Началось довольно долгое расследование.
Сначала подозревался LightDM #
Проблема была хорошо заметна уже на экране входа.
Поэтому естественной первой гипотезой был LightDM или GTK greeter.
Но затем выяснилось интересное.
Ошибки появлялись практически раз в минуту.
Причиной периодичности оказались часы LightDM:
изменилась минута -> перерисовался текст -> GPU fault
При вводе логина ошибки тоже начинали быстро увеличиваться.
Но сам LightDM оказался только удобным способом воспроизвести проблему.
xft-rgba=none
Очень важный результат появился после отключения RGB subpixel rendering.
При:
xft-rgba=rgb
ошибки стабильно воспроизводились.
При:
xft-rgba=none
они полностью исчезали в обычном desktop workload.
Мы проверили это довольно подробно.
Например:
| Тест | Minute faults | Typing faults | Всего |
|---|---|---|---|
| обычный RGB | 20 | 105 | 125 |
xft-rgba=none |
0 | 0 | 0 |
| RGB без часов | 0 | 63 | 63 |
| GPU фиксирован на 432 МГц | 14 | 105 | 119 |
Это позволило исключить несколько первоначальных гипотез.
Проблема практически точно не связана с:
-
Высокой частотой GPU
-
Переключениями devfreq
-
HDMI 4K60
-
LightDM
-
Часами
-
Самим LXQt
Проверка Mesa #
Следующим подозреваемым стала Mesa.
На системе использовалась Mesa 25.0.7.
Для теста я взял готовый arm64 stack Mesa 26.1.2 из Debian Trixie Backports и запустил его из отдельного prefix, не заменяя системные библиотеки.
Результат оказался практически одинаковым:
Mesa 25.0.7
125 faults
Mesa 26.1.2
121 faults
Значит простое обновление Mesa проблему не решает.
Rendercheck и XRender #
Дальше удалось убрать из уравнения даже GTK и Xft.
Через rendercheck выяснилось, что ошибка воспроизводится обычным:
XRenderComposite(Over)
Даже без ComponentAlpha.
Обычный Composite Over способен вызвать:
js=0 INSTR_INVALID_PC
То есть текущая область поиска уже выглядит примерно так:
XRender -> Xorg glamor -> Mesa Panfrost -> Mali-T720
Это уже гораздо более конкретная проблема.
Временное решение #
Корневой баг пока не исправлен.
Отключать аппаратное ускорение полностью я не хотел.
Например:
AccelMethod "none"
действительно убирает ошибки, но вместе с ними исчезает и нормальное GPU acceleration.
Поэтому пока выбран менее болезненный workaround:
Xft.rgba: none
Для LightDM:
xft-rgba=none
Это не исправление Panfrost.
Это именно временная мера, которая позволяет оставить glamor и аппаратное ускорение, но убрать наблюдаемые артефакты в обычной работе LXQt.
В репозитории это специально отмечено как workaround, чтобы в будущем не забыть удалить его после настоящего исправления драйвера.
3.5 мм Jack #
Еще одна проблема оказалась со звуком.
Сначала казалось, что аналоговый выход Repka Pi 4 вообще не работает в Armbian.
Но ALSA показывала полноценную карту:
card 1: ac200audio
Playback и Capture присутствовали.
После исследования mixer controls обнаружился нужный переключатель:
DAC I2S Playback Switch
Ручное включение:
amixer -c 1 cset name='DAC I2S Playback Switch' on
сразу дало звук через 3.5 мм Jack.
То есть проблема была не в DTS, не в ядре и не в самом AC200.
Не хватало правильной инициализации аудиотракта.
ALSA UCM2 #
Ставить amixer в автозагрузку мне не хотелось.
Это уже был бы настоящий костыль.
Для таких вещей в ALSA существует UCM2.
Проблема была в том, что стандартный:
alsa-ucm-conf
не содержит профиля для ac200-audio.
Поэтому для Repka Pi 4 был сделан собственный минимальный профиль.
Он включает:
DAC I2S Playback Switch
при активации HiFi playback.
После этого звуковой тракт выглядит нормально:
LXQt / audio server -> ALSA UCM -> AC200 -> DAC I2S -> 3.5 mm Line Out
И никаких ручных amixer после загрузки больше не требуется.
lm-sensors #
Казалось бы, добавить lm-sensors в образ должно быть самой простой задачей во всем проекте.
Но даже здесь удалось наступить на изменение Armbian build framework.
Сначала пакет добавлялся через:
PACKAGE_LIST_ADDITIONAL
Образ успешно собирался, но после загрузки:
sensors
не существовал.
Оказалось, что в новой версии Armbian этот способ уже не тот, который нужно использовать для board-specific packages.
В итоге пакет был перенесен в конфигурацию самой платы:
PACKAGE_LIST_BOARD="lm-sensors"
Это намного логичнее.
Теперь пакет относится к Repka Pi 4, а не к конкретному Server или LXQt образу.
MIDI и snd-seq #
Еще одна небольшая доработка появилась из-за MIDI.
В ядре понадобилась поддержка ALSA sequencer:
CONFIG_SND_SEQUENCER=m
Я специально собираю ее как модуль.
Получается:
snd-seq.ko
Он доступен системе, но не обязан постоянно находиться в памяти.
Такой функционал был вынесен в общий kernel profile, который используется:
Server
PREEMPT_RT
LXQt
То есть это уже не настройка конкретного desktop-образа, а характеристика самой платформы.
Bluetooth #
С Bluetooth возник уже скорее архитектурный вопрос.
Изначально его пакеты устанавливались только в LXQt.
Но Bluetooth может понадобиться и на Server, и в PREEMPT_RT образе.
Поэтому BlueZ правильнее устанавливать глобально.
При этом постоянно работающий Bluetooth на маленькой ARM-плате тоже не всегда нужен.
bluetoothd в простое потреблял немного:
CPU около 0.2%
RSS около 6 MiB
Это совсем немного.
Но для Server и RT нет смысла держать даже его, если Bluetooth не используется.
Поэтому политика сейчас планируется разная.
Server / RT #
BlueZ установлен
bluetooth.service disabled
Bluetooth radio off
То есть функциональность есть, но никакие ресурсы по умолчанию не расходуются.
LXQt #
Для рабочего стола удобство важнее нескольких мегабайт RAM.
Поэтому:
bluetooth.service active
AutoEnable=false
Bluetooth radio off
Daemon готов к работе, но сам адаптер не включается.
Пользователь открывает Blueman и сразу включает Bluetooth без терминала и systemctl.
Обновление Armbian #
Еще один плюс собственного проекта заключается в том, что upstream Armbian можно обновлять независимо от наших изменений.
Сейчас build framework фиксируется на конкретном Git tag и commit.
Например:
v26.11.0-trunk.22
3da49cffcb8ac58a919d86816fec4659c410ff1e
Это важно для воспроизводимости.
Нельзя просто каждый раз собирать случайный main и надеяться, что результат будет тем же.
Схема получается такая:
Armbian release -> Git commit -> Repka patches -> image
Обновление upstream тоже делается отдельным Git commit.
Если новая версия Armbian что-то ломает, ее можно откатить независимо от поддержки самой Repka.
А что с Repka Pi 3 #
В какой-то момент стало понятно, что проект не ограничится одной Repka Pi 4.
На Repka Pi 3 обнаружились похожие организационные проблемы:
-
нужен
lm-sensors -
нужен общий Bluetooth policy
-
нужен
snd-seq.ko
Но прямое копирование патчей с Pi 4 здесь невозможно.
Например, Pi 4 использует AC200, а Pi 3 показывает:
H3 Audio Codec
то есть работает через встроенный H5 codec.
Поэтому общая инфраструктура может быть одинаковой, а board-specific части должны оставаться раздельными.
Это еще одна причина, почему я постепенно ухожу от набора случайных shell-команд к нормальной структуре проекта.
Что уже работает #
На текущем этапе для Repka Pi 4 удалось получить:
-
загрузку современного Armbian
-
Linux 6.18
-
актуальный U-Boot
-
DRAM на 936 МГц
-
Server image
-
LXQt image
-
PREEMPT_RT profile
-
Ethernet
-
Wi-Fi
-
Bluetooth
-
HDMI 4K60
-
Panfrost acceleration
-
временную защиту от desktop-артефактов Panfrost
-
работающий AC200 и 3.5 мм Jack через ALSA UCM
-
lm-sensors -
ALSA MIDI Sequencer как
snd-seq.ko.
Но работа еще далеко не закончена.
Что осталось #
Главная нерешенная техническая проблема сейчас находится в графическом стеке.
Нужно дойти от:
XRenderComposite -> INSTR_INVALID_PC
до конкретного shader binary, GPU address или job descriptor, который ломается на Mali-T720.
То есть следующий уровень расследования оборачивается вокруг Mesa/Panfrost.
Что мне дал этот проект #
Наверное, самая интересная часть работы над Armbian для Repka заключается в том, насколько быстро исчезает граница между "программированием" и "железом".
Для меня как студента программной инженерии это очень полезный проект.
Один commit может изменить частоту DRAM.
Другой добавить модуль ядра.
Третий исправить маршрутизацию физического аудиовыхода.
А ошибка в одной строке Device Tree потенциально может сделать целый аппаратный блок недоступным.
Именно поэтому я хочу продолжать этот проект Repka Pi в Armbian.
Спасибо за внимание!