Willkommen auf meiner Homepage!
UPDI-Signatur auslesen: Warum LDS bei gelöschten AVR-Dx-Chips timeoutet – und wie man es löst
Wer einen eigenen UPDI-Programmer für moderne Microchip/Atmel-AVR-Chips (megaAVR0-Serie, AVR-Dx-Serie
wie AVR32DB32, AVR64DB48 usw.) baut, stößt früher oder später auf ein verwirrendes Phänomen:
Einfache UPDI-Registerzugriffe (LDCS) funktionieren zuverlässig, aber der Versuch,
die Chip-Signatur aus dem SIGROW-Speicherbereich zu lesen (LDS), läuft immer wieder
in einen Timeout – ganz ohne erkennbaren Grund in Hardware oder Code.
Dieser Artikel dokumentiert die komplette Fehlersuche und die Lösung, damit ihr euch die stundenlange
Suche sparen könnt.
Das Symptom
LDCS(Load Control/Status, Opcode0x80 | Register) liefert zuverlässig eine korrekte Antwort – z. B. beim Lesen von STATUSA oder STATUSB.LDS(Load Data Space, Opcode0x04, gefolgt von einer 16-Bit-Adresse) auf die Signatur-Adresse0x1100liefert dagegen einen Timeout – keine Antwort, kein Fehlerflag, einfach Stille auf der Leitung.- Das Verhalten tritt reproduzierbar auf, sobald der Zielchip gelöscht (Chip-Erase) ist. Sobald ein gültiges Programm im Flash liegt, funktioniert derselbe LDS-Zugriff einwandfrei.
Wichtig zu wissen: Das Symptom hat nichts mit Verkabelung, Signalqualität, Baudrate oder Timeout-Werten zu tun – auch bei sauberster Hardware und großzügigem Timeout bleibt das Problem bestehen, solange der Chip gelöscht ist.
Die eigentliche Ursache
Im Microchip-Datenblatt (Kapitel „UPDI – Unified Program and Debug Interface") steht der entscheidende Satz:
„Until the lock bits are cleared, the UPDI cannot access the system bus, and only CS-space operations can be performed."
Der Grund liegt in der Architektur von UPDI selbst:
- LDCS/STCS greifen nur auf UPDI-interne Register zu (den sogenannten „CS-Space" – Control/Status Space). Das funktioniert immer, unabhängig vom Zustand der CPU oder des Flash-Inhalts.
- LDS/STS greifen dagegen auf den „normalen" Datenraum des Chips zu (SRAM, I/O-Register, SIGROW, USERROW). Dafür muss der UPDI-Controller über eine interne Bus-Bridge Zugriff auf den System-Bus des AVR-Kerns bekommen.
Ein zusätzliches, sehr aufschlussreiches Detail steht im Register ASI_SYS_STATUS
(Offset 0x0B), Bit 1, BOOTDONE:
„This bit is set to '1' when the CPU is done with the boot sequence. The UPDI will not have access to the ACC layer until this bit is set to '1'."
Bei einem frisch gelöschten Chip (Flash komplett 0xFF) hat die CPU keinen gültigen
Code zum Booten – der Boot-Vorgang wird nie sauber abgeschlossen, BOOTDONE bleibt dauerhaft
0, und der Systembus-Zugriff für UPDI bleibt blockiert. Das erklärt exakt das
beobachtete Muster: kein Fehlerflag (STATUSB zeigt sauber 0x00), einfach keine
Antwort.
Die Lösung: NVMPROG-Modus aktivieren
Der Weg, auch auf einem gelöschten Chip Datenraum-Zugriffe (LDS/STS) zu bekommen, führt nicht über einen wartenden Boot-Vorgang, sondern über den dedizierten NVM-Programmiermodus. Dieser Modus gewährt UPDI exklusiven Bus-Zugriff, unabhängig vom CPU-/Boot-Zustand.
Ablauf (laut Datenblatt, Kapitel „NVM Programming")
- NVMPROG-Key senden über die KEY-Instruktion (Opcode
0xE0, „Receive Key", 64 Bit). Die Signatur lautet0x4E564D50726F6720und wird LSB-first übertragen. - Optional:
ASI_KEY_STATUS(Offset0x07) per LDCS lesen, um zu prüfen, ob der Key akzeptiert wurde (Bit 4 = NVMPROG). - System-Reset auslösen:
0x59inASI_RESET_REQ(Offset0x08) schreiben (RSTREQ-Signatur für „Normal Reset"). - Reset wieder freigeben:
0x00in dasselbe Register schreiben (Signatur „RUN" – löscht die Reset-Bedingung). - PROGSTART pollen:
ASI_SYS_STATUS(Offset0x0B) wiederholt per LDCS lesen, bis Bit 3 (PROGSTART) auf1springt. - Sobald
PROGSTART = 1ist, funktionieren LDS/STS zuverlässig – auch wenn BOOTDONE weiterhin0bleibt.
Wichtige Stolperfallen bei der Umsetzung
- Bei der KEY-Instruktion kein Echo erwarten. Anders als bei LDCS/STCS/LDS sendet das Target während der 8 Key-Bytes keine Echos zurück. Wer hier trotzdem auf ein Echo wartet, erzeugt acht aufeinanderfolgende Timeouts.
- Die Polling-Schleife braucht eine vernünftige Obergrenze. Ein zu hoher
tries-Wert kombiniert mit einem großzügigen Byte-Timeout kann im Fehlerfall zu mehreren Minuten Wartezeit führen, was sich wie ein Programmabsturz anfühlt, aber technisch nur eine sehr lange, regulär beendete Schleife ist. 30–50 Versuche mit kurzen Pausen reichen üblicherweise aus. - Genug Zeit nach dem Reset-Zyklus einplanen. Direkt nach dem Zurücksetzen
von
ASI_RESET_REQauf0x00sollte man dem Target ein paar Millisekunden geben, bevor man mit dem PROGSTART-Polling beginnt.
Sauberes Beenden – ohne das Target „abzuschießen"
Ein zweiter Fallstrick lauert beim Beenden der UPDI-Sitzung. Im Register CTRLB
(Offset 0x03) gibt es Bit 2, UPDIDIS:
„Writing a '1' to this bit disables the UPDI PHY interface. […] All the UPDI PHY configurations and keys will be reset when the UPDI is disabled."
Wer am Ende testweise 0x04 in dieses Register schreibt (z. B. um „sauber
abzumelden"), deaktiviert damit die komplette UPDI-Schnittstelle auf dem Target. Danach reagiert
der Chip auf keinen weiteren Befehl mehr, bis ein vollständiger, roher Enable-Impuls (das
UPDI-Äquivalent eines Kaltstarts) erneut gesendet wird.
Die bessere Alternative: Nur einen System-Reset über ASI_RESET_REQ
auslösen (wie in Schritt 3–4 oben beschrieben), ohne UPDIDIS zu setzen. Das Target startet neu,
aber die UPDI-Verbindung selbst bleibt aktiv nutzbar.
Zusätzliche Beobachtung: Nach einer bereits aktiven Sitzung (z. B. nachdem PROGSTART erreicht wurde) reicht ein einzelner Enable-Impuls oft nicht mehr aus, um die Verbindung bei einem Neustart des Programmier-Codes zuverlässig neu aufzubauen. Ein zweiter Enable-Impuls kurz nach dem ersten schafft hier zuverlässig Abhilfe – vermutlich, weil eine bereits „wache" UPDI-PHY einen kräftigeren Weckreiz braucht als eine, die seit dem letzten echten Power-Up geschlafen hat.
Nützliches Diagnose-Werkzeug: STATUSB
Für die eigene Fehlersuche lohnt sich ein Blick in STATUSB (Offset
0x01), Bits 2:0 – das PESIG-Fehlersignaturfeld:
| PESIG | Bedeutung |
|---|---|
| 0x0 | Kein Fehler |
| 0x1 | Parity-Fehler |
| 0x2 | Frame-Fehler |
| 0x3 | Access-Layer-Timeout (UPDI bekommt keine Antwort vom Access Layer) |
| 0x4 | Clock-Recovery-Fehler |
| 0x6 | Bus-Fehler (Adress- oder Zugriffsrechtefehler) |
| 0x7 | Kollisions-/Contention-Fehler |
Wer bei LDS/STS einen Timeout bekommt, sollte als Erstes STATUSB auslesen – das grenzt sofort ein, ob es sich um genau das hier beschriebene Access-Layer-Problem handelt oder um etwas anderes (Signalqualität, Kollision auf der Leitung usw.).
Kurz zusammengefasst
- LDCS/STCS funktionieren immer, unabhängig vom Chip-Zustand.
- LDS/STS brauchen entweder ein bereits laufendes Programm (BOOTDONE = 1) oder den aktiven NVM-Programmiermodus (PROGSTART = 1).
- Der NVM-Programmiermodus wird über KEY-Instruktion (NVMPROG-Signatur) + System-Reset-Zyklus + PROGSTART-Polling erreicht.
- Zum Beenden nur einen System-Reset auslösen, niemals UPDIDIS setzen – sonst ist die Verbindung komplett tot.
- STATUSB (PESIG-Feld) ist das erste Werkzeug bei jeder UPDI-Fehlersuche.
Damit lässt sich auf einem frisch gelöschten AVR-Dx-Chip zuverlässig die Signatur auslesen und der Weg zum eigentlichen Flash-Programmieren ist frei.