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 STORAGESaí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).
| Nó | O que mudamos | Por quê |
|---|---|---|
cpu0_opp_table | Adicionada OPP turbo de 1512 MHz @ 1.4 V; mantida a escada completa 408–1416 | Acessível via "Enable CPU Overclock" |
Regulador vdd_arm | regulator-max-microvolt 1.35 V → 1.45 V | Caso contrário o kernel rejeita a OPP de 1512 silenciosamente |
gpu_opp_table | Restauradas as OPPs inferiores de 200/300/400 MHz; adicionadas as superiores de 600/650 MHz | OPPs baixas são necessárias para o boot; 650 MHz é o turbo diário a 1.150 V |
dmc / dfi | Definidos explicitamente para que o devfreq possa ser controlado | O px30.dtsi upstream os mantém desabilitados |
gpu | Adicionados clock-names="bus", resets, power_policy="coarse_demand", power_models | Necessário para panfrost/mali_kbase modernos |
Alias ethernet0 | Adicionado | Nomeação futura para hot-plug de USB-Ethernet |
| Power model | mali-simple-power-model + mali-g31-power-model | DVFS 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 avisosunbalanced disables for vdd_logicquandovdd_logicé compartilhado com rockchip-pm-domain. Adiciona um flaggpu_power_heldque acompanha o estado de enable do próprio driver.linux/0005-drm-panfrost-Add-SYSTEM_TIMESTAMP*.patch: requerido pelo Mesa 26.0.5 para queriesGL_TIMESTAMPeVK_KHR_calibrated_timestamps.linux/0006-drm-panfrost-Add-cycle-counter-job-requirement.patch: encanamento paraVK_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=128MBWhitelist 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
| Original | Clone | |
|---|---|---|
| Origem | bootloader/u-boot-rk3326/ (BSP) | mainline + patches do ROCKNIX |
| Config de boot | boot.ini | boot.scr (mkimage -T script) |
| Display | hwrev SARADC ch0 → DTB da placa → DRM → logo.bmp | nenhum |
| Defconfig | odroidgoa | rk3326-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, screenshotsO 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 jogarO 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 Y3506O gerador (config/mipi-generator/generator.sh → archr-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 + SRs258 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.