ARCH R

Referência técnica

Kernel, Mesa, U-Boot, DTS, pipeline de build

Pipeline de build

make docker-RK3326 executa todo o sistema de stages no estilo LibreELEC dentro do Docker. Aproximadamente 700 passos de instalação para ~263 pacotes.

toolchain    cross-gcc 14.2 / glibc / binutils (stage do host)
linux        kernel 6.12 LTS + DTS do RK3326 + patches do ArchR
mali-bifrost mali_kbase out-of-tree + patch de PM unbalance do ArchR
mesa         26.0.5 Panfrost (GLES 3.1, +speed +lto)
zlib (-ng)   zlib-ng 2.2.4 em modo --zlib-compat (libz.so.1)
retroarch    1.x + conjunto de cores libretro
emulators    Flycast, PPSSPP, melonDS, DraStic, Yabasanshiro, Mupen64Plus standalone
es           EmulationStation (fork do ROCKNIX)
image        FAT32 BOOT (272 MB, clusters de 4 KB) + ext4 ROOT + ext4 STORAGE

Saída em target/ArchR-R36S.aarch64-DATE-{original,clone}.img.gz.


Kernel

Source       Linux 6.12 LTS (fork BSP, patches da Rockchip + ArchR)
Toolchain    gcc 14.2.0
Config       projects/ArchR/devices/RK3326/linux/linux.aarch64.conf
HZ           300
PREEMPT      CONFIG_PREEMPT=y (A/B com PREEMPT_VOLUNTARY pendente de bench)
DEBUG        todos os sanitizers / KASAN / KMEMLEAK / FTRACE desligados no release
DEBUG_FS     y (intencional, necessário para debugfs do CMA e introspecção de PSI)
CMA          96 MB (subiu de 64 MB após auditoria; veja /docs/features)
ZRAM         lzo-rle por padrão (zstd opcional via memory-manager)
ZSWAP        desabilitado (zswap.enabled=0 na cmdline)

DTS

Origem: rk3326-gameconsole-r36s.dts (placa) + rk3326-gameconsole-r3xs.dtsi (família de placas) + px30.dtsi (SoC) + 000-rk3326-dts.patch (overrides do ArchR).

O que mudamosPor quê
cpu0_opp_tableAdicionada OPP turbo de 1512 MHz @ 1.4 V; mantida a escada completa 408–1416Acessível via "Enable CPU Overclock"
Regulador vdd_armregulator-max-microvolt 1.35 V → 1.45 VCaso contrário o kernel rejeita a OPP de 1512 silenciosamente
gpu_opp_tableRestauradas as OPPs inferiores de 200/300/400 MHz; adicionadas as superiores de 600/650 MHzOPPs baixas são necessárias para o boot; 650 MHz é o turbo diário a 1.150 V
dmc / dfiDefinidos explicitamente para que o devfreq possa ser controladoO px30.dtsi upstream os mantém desabilitados
gpuAdicionados clock-names="bus", resets, power_policy="coarse_demand", power_modelsNecessário para panfrost/mali_kbase modernos
Alias ethernet0AdicionadoNomeação futura para hot-plug de USB-Ethernet
Power modelmali-simple-power-model + mali-g31-power-modelDVFS com consciência térmica

Patches de kernel

Patches de kernel específicos do ArchR mais relevantes (projects/ArchR/packages/linux-drivers/mali-bifrost/patches/6.12-LTS/ e projects/ArchR/packages/linux/patches/6.12-LTS/):

  • mali-bifrost/002-fix-unbalanced-regulator-clk-pm.patch: elimina os avisos unbalanced disables for vdd_logic quando vdd_logic é compartilhado com rockchip-pm-domain. Adiciona um flag gpu_power_held que acompanha o estado de enable do próprio driver.
  • linux/0005-drm-panfrost-Add-SYSTEM_TIMESTAMP*.patch: requerido pelo Mesa 26.0.5 para queries GL_TIMESTAMP e VK_KHR_calibrated_timestamps.
  • linux/0006-drm-panfrost-Add-cycle-counter-job-requirement.patch: encanamento para VK_KHR_shader_clock.
  • linux/0007-0010-drm-panfrost-Add-BO-labelling*.patch: auxílio de debug; o Mesa chama o novo IOCTL ainda que os labels sejam apenas para debug.

Mesa 26.0.5

Compilado com +speed +lto em packages/graphics/mesa/package.mk. Flags do configure:

-Dgallium-drivers=panfrost   -Dvulkan-drivers=
-Dgles1=disabled             -Dgles2=enabled
-Dglvnd=disabled             -Dplatforms=wl
-Dglx=disabled               -Dshader-cache=enabled
-Dopengl=true                -Dgbm=enabled
-Degl=enabled                -Dlibunwind=disabled
-Dbuild-tests=false          -Ddraw-use-llvm=false

-Dgallium-drivers=panfrost apenas, sem fallback de software no release (o overhead do LLVMpipe seria maior que o hardware no G31). -Dvulkan-drivers= vazio porque o PanVK não é conformante em Bifrost v9.

Variáveis de runtime

Exportadas globalmente em /etc/profile.d/041-panfrost:

PAN_MESA_DEBUG=forcepack             # dica de format-pack específica do G31
MESA_NO_ERROR=1
MESA_SHADER_CACHE_DIR=/storage/.cache/mesa_shader_cache
MESA_SHADER_CACHE_MAX_SIZE=128MB

Whitelist MESA_GLTHREAD=true por emulador, apenas Flycast e PPSSPP standalone (veja GPU driver e o docs/mesa-glthread-matrix.md no repo).


libmali (alternativo)

mali_kbase out-of-tree r52p0-00eac0 com o patch de PM do regulador/clk. Trocado no boot via /usr/bin/gpudriver --start, que lê /storage/.config/system.cfg → gpu.driver. Fallback automático se algum dos drivers falhar em se ligar ao nó da GPU.


U-Boot

OriginalClone
Origembootloader/u-boot-rk3326/ (BSP)mainline + patches do ROCKNIX
Config de bootboot.iniboot.scr (mkimage -T script)
Displayhwrev SARADC ch0 → DTB da placa → DRM → logo.bmpnenhum
Defconfigodroidgoark3326-handheld_defconfig

Os dois binários diferem o suficiente para que não seja possível dar boot num clone com o build do BSP. O ArchR entrega ambos; o build escolhe com base em --variant (ou make docker-RK3326 produz os dois).


Layout da imagem

GPT
├── 1   FAT32  BOOT     272 MB    65525+ clusters de 4 KB (conforme spec FAT32)
│                       Kernel, DTBs, todos os 43 panel overlays, script U-Boot
├── 2   ext4   ROOT     ~4.6 GB   sistema read-only (squashfs em alguns builds antigos)
└── 3   ext4   STORAGE  resto     gravável: configs, ROMs, save-states, screenshots

O mkimage roda fsck.fat -a -w no FAT do BOOT antes de cimentar a imagem, o que garante que os setores de boot primário e backup fiquem byte a byte idênticos. O script fs-resize no dispositivo faz o mesmo depois que o fatlabel regenera o UUID, então o boot pós-resize continua consistente.


Fluxo de boot

0.0   POR / SPL (na ROM)
0.x   U-Boot lê SARADC ch0 → ID da placa
0.5   carrega DTB da placa + overlay do painel a partir de /flash/
0.7   splash do initramfs (BMP via xxd, /init estático em aarch64)
~7    entrega ao kernel
~9    target do systemd
~12   archr-autostart (quirks + governor + display + bluetooth + checagem de ssh)
~17   EmulationStation
~19   pronto para jogar

O trace é escrito em /storage/.boot_last_step antes de cada script de autostart rodar, e apagado em caso de sucesso. Se o boot anterior travou, o arquivo /storage/.boot_last_hang nomeia o script que travou. Inclua isso em relatos de bug.


Painéis de display

43 panel overlays gerados a partir de dumps de DTB dos fabricantes:

config/archr-dts/
├── original/    (15)   R36S V20–V22, variantes OGS
├── clone/       (18)   K36, R33S, R36 Max, RX6S, várias famílias de painel
└── soysauce/    (10)   hardware baseado no Y3506

O gerador (config/mipi-generator/generator.sharchr-dtbo.py) extrai a sequência de init e os timings do painel a partir do DTB do fabricante, aplica um template-base de overlay do ArchR e emite um .dtbo por revisão de placa-mãe. São produzidas seis variantes por painel:

default                    layout K36, sem swap JP, áudio normal
_JPk36                     layout K36, JP A↔B / X↔Y
_JPmm                      layout MyMini, swap JP
_SRs                       força caminho de áudio simples
_JPk36_SRs                 K36 + JP + SRs
_JPmm_SRs                  MyMini + JP + SRs

258 DTBOs no total. O Flasher (ou cópia manual) coloca um destes em /flash/overlays/mipi-panel.dtbo no momento da gravação.


Armadilhas

Casos extremos que apareceram durante o desenvolvimento. Nenhum se aplica a uma gravação normal de release. Só importam se você está mexendo no build.

Contagens de cabeçalho de hunk em patches DTS importam. Uma contagem @@ -X,Y +A,B @@ errada faz o patch abortar silenciosamente o resto dos hunks, deixando "lixo" recuperado. Valide com patch --dry-run --verbose sobre uma fonte limpa após cada edição de DTS.

OPPs de turbo-mode se escondem atrás de cpufreq/boost. Setar scaling_max_freq=1512000 diretamente não faz nada se boost=0. A frequência não aparece em scaling_available_frequencies até você escrever 1 em cpufreq/boost. O set_cpu_max_freq highest do ArchR lê tanto scaling_available_frequencies quanto scaling_boost_frequencies.

O regulator-max do vdd_arm controla a disponibilidade de OPPs silenciosamente. Se uma OPP solicita uma tensão acima de regulator-max-microvolt, o kernel descarta a OPP sem nada no dmesg, e policy_has_boost_freq() retorna false → o sysfs cpufreq/boost nunca é criado.

fatlabel -i -r dessincroniza primário/backup do FAT. Reescreve UUID/label apenas no setor 0; o backup no setor 6 mantém os valores antigos. Alguns builds de U-Boot ocasionalmente leem o backup, causando travas intermitentes de boot após o resize. Solução: rodar fsck.fat -a -w em seguida.

Avisos de patch.fat / cluster < 65525 são na maioria inofensivos, mas ocasionalmente atrapalham versões específicas de ROM do U-Boot. O ArchR usa BOOT_SIZE=272 MB com clusters de 4 KB → 69500+ clusters → acima da spec.

O diretório raiz do shader cache do Mesa precisa existir. O Mesa não vai fazer mkdir em MESA_SHADER_CACHE_DIR por conta própria; apenas cai silenciosamente para modo sem cache. O runemu.sh cria /storage/.cache/mesa_shader_cache se estiver faltando.

panfrost_devfreq precisa de OPPs baixas de GPU para inicializar. Remover as OPPs de 200/300/400 MHz (para forçar um piso mais alto) bloqueia a inicialização da GPU no boot. O driver espera que a menor OPP publicada seja alcançável. Mantenha a escada; force um piso alto em runtime com set_gpu_min_freq highest.

PREEMPT vs PREEMPT_VOLUNTARY ainda não foi bencheado. O kernel atualmente usa PREEMPT; o ROCKNIX usa VOLUNTARY. A/B pendente com o bench no dispositivo.

O unbalance do regulador no mali_kbase é um patch de kernel, não um quirk. Sem o 002-fix-unbalanced-regulator-clk-pm.patch, cada transição de PM emite unbalanced disables for vdd_logic e Enabling unprepared clk_gpu, audível como estalo no Mario 64.

On this page