carsten's blog

Debian

Orange Pi 3: Warum der Warmstart hängt – und wie ein Device-Tree-Umbau den PMIC zurückholt

by on Oct.29, 2026, under Armbian, Debian, Hardware, Linux, SBC

TL;DR: Auf meinem Orange Pi 3 (Allwinner H6, Armbian) bootete das System nach einem reboot nicht mehr – nur Strom ziehen half. Ursache: Die Firmware (ATF/Crust) spricht den Power-Management-Chip AXP805 über den RSB-Bus an und schaltet ihn dabei in den RSB-Modus. Der überlebt einen Warmreset. Armbians Device Tree lässt Linux den PMIC aber über I2C ansprechen – nach dem Warmstart antwortet er dort nicht mehr, ohne PMIC gibt es keine Spannungsregler, ohne Regler keine SD-Karte, und der Kernel wartet ewig auf sein Root-Dateisystem. Lösung: ein DTB, in dem der PMIC unter rsb@7083000 hängt, plus ein apt-Hook, der diesen DTB nach Kernel-Updates neu erzeugt.


Ausgangslage

Der Orange Pi 3 läuft bei mir als kleiner Infrastruktur-Server im Keller (Pi-hole, DNS, VPN & Co.). Eines Tages kam er nach einem Ansible-Update-Lauf nicht mehr hoch. Das interne eMMC meldete sich als verschlissen (life_time 0x0B, „Card stuck being busy“), also: Backup auf eine SD-Karte, davon booten – läuft.

Bis auf ein Detail: Ein reboot endete jedes Mal im Nichts. Kein Ping, kein SSH. Nur ein Power-Cycle brachte das Board zurück. Naheliegender Verdacht: das kaputte eMMC stört den Boot.

Werkzeug: serielle Konsole aus der Ferne

Ohne Konsole rät man nur. Also kam ein USB-TTL-Adapter an den Debug-UART des OPi und an einen Raspberry Pi daneben (115200 8N1; Klassiker: TX/RX zuerst vertauscht). Auf dem Raspberry Pi läuft eine screen-Sitzung mit Logfile, dazu zwei kleine Skripte:

  • Autoboot-Stopper: wartet im Log auf „U-Boot“ und sendet dann alle 100 ms ein Leerzeichen, bis der Prompt => erscheint.
  • Boot-Helfer: setzt am Prompt Variablen (extraargs, fdtfile) per screen -X stuff und prüft jeweils das Echo, dann boot.

Kleine Falle am Rande: screen schreibt sein Log erst bei Zeilenende. Der Prompt => taucht deshalb erst auf, nachdem man ein CR hinterhergeschickt hat.

Schritt 1: Ist es das eMMC?

Erster Versuch: das eMMC (mmc2) per Device-Tree-Overlay komplett abschalten.

/dts-v1/;
/plugin/;
/ {
    compatible = "xunlong,orangepi-3", "allwinner,sun50i-h6";
    fragment@0 {
        target = <&mmc2>;
        __overlay__ { status = "disabled"; };
    };
};

Das funktioniert (u-boot meldet „Applying user provided DT overlay“, die eMMC-Fehler sind weg) – aber der Warmstart hängt weiterhin. Das eMMC war also nur ein zufällig gleichzeitiger Defekt.

Schritt 2: Warm gegen kalt vergleichen

Mit der seriellen Konsole lassen sich Warm- und Kaltstart Zeile für Zeile vergleichen. Ergebnis: SPL, ATF (BL31), Crust und u-boot laufen identisch durch, bis Starting kernel .... Danach: Stille.

Das liegt aber erst einmal nur daran, dass Armbian mit loglevel=1 startet und /dev/console auf tty1 (HDMI) liegt. Also am u-boot-Prompt, ohne Dateien zu ändern:

=> setenv extraargs "earlycon=uart8250,mmio32,0x05000000 ignore_loglevel keep_bootcon"
=> boot

Falle: earlycon=uart8250,mmio32,0x05000000,115200n8 sieht richtiger aus, liefert aber Zeichensalat. Mit Baudrate rechnet der Kernel mit einem angenommenen UART-Takt von 1,8432 MHz statt der tatsächlichen 24 MHz. Ohne Baudrate übernimmt er einfach die Einstellung von u-boot.

Schritt 3: Der Kernel spricht

Der erste Lauf mit Debug-Ausgabe hing bei clk: Disabling unused clocks. Mit clk_ignore_unused kam der Kernel weiter, hing dann aber beim Warten auf das Root-Dateisystem. Ein Blick weiter oben im Log zeigte den eigentlichen Fehler:

axp20x-i2c 0-0036: AXP20x variant AXP806 found
axp20x-i2c 0-0036: Failed to set masks in 0x40: -6
axp20x-i2c 0-0036: failed to add irq chip: -6
...
platform 4020000.mmc: deferred probe pending: platform: wait for supplier /soc/i2c@7081400/pmic@36/regulators/cldo1
platform 5020000.ethernet: deferred probe pending: platform: wait for supplier /soc/i2c@7081400/pmic@36/regulators/aldo2

Beim Kaltstart steht an derselben Stelle AXP20X driver loaded.

Die Kette ist damit klar: Ohne PMIC-Treiber gibt es keine Spannungsregler. Ohne Regler bleiben SD-Controller, Pin-Controller und Ethernet im „deferred probe“, und rootwait wartet für immer. Der Hänger bei den Clocks war nur eine Folge davon.

Falle Nr. 2: „AXP806 found“ klingt, als hätte der Kernel den Chip erfolgreich gelesen. Tatsächlich stammt die Meldung aus dem Abgleich mit dem Device Tree, ohne jeden Buszugriff. Der erste echte Zugriff ist das Schreiben der IRQ-Masken, und der scheitert mit -6 (ENXIO). Beim I2C-Treiber heißt das: NAK, unter Adresse 0x36 antwortet niemand.

Schritt 4: Warum antwortet der PMIC nicht mehr?

Ein Warmreset setzt nur den SoC zurück, nicht den PMIC. Der AXP805 behält also den Zustand, den die Software vor dem Reset hinterlassen hat. Die Frage war: Wer fasst den PMIC zwischen reboot und dem nächsten Linux an?

Die Bootkette des H6 sieht so aus:

BROM → u-boot SPL → TF-A (BL31) → Crust (SCP-Firmware auf dem AR100-Kern) → u-boot → Linux

Ein reboot läuft so ab: Linux ruft PSCI SYSTEM_RESET auf, TF-A leitet das per SCPI an Crust weiter, und erst die Firmware führt den Reset aus.

Die Strings im Armbian-Bootloader-Binary (u-boot-sunxi-with-spl.bin) sind aufschlussreich:

PMIC: Probing AXP805 on RSB
RSB: set device to RSB
RSB: set run-time address
PSCI: SCPI %s failed: %d

Die Firmware kann den PMIC also über RSB ansprechen, Allwinners „Reduced Serial Bus“. Der AXP805 startet nach dem Einschalten im I2C-Modus. Ein „set device to RSB“ schaltet ihn um, und zurück geht es erst mit einem Stromtrennen.

Der Device Tree von Armbian hängt den PMIC dagegen an den I2C-Bus:

i2c@7081400 {             /* r_i2c */
    status = "okay";
    pmic@36 {
        compatible = "x-powers,axp805", "x-powers,axp806";
        reg = <0x36>;
        ...
    };
};
rsb@7083000 {
    status = "disabled";
};

Genau dieses Szenario wurde 2021 schon auf der Kernel-Mailingliste diskutiert. Samuel Holland stellte den H6-PMIC im Mainline-Kernel auf RSB um, getestet unter anderem auf dem Orange Pi 3 (Patch-Serie, DT-Patch). In der Review wies Chen-Yu Tsai auf das Risiko hin: Firmware wie Crust, die RSB benutzt, schaltet den Chip nicht zurück auf I2C, und dann erreicht Linux ihn nicht mehr.

Ehrlicherweise: Den Moment der Umschaltung habe ich nicht direkt beobachtet. TF-A meldet beim Boot kein eigenes PMIC-Setup, weil Crust vorhanden ist. Am wahrscheinlichsten passiert sie daher im Reboot-Pfad von Crust. Belegt ist aber das Wichtige: Nach dem Warmreset gibt der PMIC auf I2C ein NAK, über RSB ist er erreichbar. Das zeigt der nächste Schritt.

Warum lief das früher? Der Wechsel auf den aktuellen Kernel und die aktuelle Firmware kam mit einem Update Anfang September. Der erste Warmstart danach war ausgerechnet der Update-Reboot, nach dem das System „tot“ war. Das gleichzeitig sterbende eMMC hat die Spur zusätzlich verwischt.

Schritt 5: Der Beweis ohne Risiko

Statt gleich etwas fest einzutragen, habe ich einen alternativen DTB gebaut und ihn nur für einen einzigen Boot am u-boot-Prompt ausgewählt. Armbians armbianEnv.txt setzt kein fdtfile, die Variable aus dem Prompt bleibt also erhalten:

=> setenv fdtfile allwinner/sun50i-h6-orangepi-3-rsb.dtb
=> boot

Ergebnis, nach einem Warmstart in genau dem Zustand, der vorher fünfmal gescheitert war:

sunxi-rsb 7083000.rsb: RSB running at 4000000 Hz
axp20x-rsb sunxi-rsb-745: AXP20x variant AXP806 found
axp20x-rsb sunxi-rsb-745: AXP20X driver loaded
mmcblk0: mmc0:59b4 SN32G 29.7 GiB

Das System kam vollständig hoch. Wäre es schiefgegangen, hätte ein Power-Cycle gereicht, und das Board hätte wieder mit dem Original-DTB gestartet.

Warum funktioniert das beim Kalt- und beim Warmstart? Der Linux-RSB-Treiber schickt beim Start selbst „set device to RSB“. Für ihn spielt es keine Rolle, ob der PMIC noch im I2C-Modus ist oder schon umgeschaltet wurde.

Der Umbau des Device Trees

Ein Overlay reicht hier nicht. Overlays können Knoten nicht verschieben, und alle Verbraucher (SD-Controller, CPU, GPU, Ethernet …) verweisen per Phandle auf die Regulator-Knoten unter pmic@36. Also wird der komplette DTB umgebaut:

  1. Mit dtc -I dtb -O dts dekompilieren.
  2. Den Knoten pmic@36 aus i2c@7081400 herausschneiden.
  3. Ihn als pmic@745 (die RSB-Laufzeitadresse) mit reg = <0x745> in rsb@7083000 einsetzen.
  4. rsb@7083000 auf okay stellen, i2c@7081400 auf disabled. Der PMIC war das einzige Gerät an r_i2c, und beide Busse teilen sich die Pins PL0/PL1.
  5. Die Pfade in __symbols__ umschreiben (/soc/i2c@7081400/pmic@36 → /soc/rsb@7083000/pmic@745), damit Overlays weiter auflösen, etwa das eMMC-Overlay.
  6. Mit dtc -@ neu kompilieren.

Die Phandle-Werte wandern mit dem Knoten mit, deshalb stimmen alle Verweise weiterhin. Ob der Kernel die nötigen Treiber mitbringt, zeigt ein kurzer Blick in die Config: CONFIG_SUNXI_RSB=y, CONFIG_MFD_AXP20X_RSB=y.

Dauerhaft machen und gegen Updates absichern

In /boot/armbianEnv.txt:

fdtfile=allwinner/sun50i-h6-orangepi-3-rsb.dtb

Falle Nr. 3: Armbian legt die DTBs pro Kernelversion ab (/boot/dtb-6.18.44-current-sunxi64/), /boot/dtb ist nur ein Symlink. Nach dem nächsten Kernel-Update zeigt der Link auf ein neues Verzeichnis ohne den RSB-DTB. u-boot hätte dann gar keinen DTB, und das Board startet überhaupt nicht mehr.

Deshalb gibt es einen Hook. /usr/local/sbin/opi3-rsb-dtb läuft per DPkg::Post-Invoke nach jedem apt-Lauf, also auch bei Ansible und unattended-upgrades:

  • Es erzeugt den RSB-DTB in jedem /boot/dtb-*/ neu, sobald sich die Prüfsumme des Original-DTB ändert.
  • Es prüft das Ergebnis mit fdtget: RSB an, PMIC-Adresse 0x745, Symbole umgehängt.
  • Bringt der Upstream-DTB den PMIC irgendwann selbst unter RSB, übernimmt es ihn unverändert.
  • Bei jedem Fehler entfernt es fdtfile aus armbianEnv.txt. Dann bootet das Board sicher mit dem Original-DTB, nur der Warmstart hängt wieder. Den Fehler meldet es ins Syslog und legt eine Markierungsdatei an.
// /etc/apt/apt.conf.d/99-opi3-rsb-dtb
DPkg::Post-Invoke { "if [ -x /usr/local/sbin/opi3-rsb-dtb ]; then /usr/local/sbin/opi3-rsb-dtb >/dev/null || true; fi"; };

Dazu kommt ein NRPE-Check check_opi3_bootfix. Er schlägt Alarm, wenn fdtfile nicht mehr auf den RSB-DTB zeigt, die Datei fehlt, sie nicht zum aktuellen Original passt oder der Hook fehlgeschlagen ist.

Testmatrix

TestSzenarioErgebnis
1–5Warmstart, Original-DTB (PMIC an I2C), mit und ohne Debug-Optionenhängt: PMIC gibt NAK
AWarmstart, RSB-DTB nur am u-boot-Prompt gewählt✅
Bnormaler reboot, RSB-DTB fest eingetragen✅
CKaltstart (Strom getrennt)✅
Dnormaler reboot nach weiterem Aufräumen, Stunden später✅

Bonus: Was das eMMC wirklich umgebracht hat

Bei der Gelegenheit habe ich nachgemessen, wer eigentlich so viel schreibt. Die neue SD-Karte hatte nach zwei Tagen schon über 300 GB auf dem Zähler (/sys/fs/ext4/mmcblk0p1/lifetime_write_kbytes). Hauptverursacher war Pi-hole v6 mit database.forceDisk = true. Damit liegt die Kurzzeit-Datenbank, die normalerweise im RAM gehalten wird, auf der Karte, und SQLite schreibt bei vielen kleinen Einfügungen etwa das Hundertfache dessen, was die Datenbank tatsächlich wächst. Ergebnis: 30 bis über 100 GiB pro Tag. Für ein 8-GB-eMMC aus 2018 ist das nach ein paar Monaten das Lebensende. Die Datenbank zieht deshalb auf eine USB-SSD um. Außerdem gibt es einen zweiten NRPE-Check, der Schreibmenge und Schreibrate der SD-Karte überwacht, weil die Karte selbst keine Gesundheitsdaten liefert (CMD56 liefert nur Nullen).

Was ich mitnehme

  • Ohne serielle Konsole keine Diagnose. Ein 3-Euro-USB-TTL-Adapter und ein Raspberry Pi daneben machen aus „startet nicht“ einen nachvollziehbaren Ablauf.
  • Warm- und Kaltstart sind auf ARM-Boards zwei verschiedene Welten. Alles, was den SoC-Reset überlebt (PMIC, RTC-Domäne, SCP-Firmware), kann Zustand mitschleppen.
  • Fehlercodes ernst nehmen: -6 heißt bei I2C NAK und nicht etwa Timeout. Das hat direkt auf den Busmodus gezeigt.
  • Meldungen nicht trauen, die nach Erfolg klingen: „AXP806 found“ war nie ein Hardware-Zugriff.
  • Erst flüchtig testen, dann festschreiben. setenv am u-boot-Prompt ist der risikoärmste Weg, einen DTB auszuprobieren.
  • Workarounds absichern: Ein Fix, den das nächste Kernel-Update stillschweigend aushebelt (oder der das Board gar nicht mehr starten lässt), ist schlimmer als keiner. Daher Hook, Rückfall und Monitoring.
Leave a Comment :, , , , , , , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Blogroll

A few highly recommended websites...