Hardwarové limity: hodiny, SPI a displej
Jak spolu souvisí jádrový clock, periferní clock a display SPI na deskách RP2, kde jsou skutečné stropy a jak testovat, když je překračujete. Napsáno z měření na PicoPadu (RP2040) a na PicoPadu s čipem vyměněným za RP2350 (Pico 2).
Doplňuje HARDWARE.md (rozpočet RAM, nasazení) a FEATURES.md §18 (rychlý vs. přenositelný renderer, kam vlastně mizí FPS).
1. Řetězec hodin (co řídí co)
Sekce “1. Řetězec hodin (co řídí co)” PLL_SYS ──> clk_sys ──> jádra CPU └─────> clk_peri ──> SPI, UART, … (CircuitPython: clk_peri = clk_sys, neděleno) XIP/QMI flash clock je odvozen také z clk_sys (samostatná dělička) PLL_USB ──> 48 MHz USB (nezávislé — USB-CDC REPL není overclockingem ovlivněn)Dva důsledky, které řídí vše níže:
clk_perinásledujeclk_sys. Na CircuitPythonu je periferní clock systémovým clockem, neděleno. Takže změna jádrového clocku mění vstupní clock SPI — a tedy i clock displeje. Nemůžete ladit jedno bez přemýšlení o druhém.- Výchozí
clk_sysse liší podle čipu: RP2040 = 125 MHz, RP2350 = 150 MHz. Konstanta vyladěná pro jeden čip dopadne na druhém jinak (viz §3).
2. Jak je odvozen clock display SPI
Sekce “2. Jak je odvozen clock display SPI”Displej je ST7789 na čtyřvodičové sběrnici SPI. Jeho clock pochází z periferie PL022 SPI,
která dělí clk_peri sudým celým číslem (CPSDVSR × (1+SCR)), a SDK vybírá
děličku tak, aby skutečný clock byl nejvyšší dosažitelný, který NEPŘEKROČÍ váš požadavek:
actual_spi_hz = clk_peri / even_divider # největší výsledek <= požadovaný baudrateBaudrate požadujete v board.c (common_hal_fourwire_fourwire_construct(... baudrate ...)).
Požadavek je strop, ne přesná hodnota — pokud přesná hodnota není sudým dělením
clk_peri, dostanete tu nejbližší nižší.
Propočtené příklady (ve všech případech požadavek 62,5 MHz):
| clk_peri (= clk_sys) | sudé dělitele kolem 62,5 | vybráno | skutečné SPI |
|---|---|---|---|
| 125 MHz (RP2040 stock) | /2 = 62,5 | /2 | 62,5 MHz (přesně) |
| 150 MHz (RP2350 stock) | /2 = 75 (> 62,5, zamítnuto), /4 = 37,5 | /4 | 37,5 MHz |
| 200 MHz | /2 = 100 (zam.), /4 = 50 | /4 | 50 MHz |
| 225 MHz | /2 = 112,5 (zam.), /4 = 56,25 | /4 | 56,25 MHz |
| 250 MHz | /2 = 125 (zam.), /4 = 62,5 | /4 | 62,5 MHz (přesně) |
Klíčová past: stejný požadavek 62,5 MHz dá 62,5 na RP2040 (125/2), ale jen 37,5 na
stock-150 MHz RP2350 (protože 150/2 = 75 přestřelí a zaokrouhlí dolů na 150/4). Abyste dostali dobrý
display clock na RP2350, musíte zvolit clk_sys, jehož sudá dělení dopadnou tam, kde chcete —
např. 250 MHz → /4 = přesně 62,5 MHz, maximum v rámci specifikace (viz §3, §4).
Abyste dostali clock SPI, musíte požadovat request = actual nebo vyšší, ale pod 2×actual;
bezpečné pravidlo je požadovat přesně clock, který chcete a ověřit, kterou děličku vybral.
3. Limit z datasheetu (a jeho překračování)
Sekce “3. Limit z datasheetu (a jeho překračování)”Datasheet ST7789 udává sériový zápisový clock na tSCYCW = 16 ns min → max 62,5 MHz (čtení je mnohem pomalejší, ~6,6 MHz, ale displej je zde jen pro zápis). Takže 62,5 MHz je strop v rámci specifikace pro posílání pixelů.
V praxi panel na dané desce často běží nad specifikací:
- Na tomto PicoPadu 75 MHz SPI (RP2350 na 150 MHz, /2) vytvořilo čistý obraz — ~20 % nad specifikací, na tomto kusu funguje při pokojové teplotě.
- „Funguje tady” není „garantováno všude”: clocking nad specifikací může selhat na jiném panelu, při teplotních extrémech, při jiném napětí nebo na delší/horší kabeláži. Berte to jako experiment na konkrétním kusu, ne jako nasaditelný výchozí stav.
Protože PL022 dělí jen sudými celými čísly, z daného clk_sys máte obvykle jen
dvě volby ohraničující specifikaci — např. ze 150 MHz: 75 (nad) nebo 37,5 (hluboko pod),
nic na 62,5. Volba clk_sys je způsob, jak trefit dobrý clock v rámci specifikace (250 → 62,5).
4. Overclocking jádra
Sekce “4. Overclocking jádra”Naměřený závěr na této desce: overclocking je ČISTĚ NEGATIVNÍ — nedělejte to. Zní to lákavě (většina práce v picogame je vázaná na CPU/MicroPython a 250 MHz by dokonce trefilo SPI na přesných 62,5 MHz v rámci specifikace), ale na reálném hardwaru každý režim rendereru vyšel ~2× pomaleji overclocknutý než na stock 150 MHz:
režim stock 150 MHz overclock 225 MHz HEAVY (vázáno na CPU/blit) ~31 fps ~15 fps STRESS (celosnímkové, vázáno na SPI) ~44 fps ~16 fps výchozí (dirty-rect) ~95 fps ~42 fps Proč to selhává: zvýšení
clk_sysbez přeladění flash timingu QMI/XIP způsobí, že se kód vykonává z flash s wait-states. Jádro tiká rychleji, ale propustnost instrukcí klesá — a ta ztráta převáží zisk z clocku. CircuitPythonovéset_sys_clock_khz(ať přesmicrocontroller.cpu.frequencynebo voláníboard_init) flash nepřeladí; návrhy, které úspěšně overclockují (např. PicoDVI na 252 MHz), spouští svou horkou smyčku z RAM, ne z XIP. Přeladění timingu QMI pro nový clock je specifické pro daný flash čip a háklivé, a navíc 250 MHz nezávisle rozházelo displej (§4b) — takže praktická odpověď je zůstaňte na stock clocku a rychlost displeje získejte z děličky SPI (§2/§3).
Poznámky níže jsou ponechány, protože stále platí, pokud byste někdy overclockovali (a ta dvě pravidla jsou způsob, jak se vyhnout zničení displeje, než to zjistíte).
Dvě těžce vydobytá pravidla
Sekce “Dvě těžce vydobytá pravidla”(a) Nastavte clock při BOOTU, v board.c board_init(), PŘED konstrukcí display SPI —
NE za běhu. Změna microcontroller.cpu.frequency za běhu poškodí živý ST7789:
skok napětí VREG (CircuitPython zvyšuje napětí jádra pro >133 MHz) a glitch při rekonfiguraci
PLL naruší clk_peri, zatímco je panel uprostřed transakce, a rozhází ho. Naměřeno: změna za běhu
na jakoukoli hodnotu ≥133 MHz rozházela displej; ≤120 MHz (bez změny VREG) bylo v pořádku.
Provedení v board_init před existencí displeje glitch zcela odstraní:
#include "hardware/clocks.h"#include "hardware/vreg.h"#include "hardware/timer.h"
void board_init(void) { vreg_set_voltage(VREG_VOLTAGE_1_20); // vyžadováno pro >133 MHz busy_wait_us(10000); // nech napětí ustálit set_sys_clock_khz(225000, true); // AŽ PAK zvyš clock // ... teprve teď konstruuj display SPI (inicializuje se na finálním clk_peri) ...}Napěťové úrovně VREG, které CircuitPython používá: ≤133 MHz → 1,10 V, >133 MHz → 1,20 V, ≥300 MHz → 1,20 V, ≥400 MHz → 1,30 V.
(b) Skutečným stropem je displej, ne čip. Čip RP2350 nabootoval a běžel v pořádku na 250 MHz (jednoduchá hra jako Train byla čistá), ale náročné renderování ukázalo artefakty kolem dirty regionů: na 250 MHz vydává CPU příkazy nastavení okna pro jednotlivé obdélníky (CASET / RASET / RAMWR plus přepínání GPIO DC/CS) rychleji, než je ST7789 spolehlivě zachytí, takže občas okno dopadne špatně a strip se zapíše mírně mimo. To je efekt jádrového clocku, ne datové rychlosti SPI: objevil se na 250 MHz/62,5 MHz SPI, zatímco 150 MHz/75 MHz SPI bylo čisté (pomalejší SPI, rychlejší jádro → stejně se to rozbilo). Projevuje se všude, kde je mnoho nastavení okna na snímek (spousta dirty rectů, celosnímkové překreslení), a sotva u lehkých dirty-rect her.
Binární vyhledávání na této desce našlo strop displeje: 150 · 200 · 225 MHz čisté · 250 MHz dirty (limit příkazů panelu mezi 225 a 250). Ale viz rámeček výše — i na čistých 200/225 deska běžela celkově ~2× pomaleji (flash/XIP), takže se deska dodává jako stock 150 MHz, ne overclock. Pákou zde není clock; je to dělička SPI.
Kompromis
Sekce “Kompromis”Overclocking zvedá CPU, ale (přes pravidlo sudé děličky) často snižuje SPI clock v rámci specifikace:
| Build | jádro | display SPI | výsledek |
|---|---|---|---|
| stock + „spi75” (dodávaný) | 150 MHz | 75 MHz (nad specifikací, zde čisté) | celkově nejrychlejší na této desce |
| boot-225 (zamítnuto) | 225 MHz | 56,25 MHz (v rámci specifikace) | ~2× pomalejší (flash/XIP — viz rámeček v §4) |
Nižší SPI overclocku i jeho flash penalizace tlačily oba špatným směrem, takže
doporučená konfigurace RP2350 PicoPadu je stock 150 MHz s požadavkem 75 MHz SPI (/2).
Takže vybírejte podle své zátěže: hra vázaná na CPU → overclock; celosnímkové/náročné na přenos → držte jádro nízko a SPI vysoko. Z jedné sudé děličky nemůžete maximalizovat obojí.
5. Jak to testovat
Sekce “5. Jak to testovat”Použijte examples/picogame_bench.py — jeho přepínače izolují každý režim:
| Přepínač | Izoluje | Čtení |
|---|---|---|
FAST = True/False | rychlý DMA vs. přenositelný renderer | liší se? (liší se jen vícestripové přenosy) |
STRESS = True | vynutí celosnímkové překreslení každý snímek | strop vázaný na SPI (∝ SPI clock) |
HEAVY = True | pár velkých scale+rotate spritů | případ vázaný na CPU/blit (∝ jádrový clock) |
OVERCLOCK = … | jádrový clock za běhu | na PicoPadu nechte None — změna za běhu poškodí displej; overclockujte při bootu ve firmwaru |
Čtení výsledků:
- Výchozí režim (malé sprity) je špatná metrika — 25 rozházených spritů přestřelí strop 6
dirty rectů, sloučí se do téměř celoobrazovkového ohraničujícího boxu a stanou se proměnlivě velkým
celosnímkovým přenosem. FPS divoce kolísá podle toho, jak se sprity náhodou seskupí. Použijte
STRESS(deterministický celý snímek) neboHEAVY(deterministická zátěž CPU) pro čistá čísla. STRESSFPS škáluje s SPI clockem (vázáno na přenos). Pokud zdvojnásobení SPI clocku ho ~zdvojnásobí, jste tam vázáni na SPI.HEAVYFPS škáluje s jádrovým clockem (vázáno na blit). Zde se overclock vyplatí.
Rozpoznání overclocku, který je pro displej příliš vysoký:
- Artefakty kolem / na okrajích dirty regionů, rozmazání nebo posunuté stripy v náročném renderování — zatímco lehká scéna (nebo jednoduchá hra) stále vypadá dobře. To je strop časování příkazů okna (§4b), ne pád.
- Clock příliš vysoký pro čip/flash naopak selže tvrději: buď nenabootuje, nebo hard-faultne.
- Záchrana je vždy BOOTSEL: podržte BOOTSEL, znovu naflashujte známý funkční
.uf2. Overclock nemůže desku trvale zničit.
Hledání stropu: buildněte firmwary na sestupných jádrových clockách (250 → 225 → 200 → …), naflashujte každý,
spusťte STRESS + HEAVY a ponechte nejvyšší clock bez artefaktů v dirty regionech. Měňte
clock jen v board.c board_init (ne za běhu) a znovu zkontrolujte, kterou SPI děličku nový
clk_peri vybral (§2).