27.   Urlader-Unterstützung

Die Urlader-Unterstützung betrifft die Typen ATmega88, -168 und -328.

27.1   Features

27.2   Übersicht

Die Urlader-Unterstützung des ATmega88/168/328 bietet einen echten Lesen-während-Schreiben-Selbstprogrammiermechanismus, der es ermöglicht, Programmcode durch den Mikrocontroller selbst laden zu lassen. Diese Eigenschaft erlaubt fexible Anwendungs-Updates, die durch den Controller selbst mit einem Boot-Loader Programm druchgeführt werden. Das Urlader-Programm kann alle verfügbaren Schnittstellen und die damit verbundenen Protokolle verwenden, um Programmcode zu lesen und diesen in den Flash-Speicher zu schreiben oder den Programmcode auszulesen.

Der Programmcode innerhalb des Urlader-Bereiches kann in den gesamten Flash schreiben, also auch in den Urlader-Bereich. Der Urlader kann sich daher selbst modifizieren oder auch sich selbst löschen, wenn er nicht mehr benötigt wird. Die Größe des Urlader-Bereichs wird mit zwei Fuses konfiguriert. Ferner hat der Urlader zwei separate Einstellungen von Sperrbits, die unabhängig voneinander gesetzt werden können. Dies gibt dem Anwender eine einzigartige Flexibilität bei der Auswahl verschiedener Schutzstufen.

27.3   Anwendungs- und Urlader-Bereiche im Flash

Der Flash-Speicher ist in zwei Hauptbereiche organisiert, dem Anwender- und den Urlader-Bereich, siehe Bild 27-2. Die Größe der beiden Bereiche wird mit den BOOTSZ-Fuses konfiguriert, siehe Tabelle 27-7. Beide Bereiche können unterschiedliche Schutzstufen haben, da sie verschiedene Sperrbits haben.

27.3.1   Anwender-Bereich

Der Anwender-Bereich ist der Bereich im Flash, in dem der Kode des Anwenderprogrammes gespeichert wird. Die Schutzstufe für den Anwender-Bereich kann durch die Anwendungs-Sperrbits (Sperrbits 0) eingestellt werden, siehe Tabelle 27-2. Das Anwenderprogramm selbst kann keinen Urlader-Programmkode speichern, da der SPM-Befehl im Anwender-Bereich ausgeschaltet ist.

27.3.2   Urlader-Bereich

Da der Anwender-Bereich zum Speichern des Anwendungsprogrammes vorgesehen ist, muss die Urlader-Software in den Urlader-Bereich gelegt werden, da nur hier der SPM-Befehl eine Programmierung des Flash durchführen kann. Der SPM-Befehl kann auf den gesamten Flash-Speicher zugreifen, also auch auf den Urlader-Bereich selbst. Die Schutzstufe für den Urlader-Bereich kann mit den Urlader-Sperrbits (Sperrbits 1) eingestellt werden, siehe Tabelle 27-3.

27.4   Lesen-beim-Schreiben- und Nicht-Lesen-beim-Schreiben-Bereich

Technischer Hintergrund: Flash-Speicher, genauer: seine Adressierungseinheit, ist nicht in der Lage, beim Zugriff auf „beschäftigte“ (gerade beim Löschen oder Programmieren) Sektoren bspw. aus einem Cache zu lesen. Auch kann nur maximal ein Sektor „beschäftigt“ sein. Damit ist beim Programmieren der Speicher komplett mit sich beschäftigt. Als grober zeitlicher Richtwert gelten allgemein 10 ms. Während dieser Zeit sind keine Lesezugriffe möglich, und die CPU würde so keine Befehle lesen können. Verschiedene Mikrocontroller-Architekturen gehen verschiedene Wege, mit diesem Problem umzugehen. Häufig wird die CPU angehalten. Damit erscheint der Controller für kurze Zeit tot. Von-Neumann-Architekturen können (nur) Kode aus dem RAM ausführen. Beispielsweise ist das Verhalten undefiniert, wenn irrtümlich Flash-Speicher gelesen wird. Undefiniert heißt, dass von falschen Daten über Programmabsturz bis zum Chip-Abbrand alles drin ist. Die AVR-Lösung für größere Controller ist die Einteilung des Flash-Speichers in zwei hinreichend getrennte Bereiche, sodass einer beschäftigt sein kann und der andere (zum Befehlslesen) funktionstüchtig bleibt. Die Aufteilung und die Zugriffsmöglichkeiten ist dabei ziemlich asymmetrisch ausgelegt.
Ob die CPU das Lesen während des Schreibens unterstützt oder ob die CPU angehalten wird, während die Urlader-Software updatet, ist davon abhängig, an welcher Adresse das Urlader-Programm steht. Genauso, wie der Flash wie oben beschrieben mit den BOOTSZ-Fuses in den Anwendngs- und Urlader-Bereich eingeteilt wird, wird der Flash auch in zwei feste Bereiche, nämlich den Lesen-beim-Schreiben- (RWW) und den Nicht-Lesen-beim-Schreiben-Bereich (NRWW) eingeteilt. Die Grenze zwischen dem RWW- und dem NRWW-Bereich ist der Tabelle 27-8 angegeben. Der Hauptunterschied zwischen den beiden Bereichen ist der folgende: Man beachte, dass die Anwendersoftware niemals Code lesen kann, der im RWW-Bereich steht, während die Urlader-Software arbeitet.(sic) Der Term „Lesen-beim-Schreiben-Bereich“ bezieht sich darauf, welcher Bereich gerade programmiert (d.h. gelöscht oder beschrieben) wird und nicht darauf, welcher Bereich gerade durch die Urlader-Software gelesen wird.

27.4.1   RWW — Lesen-beim-Schreiben

Während die Urlader-Software eine Seite im RWW-Bereich programmiert, ist es möglich, Kode aus dem Flash zu lesen, allerdings nur Kode, der im NRWW-Bereich steht. Während einer laufenden Programmierung muss die Software sicherstellen, dass nicht aus dem RWW-Bereich gelesen wird. Wenn die Software versucht, während der Programmierung Code aus dem RWW-Bereich zu lesen, so gerät die Software in einen undefinierten Zustand. Um dies zu verhindern, sollten alle Interrupts gesperrt oder in den Urlader-Bereich gelegt werden. Der Urlader-Bereich liegt immer im NRWW Bereich. Das RWW-Busy-Bit (RWWSB) im SPM-Steuerregister (SPMCSR) wird so lange als 1 gelesen, wie der RWW-Bereich für das Lesen blockiert ist. Nachdem eine Programmierung abgeschlossen ist, muss das RWWSB durch die Software gelöscht werden, bevor Code aus dem RWW Bereich gelesen wird. Siehe SPMCSR.

27.4.2   NRWW — Nicht-Lesen-beim-Schreiben

Der Code, der im NRWW-Bereich liegt, kann gelesen werden, während die Software eine Seite im RWW-Bereich programmiert. Wenn das Urlader-Programm eine Seite im NRWW-Bereich programmiert, wird die CPU für die Dauer des gesamten Lösch- oder Schreibvorganges angehalten.
Tabelle 27-1: Gleichzeitig Lesen und Programmieren — Ja oder nein?
Welchen Bereich adressiert der Zeiger Z beim Programmieren? Welcher Bereich kann gelesen werden? Ist die CPU angehalten? Gleichzeitig Lesen und Programmieren?
RWW-BereichNRWW-BereichNeinJa
NRWW-BereichKeinerJaNein
Bild 27-1: Lesen-beim-Schreiben- und Nicht-Lesen-beim-Schreiben-Bereich
Bild 27-2: Speicherbereiche
Hinweis:
  1. Die Parameter im Bild sind in Tabelle 27-7 erklärt.

27.5   Urlader-Sperrbits

Wenn keine Urlader-Funktion benötigt wird, steht der gesamte Flash für das Anwenderprogramm zur Verfügung. Der Urlader hat zwei separate, unabhängige Einstellungen der Sperrbits. Dies ermöglicht dem Anwender eine einzigartige Flexibilität bei der Auswahl verschiedener Schutzstufen.

Der Anwender kann wählen:

Die nachfolgenden Tabellen geben weitere Details. Die Urlader-Sperrbits können durch die Software und im seriellen und parallelen Programmiermodus gesetzt werden. Das Löschen der Bits kann aber nur durch Löschen des gesamten Bausteins durchgeführt werden. Der generelle Schreibschutz (Sperrbit-Modus 2) beeinflusst nicht das Programmieren des Flash-Speichers mit einem SPM-Befehl. Ähnlich beeinflusst die generelle Lese/Schreibsperre (Sperrbit-Modus 3) nicht das Lesen oder Schreiben durch einen LPM- bzw. SPM-Befehl, wenn diese auftreten.
Tabelle 27-2: BLB0: Schutzstufen des Anwender-Bereichs(1)
BLB0-ModusBLB02BLB01Schutzart
111Keine Einschränkung für SPM und LPM beim Zugriff auf den Anwender-Bereich
210Schreibschutz: SPM darf nicht in den Anwender-Bereich schreiben
300Vollschutz: SPM darf nicht in den Anwender-Bereich schreiben, und LPM darf nicht vom Urlader-Bereich aus den Anwender-Bereich lesen. Sofern Interruptvektoren im Urlader-Bereich platziert sind, sind Interrupts deaktiviert, wenn Kode aus dem Anwender-Bereich ausgeführt wird.
401Kopierschutz: LPM darf nicht vom Urlader-Bereich aus den Anwender-Bereich lesen. Sofern Interruptvektoren im Urlader-Bereich platziert sind, sind Interrupts deaktiviert, wenn Kode aus dem Anwender-Bereich ausgeführt wird.
Hinweis:
  1. „1“ bedeutet unprogrammiert, „0“ bedeutet programmiert
Tabelle 27-3: BLB1: Schutzstufen des Urlader-Bereichs(1)
BLB1-ModusBLB12BLB11Schutzart
111Keine Einschränkung für SPM und LPM beim Zugriff auf den Urlader-Bereich
210Schreibschutz: SPM darf nicht in den Urlader-Bereich schreiben
300Vollschutz: SPM darf nicht in den Urlader-Bereich schreiben, und LPM darf nicht vom Anwender-Bereich aus den Urlader-Bereich lesen. Sofern Interruptvektoren im Anwender-Bereich platziert sind, sind Interrupts deaktiviert, wenn Kode aus dem Urlader-Bereich ausgeführt wird.
401Kopierschutz: LPM darf nicht vom Anwender-Bereich aus den Urlader-Bereich lesen. Sofern Interruptvektoren im Anwender-Bereich platziert sind, sind Interrupts deaktiviert, wenn Kode aus dem Urlader-Bereich ausgeführt wird.
Hinweis:
  1. „1“ bedeutet unprogrammiert, „0“ bedeutet programmiert

27.6   Aufruf des Urladers

Das Aufrufen des Urlader-Programmes kann durch einen JUMP- oder CALL-Befehl aus dem Anwenderprogramm heraus erfolgen. Dieser Anstoß kann durch ein bestimmtes Kommando erfolgen, das über das USART oder die SPI-Schnittstelle empfangen wurde. Alternativ kann die Urlader-Reset-Fuse so programmiert werden, dass der Reset-Vektor auf die Startadresse des Urlader-Bereiches zeigt. In diesem Fall wird das Urlader-Programm nach einem Reset gestartet. Nachdem der Programmcode der Applikation geladen ist, kann dieses Programm dann ausgeführt werden. Man beachte, dass die Fuses nicht durch die CPU selbst verändert werden können. Das bedeutet, dass, wenn die Urlader-Reset-Fuse programmiert ist, der Reset-Vektor immer in den Urlader-Bereich zeigt. Die Fuse kann nur über die serielle oder parallele Programmierung geändert werden.
Tabelle 27-4: Urlader-Reset-Fuse(1)
BOOTRSTReset-Adresse
1Reset-Vektor = Anwendungs-Reset (Adresse 0x0000)
0Reset-Vektor = Urlader-Reset (Adresse siehe Tabelle 27-7)
Hinweis:
  1. „1“ bedeutet unprogrammiert, „0“ bedeutet programmiert

27.7   Adressierung beim Selbstprogrammieren

Das Zeigerregisterpaar Z wird zur Adressierung des SPM-Befehls benutzt (= impliziter Operand).

Bit15141312111098
ZH(R31)Z15Z14Z13Z12Z11Z10Z9Z8
ZL(R30)Z7Z6Z5Z4Z3Z2Z1Z0
76543210

Da der Flash-Speicher in Seiten organisiert ist (siehe Tabelle 28-11), kann man sich den Programmzähler in zwei Teile aufgeteilt vorgestellen. Die niederwertigen Bits addressieren ein 16-Bit-Wort in einer Seite, und der höherwertige Teil adressiert die Seite. Siehe Bild 27-3. Man beachte, das Seite-Löschen und Seite-Schreiben unabhängig adressiert werden. Daher muss die Software gleiche Adressen zum Seitenlöschen und Seitenschreiben sicherstellen. Eine Programmieroperation gestartet ist der Z-Zeiger wieder frei verwendbar.

Die einzige SPM-Operation, die nicht den Z-Zeiger verwendet, ist das Setzen von Sperrbits. In diesem Fall wird das Z-Registerpaar nicht verwendet. Für den LPM-Befehl wird Z (implizit oder explizit) zur Adressierung verwendet. Da dieser Befehl byteweise arbeitet, wird hierbei auch das LSB (Bit 0) von Z verwendet.

Bild 27-3: Flash-Adressierung während SPM (1)
Hinweis:
  1. Die verschiedenen Variablen im Bild 27-3 sind in Tabelle 28-11 gelistet.

27.8   Flash-Selbstprogrammierung

Der Programmspeicher wird Seite für Seite beschrieben und gelöscht. Bevor eine Seite mit den Daten, die in dem temporären Seitenpuffer geladen sind, programmiert wird, muss die Seite gelöscht werden. Der temporäre Seitenpuffer wird 16-bitweise mit dem SPM-Befehl gefüllt. Der Seitenpuffer kann sowohl vor dem Seitenlösch-Kommando als auch zwischen dem Seitenlösch-Kommando und dem Schreiben der Seite gefüllt werden.

Variante 1: Füllen des Puffers vor dem Löschen:

Variante 2: Füllen des Puffers zwischen dem Löschen und Schreiben: Wenn nur ein Teil einer Seite verändert werden muss, muss der Rest der Seite vorher rückgelesen werden (z.B. im temporären Seitenpuffer), da vor dem Schreiben immer die gesamte Seite gelöscht wird. Wenn Variante 1 verwendet wird, bietet der Urloader echtes, byteweises Lesen-Verändern-Schreiben an. In dieser wird die Software zunächst die Seite lesen, dann die notwendigen Veränderungen durchführen und anschließend die modifizierten Daten zurückschreiben. Wenn Variante 2 verwendet wird, ist es nicht möglich, die alten Daten zu lesen, da die Seite bereits gelöscht wurde. Auf den temporären Seitenpuffer kann frei zugegriffen werden. Es ist wichtig, dass die Seitenadresse beim Löschen und Schreiben der Seite die gleiche Flash-Seite adressiert.

27.8.1   Seite löschen

Zum Löschen einer Seite wird die Seitenadresse im Zeigerregisterpaar Z hinterlegt, der Wert 0bx0000011 in das SPMCSR geschrieben und innerhalb von 4 Taktzyklen ein SPM-Befehl ausgeführt. Die Daten in R1 und R0 werden dabei ignoriert. Die Seitenadresse muss in den Bereich PCPAGE in Z geschrieben werden, die anderen Bits von Z werden bei dieser Operation ignoriert.

27.8.2   Zwischenpuffer füllen (Seite laden)

Zum Schreiben eines Befehlswortes wird die Adresse im Zeigerregisterpaar Z hinterlegt, die Daten in R1:R0 geschrieben, der Wert 0b00000001 in das SPMCSR geschrieben und innerhalb von vier Taktzyklen ein SPM-Befehl ausgeführt. Der PCWORD-Bereich von Z wird verwendet, um die Daten im temporären Puffer zu adressieren. Der temporäre Puffer wird automatisch nach dem Befehl Seite-Schreiben gelöscht, aber auch durch Beschreiben des RWWSRE Bits im SPMCSR. Er wird auch nach einem System-Reset gelöscht. Man beachte, dass es nicht möglich ist, mehr als einmal in eine Adresse zu schreiben, ohne dass der temporäre Puffer gelöscht wird.

Wenn der EEPROM mitten in einer Seitenlade-Operation beschrieben wird, gehen alle geladenen Daten verloren.

27.8.3   Seite Schreiben

Um das Schreiben einer Seite durchzuführen, wird die Adresse im Zeigerregisterpaar Z hinterlegt, der Wert 0bx000101 in das SPMCSR geschrieben und innerhalb von vier Taktzyklen ein SPM-Befehl ausgeführt. Die Daten in R1:R0 werden dabei ignoriert. Die Seitenadresse muss in dem Bereich PCPAGE von Z geschrieben werden, die anderen Bits von Z müssen während dieser Operation auf Null gesetzt sein.

27.8.4   SPM-Interrupt

Wenn der SPM-Interrupt freigegeben ist, wird permanent ein Interrupt angefordert, solange das SPMEN-Bit im SPMCSR gelöscht ist. Das bedeutet, dass der Interrupt verwendet werden kann, anstatt den Zustand des SPMCSR durch Softwarepolling abzufragen. Wenn der SPM-Interrupt verwendet wird, sollten die Interruptvektoren in den Urlader-Bereich gelegt werden, um zu verhindern, dass der Interrupt auf den RWW-Bereich zugreift, während dieser blockiert ist. Siehe Interrupts.

27.8.5   Überlegungen beim Update des Urladers

Besondere Vorsicht ist angeraten, wenn durch entsprechende Konfiguration der Urlader-Sperrbits möglich ist, den Urlader-Bereich zu überschreiben. Ein schreibender Zugriff des Urladers auf sich selbst kann den gesamten Urlader unbrauchbar und somit zukünftige Softwareupdates unmöglich machen. Wenn es demnach nicht erforderlich ist, dass der Urlader sich selbst aktualisiert, sollte das Urlader-Sperrbit 11 (Schreibschutz) programmiert werden, um die Urlader-Software vor Änderungen zu schützen.

27.8.6   RWW-Lesen verhindern beim Programmieren

Während der Selbstprogrammierung (sowohl Seite löschen als auch schreiben) ist der RWW-Bereich für Lesezugriffe gesperrt. Die Anwendersoftware selbst muss verhindern, dass dieser Bereich während einer Selbstprogrammierung angesprochen werden kann. Das RWWSB-Bit im SPMCSR ist so lange gesetzt, wie der RWW-Bereich blockiert ist. Während der Selbstprogrammierung sollten die Interruptvektoren in den Urlader Bereich gelegt werden, siehe Watchdog, oder die Interrupts generell gesperrt sein. Bevor auf den RWW-Bereich zugegriffen wird, nachdem eine Programmierung abgeschlossen ist, muss die Software das RWWSB-Bit durch Beschreiben des RWWSRE wieder löschen. Siehe Programmbeispiel.

27.8.7   Sperrbits setzen

Zum Setzen der Urlader Sperrbits wird der erforderliche Wert in R0 geschrieben, der Wert 0bx0001001 in das SPMCSR geschrieben und innerhalb von vier Taktzyklen ein SPM-Befehl ausgeführt.

Bit76543210
R011BLB12BLB11BLB02BLB01LB2LB1

Siehe Tabelle 27-2 und Tabelle 27-3, wie die verschiedenen BLB-Bits wirken.

Werden die Bits 5:0 in R0 auf Null gesetzt, werden die entsprechenden Sperrbits gesetzt, wenn BLBSET und SPMEM im SPMCSR gesetzt wurden und innerhalb von vier Takten SPM ausgeführt wird. Der Z-Zeiger wird dabei nicht verwendet. Für künftige Kompatibilität sollte Z auf 0x0001 gesetzt werden, genauso wie zum Lesen der IOCK-Bits. Außerdem sind die Bits 7 und 6 in R0 wie oben angegeben auf „1“ gesetzt sein. Während des Programmierens der Sperrbits bleibt der gesamte Flash-Speicher ungesperrt zum Lesen.

27.8.8   EEPROM schreiben behindert Schreibzugriff auf SPMCSR

Man beachte, dass das Beschreiben des EEPROM alle Programmierungen des Flash blockiert. Das Lesen der Fuses und Sperrbits durch die Software ist ebenfalls während der Beschreibens des EEPROM nicht möglich. Es wird daher empfohlen, dass der Anwender überprüft, ob das Statusbit EEWE im EECR Register gelöscht ist, bevor in das SPMCSR geschrieben wird.

27.8.9   Fuse- und Sperrbits lesen

Es ist möglich, sowohl die Fuses als auch die Sperrbits durch die Software auszulesen. Zum Lesen der Sperrbits wird der Z-Zeiger mit 0x0001 geladen und die Bits BLBSET und SPMEN im SPMCSR gesetzt. Wenn innerhalb der nächsten drei Taktzyklen nach dem Setzen der beiden Bits ein LPM-Befehl ausgeführt wird, werden die Werte der Sperrbits in das Zielregister geladen. Die beiden Bits werden nach dem Ausführen des Befehls oder Zeitüberschreitung automatisch gelöscht. Wenn BLBSET und SPMEN gelöscht sind, arbeitet der LPM-Befehl wieder normal, so wie in der Befehlsübersicht beschrieben.

Bit76543210
Rn11BLB12BLB11BLB02BLB01LB2LB1

Das Auslesen der Low-Fuse ist mit dem Lesen der Sperrbits vergleichbar. Zum Lesen der Low-Fuse, wird der Z-Pointer mit 0x0000 geladen und die Bits BLBSET und SPMEN im SPMCSR gesetzt. Wenn innerhalb der nächsten drei Taktzyklen nach dem Setzen der beiden Bits ein LPM-Befehl ausgeführt wird, wird die Low-Fuse in das Zielregister geladen, wie nachfolgend dargestellt. Siehe Tabelle 28-9 zur Zuordnung der Fuse-Bits.

Bit76543210
RnCKDIV8CKOUTSUT1SUT0CKSEL3CKSEL2CKSEL1CKSEL0

Ebenso wird zum Lesen der High-Fuse der Z-Pointer mit 0x0003 geladen. Wenn innerhalb der nächsten drei Taktzyklen nach dem Setzen der Bits BLBSET und SPMEN im SPMCSR ein LPM-Befehl ausgeführt wird, wird die High-Fuse in das Zielregister geladen, wie nachfolgend dargestellt. Siehe Tabelle 28-7 zur Zuordnung der Fuse-Bits.

Bit76543210
RnRSTDISBLDWENSPIENWDTONEESAVEBODLEVEL2
BOOTSZ1
BODLEVEL1
BOOTSZ0
BODLEVEL0
BOOTRST
ATmega48/88/168
ATmega328

Zum Lesen der Erweiterten Fuse wird der Z-Pointer mit 0x0002 geladen. Wenn innerhalb der nächsten drei Taktzyklen nach dem Setzen der Bits BLBSET und SPMEN im SPMCSR ein LPM-Befehl ausgeführt wird, wird die Erweiterte Fuse in das Zielregister geladen, wie nachfolgend dargestellt. Siehe Tabelle 28-5 zur Zuordnung der Fuse-Bits.

Bit76543210
Rn-----BOOTSZ1
BODLEVEL2
BOOTSZ0
BODLEVEL1
BOOTRST
BODLEVEL0
ATmega48/88/168
ATmega328

Fuse- und Sperrbits, die programmiert sind, werden als Null gelesen. Bits, die unprogrammiert sind, werden als Eins gelesen.

27.8.10   Signaturbytes lesen

Zum Auslesen der Signaturzeile wird der Z-Zeiger mit der Adresse laut Tabelle 27-5 geladen und die Bits SIGRD und SPMEN im SPMCSR gesetzt. Wenn innerhalb der nächsten drei Taktzyklen nach dem Setzen der beiden Bits ein LPM-Befehl ausgeführt wird, wird der Wert des Signaturbytes in das Zielregister geladen. Die beiden Bits werden nach dem Ausführen des Befehls oder Zeitüberschreitung automatisch gelöscht. Wenn BLBSET und SPMEN gelöscht sind, arbeitet der LPM-Befehl wieder normal, so wie in der Befehlsübersicht beschrieben.
Tabelle 27-5: Adressierung der Signaturzeile
SignaturbyteAdresse im Z-Zeiger
Signaturbyte 10x0000
Signaturbyte 20x0002
Signaturbyte 30x0004
Kalibrierbyte für RC-Oszillator0x0001
Hinweis:
  1. Alle anderen Adressen sind reserviert

27.8.11   Schreibfehler vermeiden

Wenn UCC zu niedrig ist, kann der Inhalt des Flash-Speichers undefiniert sein, weil die Speisespannung für ein korrektes Arbeiten der CPU und/oder des Flash ist zu niedrig ist. Das gilt gleichermaßen auch für Systeme mit externem Flash-Speicher.

Ein falscher Flash-Speicherinhalt kann durch zwei Ursachen entstehen, in denen die Speisespannung zu gering ist. Erstens benötigt ein regulärer Schreibvorgang in den Flash eine Mindestspannung um korrekt zu arbeiten. Zweitens kann die CPU selbst Befehle falsch ausführen, wenn die Speisespannung zu gering ist.

Flash-Fehler können verhindert werden, wenn folgende Designregeln beachtet werden (eine genügt):

  1. Wenn kein Urlader-Update im System benötigt wird, sollten die entsprechenden Sperrbits programmiert werden um den Urlader vor Änderungen zu schützen.
  2. Zu Zeiten unzureichender Speisespannung kann die CPU im Reset gehalten werden. Dies kann durch Aktivierung des internen Unterspannungsdetektors geschehen. Oder es kann eine externe Spannungsüberwachung eingesetzt werden, die den Mikrocontroller per Low-Pegel am Reset-Eingang anhält. Wenn ein Reset auftritt, während ein Schreibvorgang läuft, so wird dieser Vorgang noch bis zum Ende ausgeführt, vorausgesetzt, die Speisespannung ist dafür noch ausreichend.
  3. Zu Zeiten unzureichender Speisespannung kann die CPU im Leistung-Weg-Modus gehalten werden. Das schützt die CPU davor, Befehle zu dekodieren und auszuführen, woduch auch das SPMCSR geschützt wird und somit auch der Flash.

27.8.12   Programmierzeiten

Der kalibrierte RC-Oszillator legt die Zugriffzeiten für den Flash fest. Nachfolgende Tabelle zeigt die typischen Programmierzeiten des Flash durch die CPU.
Tabelle 27-6: Programmierzeiten mit dem SPM-Befehl(1)
AktionMin. ProgrammierzeitMax. Programmierzeit
Flash schreiben (Seite löschen, Seite schreiben, Sperrbits schreiben)3,7 ms4,5 ms
Hinweis:
  1. Minimale und maximale Zeit sind individuell für jeden einzelnen SPM-Befehl

27.8.13   Einfaches Assembler-Beispiel für einen Urlader

	;- Diese Routine schreibt eine Seite vom RAM zum Flash.
	;   Die erste RAM-Speicherzelle wird durch Y adressiert.
	;   Die erste Flash-Speicherzelle wird durch Z adressiert.
	;- Fehlerbehandlung ist nicht dabei.
	;- Verwendete Register: R0, R1, temp1 (R16), temp2 (R17), loop (R18), spmcrval (R19)
	;  Retten und Siederherstellen (Push+Pop) ist hier nicht eingebaut.
	;  Registerverbrauch kann gegen Kodegröße eingespart werden.
	;- Es wird PAGESIZEB ≤ 256 für 8-Bit-Schleifenzähler vorausgesetzt.
.equ	PAGESIZEB = PAGESIZE*2	;PAGESIZEB = Seitengröße in BYTE, nicht in WORD
.org SMALLBOOTSTART
Write_page:
	; Seite löschen
	ldi	spmcrval, (1<<PGERS) | (1<<SPMEN)
	rcall	Do_spm
	; RWW-Bereich wiederherstellen
	ldi	spmcrval, (1<<RWWSRE) | (1<<SPMEN)
	rcall	Do_spm
	; Daten vom RAM zum Flash-Seitenpuffer schaufeln
	ldi	loop, PAGESIZE		;Schleifenzähler initialisieren
Wrloop:
	ld	r0, Y+
	ld	r1, Y+
	ldi	spmcrval, (1<<SPMEN)
	rcall	Do_spm
	subi	ZL, -2			;= +2, ohne Überlauf zum High-Teil
	dec	loop
	brnz	Wrloop
	; execute Page Write
	subi	ZL, PAGESIZEB		;Zeiger wiederherstellen
	ldi	spmcrval, (1<<PGWRT) | (1<<SPMEN)
	rcall	Do_spm
	; re-enable the RWW section
	ldi	spmcrval, (1<<RWWSRE) | (1<<SPMEN)
	rcall	Do_spm
	; read back and check, optional
	ldi	loop, PAGESIZEB		;Schleifenzähler initialisieren
	subi	YL, PAGESIZEB		;Zeiger wiederherstellen
	sbci	YH, 0
Rdloop:
	lpm	r0, Z+
	ld	r1, Y+
	cpse	r0, r1
	rjmp	Error			;Nicht gezeigte Fehlerbehandlung
	dec	loop
	brnz	Rdloop
	; Rückkehr zum RWW-Bereich
Return:	; Warten bis RWW-Bereich bereit zum Lesen ist
	in	temp1, SPMCSR
	sbrs	temp1, RWWSB
	ret
	; RWW-Bereich wiederherstellen
	ldi	spmcrval, (1<<RWWSRE) | (1<<SPMEN)
	rcall	Do_spm
	rjmp	Return

Do_spm:
	; Warten bis vorheriges SPM fertig
Wait_spm:
	in	temp1, SPMCSR
	sbrc	temp1, SPMEN
	 rjmp	Wait_spm
	; Warten bis evtl. EEPROM-Schreibzugriff fertig ist (Interrupts okay)
Wait_ee:
	sbic	EECR, EEPE
	 rjmp	Wait_ee
	; Eingabe: spmcrval legt SPM-Aktion fest
	; Interrupts sperren, falls freigegeben, Zustand retten
	in	temp2, SREG
	cli
	; Spezielle zeitabhängige SPM-Sequenz
	out	SPMCSR, spmcrval
	spm
	; SREG wiederherstellen (Interrupts freigeben wenn vorher freigegeben)
	out	SREG, temp2
	ret

27.8.14   Urlader-Parameter für ATmega88

Die nachfolgenden Tabellen zeigen die Parameter, die in der Beschreibung der Selbstprogrammierung erwähnt wurden.
Tabelle 27-7: Konfiguration der Größe des Bootbereichs
BOOTSZ1BOOTSZ0Boot SizeSeitenAnwender-BereichBoot-Bereich Ende des Anwender-BereichsBoot-Reset-Adresse (=Anfang Boot-Bereich)
11128 Word40x000 - 0xF7F0xF80 - 0xFFF0xF7F0xF80
10256 Word80x000 - 0xEFF0xF00 - 0xFFF0xEFF0xF00
01512 Word160x000 - 0xDFF0xE00 - 0xFFF0xDFF0xE00
001024 Word320x000 - 0xBFF0xC00 - 0xFFF0xBFF0xC00
Hinweis:
  1. Die verschiedenen BOOTSZ-Fuse-Bits sind im Bild 27-2 zu sehen.
Tabelle 27-8: Grenze des RWW- und NRWW-Bereichs
BereichSeitenAdress-Bereich
Lesen-beim-Schreiben (Read-While-Write = RWW)960x000 - 0xBFF
Nicht-lesen-beim-Schreiben (No Read-While-Write = NRWW)320xC00 - 0xFFF
Details zu RWW- und NRWW-Bereichen sind bereits erläutert.
Man beachte, dass die Bereichsaufteilung nur mit der größten Bootbereichsgröße von 2 KByte korelliert.
Tabelle 27-9: Erläuterungen der verschiedenen Variablen in Bild 27-3 und die Verbindung zum Z-Zeiger
VariableEntsprechende Z-Bits(1)Beschreibung
PCMSB11 Höchstwertiges Bit im Programmzähler. (Der Programmzähler ist 12 Bit breit = PC[11:0])
PAGEMSB4 Höchstwertiges Bit, welches Worte innerhalb einer Page adressiert. 32 Word per Seite erfordern 5 Bits des Programmzählers = PC[4:0].
ZPCMSBZ12 Bit in Z-Register, welches auf PCMSB gemappt ist. Weil Z0 ungenutzt ist, ist ZPCMSB gleich PCMSB + 1.
ZPAGEMSBZ5 Bit in Z-Register, welches auf PAGEMSB gemappt ist. Weil Z0 ungenutzt ist, ist ZPAGEMSB gleich PAGEMSB + 1.
PCPAGEPC[11:5]Z12:Z6 Programmzähler-Seitenadresse: Seitenauswahl, fürs Seiten-Löschen und Seiten-Schreiben
PCWORDPC[4:0]Z5:Z1 Programmzähler Word-Adresse: Word-Auswahl, um den Zwischenpuffer zu füllen; muss Null sein beim Seiten-Schreiben
Hinweis:
  1. Bits Z15:Z13 werden ignoriert.
    Bit Z0 ist Byte-Auswahl beim LPM-Befehl und sollte für alle SPM-Befehle stets Null sein. Siehe „Adressierung des Flash-Speichers beim Selbst-Programmieren” zur der Verwendung des Z-Zeigers beim SPM-Befehl.

27.8.15   Urlader-Parameter für ATmega168

Die nachfolgenden Tabellen zeigen die Parameter, die in der Beschreibung der Selbstprogrammierung erwähnt wurden.
Tabelle 27-10: Konfiguration der Größe des Bootbereichs
BOOTSZ1BOOTSZ0Boot SizeSeitenAnwender-BereichBoot-Bereich Ende des Anwender-BereichsBoot-Reset-Adresse (=Anfang Boot-Bereich)
11128 Word20x0000 - 0x1F7F0x1F80 - 0x1FFF0x1F7F0x1F80
10256 Word40x0000 - 0x1EFF0x1F00 - 0x1FFF0x1EFF0x1F00
01512 Word80x0000 - 0x1DFF0x1E00 - 0x1FFF0x1DFF0x1E00
001024 Word160x0000 - 0x1BFF0x1C00 - 0x1FFF0x1BFF0x1C00
Hinweis:
  1. Die verschiedenen BOOTSZ-Fuse-Bits sind im Bild 27-2 zu sehen.
Tabelle 27-11: Grenze des RWW- und NRWW-Bereichs
BereichSeitenAdress-Bereich
Lesen-beim-Schreiben (Read-While-Write = RWW)1120x0000 - 0x1BFF
Nicht-lesen-beim-Schreiben (No Read-While-Write = NRWW)160x1C00 - 0x1FFF
Details zu RWW- und NRWW-Bereichen sind bereits erläutert.
Man beachte, dass die Bereichsaufteilung nur mit der größten Bootbereichsgröße von 2 KByte korelliert.
Tabelle 27-12: Erläuterungen der verschiedenen Variablen in Bild 27-3 und die Verbindung zum Z-Zeiger
VariableEntsprechende Z-Bits(1)Beschreibung
PCMSB12 Höchstwertiges Bit im Programmzähler. (Der Programmzähler ist 13 Bit breit = PC[12:0])
PAGEMSB5 Höchstwertiges Bit, welches Worte innerhalb einer Page adressiert. 64 Word per Seite erfordern 6 Bits des Programmzählers = PC[5:0].
ZPCMSBZ13 Bit in Z-Register, welches auf PCMSB gemappt ist. Weil Z0 ungenutzt ist, ist ZPCMSB gleich PCMSB + 1.
ZPAGEMSBZ6 Bit in Z-Register, welches auf PAGEMSB gemappt ist. Weil Z0 ungenutzt ist, ist ZPAGEMSB gleich PAGEMSB + 1.
PCPAGEPC[12:6]Z13:Z7 Programmzähler-Seitenadresse: Seitenauswahl, fürs Seiten-Löschen und Seiten-Schreiben
PCWORDPC[5:0]Z6:Z1 Programmzähler Word-Adresse: Word-Auswahl, um den Zwischenpuffer zu füllen; muss Null sein beim Seiten-Schreiben
Hinweis:
  1. Bits Z15:Z14 werden ignoriert.
    Bit Z0 ist Byte-Auswahl beim LPM-Befehl und sollte für alle SPM-Befehle stets Null sein. Siehe „Adressierung des Flash-Speichers beim Selbst-Programmieren” zur der Verwendung des Z-Zeigers beim SPM-Befehl.

27.8.16   Urlader-Parameter für ATmega328

Die nachfolgenden Tabellen zeigen die Parameter, die in der Beschreibung der Selbstprogrammierung erwähnt wurden.
Tabelle 27-13: Konfiguration der Größe des Bootbereichs
BOOTSZ1BOOTSZ0Boot SizeSeitenAnwender-BereichBoot-Bereich Ende des Anwender-BereichsBoot-Reset-Adresse (=Anfang Boot-Bereich)
11256 Word40x0000 - 0x3EFF0x3F00 - 0x3FFF0x3EFF0x3F00
10512 Word80x0000 - 0x3DFF0x3E00 - 0x3FFF0x3DFF0x3E00
011024 Word160x0000 - 0x3BFF0x3C00 - 0x3FFF0x3BFF0x3C00
002048 Word320x0000 - 0x37FF0x3800 - 0x3FFF0x37FF0x3800
Hinweis:
  1. Die verschiedenen BOOTSZ-Fuse-Bits sind im Bild 27-2 zu sehen.
Tabelle 27-14: Grenze des RWW- und NRWW-Bereichs
BereichSeitenAdress-Bereich
Lesen-beim-Schreiben (Read-While-Write = RWW)2240x0000 - 0x37FF
Nicht-lesen-beim-Schreiben (No Read-While-Write = NRWW)320x3800 - 0x3FFF
Details zu RWW- und NRWW-Bereichen sind bereits erläutert.
Man beachte, dass die Bereichsaufteilung nur mit der größten Bootbereichsgröße von 4 KByte korelliert.
Tabelle 27-15: Erläuterungen der verschiedenen Variablen in Bild 27-3 und die Verbindung zum Z-Zeiger
VariableEntsprechende Z-Bits(1)Beschreibung
PCMSB13 Höchstwertiges Bit im Programmzähler. (Der Programmzähler ist 14 Bit breit = PC[13:0])
PAGEMSB5 Höchstwertiges Bit, welches Worte innerhalb einer Page adressiert. 64 Word per Seite erfordern 6 Bits des Programmzählers = PC[5:0].
ZPCMSBZ14 Bit in Z-Register, welches auf PCMSB gemappt ist. Weil Z0 ungenutzt ist, ist ZPCMSB gleich PCMSB + 1.
ZPAGEMSBZ6 Bit in Z-Register, welches auf PAGEMSB gemappt ist. Weil Z0 ungenutzt ist, ist ZPAGEMSB gleich PAGEMSB + 1.
PCPAGEPC[13:6]Z14:Z7 Programmzähler-Seitenadresse: Seitenauswahl, fürs Seiten-Löschen und Seiten-Schreiben
PCWORDPC[5:0]Z6:Z1 Programmzähler Word-Adresse: Word-Auswahl, um den Zwischenpuffer zu füllen; muss Null sein beim Seiten-Schreiben
Hinweis:
  1. Bit Z15 wird ignoriert.
    Bit Z0 ist Byte-Auswahl beim LPM-Befehl und sollte für alle SPM-Befehle stets Null sein. Siehe „Adressierung des Flash-Speichers beim Selbst-Programmieren” zur der Verwendung des Z-Zeigers beim SPM-Befehl.

27.9   Register-Beschreibung

27.9.1   SPMCSR — SPM-Kontroll- und Statusregister

Das SPMCSR enthält Steuerbits, die benötigt werden, um die Urlader-Funktionen zu steuern.
Bit76543210
(0x57)SPMIERWWSBSIGRDRWWSREBLBSETPGWRTPGERSSPMENSPMCSR
ZugriffR/WRR/WR/WR/WR/WR/WR/W
Startwert00000000
Wenn das SPMIE-Bit auf 1 gesetzt ist und das I-Bit im Statusregister gesetzt ist, wird der SPM-Fertig-Interrupt freigegeben. Der SPM-Fertig-Interrupt wird ausgeführt, sobald das SPMEN-Bit im SPMCSR (durch die Hardware) gelöscht ist. Wenn eine Selbstprogrammieroperation (Löschen oder Schreiben) in dem RWW-Bereich gestartet wird, wird das Bit durch die Hardware auf 1 gesetzt. Solange das RWWSB-Bit gesetzt ist, kann nicht auf den RWW-Bereich zugegriffen werden. Das RWWSB-Bit wird gelöscht, indem das RWWSRE Bit auf 1 gesetzt wird, nachdem der Selbstprogrammierungs-vorgang abgeschlossen ist. Alternativ wird das RWWSB-Bit automatisch gelöscht, wenn mit dem Laden einer Seite begonnen wird. Ein LPM-Befehl innerhalb von drei Taktzyklen nach dem Setzen der Bits SIGRD und SPMEN liest ein Byte aus der Signaturzeile (Herstellerkennung) oder das RC-Oszillator-Werkskalibrierbyte, abhängig vom Inhalt des Z-Zeigers, in ein Zielregister. Siehe „Signaturbytes lesen“. Das Beschreiben mittels SPM ist wirkungslos und sollte wegen künftiger Erweiterungen unterlassen werden. Wenn eine Programmierung des RWW Bereiches erfolgt (Seite löschen oder schreiben) ist den RWW-Bereich für das Lesen gesperrt (das RWWSB Bit wird durch die Hardware gesetzt). Um die RWW Sektion wieder freizugeben muss die Software warten, bis der Programmiervorgang abgeschlossen ist (SPMEN wird gelöscht). Dann, wenn das RWWSRE-Bit zur gleichen Zeit wie das SPMEN Bit mit einer 1 beschrieben wird, gibt der nächste SPM Befehl innerhalb von vier Taktzyklen den RWW-Bereich wieder frei. Der RWW-Bereich kann nicht wieder freigegeben werden, während der Flash mit dem Löschen oder Schreiben einer Seite beschäftigt ist (SPMEN ist gesetzt). Wenn das RWWSRE Bit beschrieben wird, während der Flash geladen wird, wird die Flash-Operation abgebrochen und die zu ladenden Daten gehen verloren. Wenn dieses Bit zur gleichen Zeit wie das SPMEN-Bit auf Eins gesetzt wird, wird der nächste SPM-Befehl innerhalb von vier Taktzyklen die Urlader-Sperrbits mit den Daten einstellen, die in R0 stehen. Die Daten in R1 und die Adresse im Z-Pointer werden ignoriert. Das BLBSET-Bit wird automatisch gelöscht, wenn die Einstellung der Urlader-Sperrbits erfolgte oder wenn der SPM Befehl nicht innerhalb der vier Taktzyklen ausgeführt wird.

Ein LPM-Befehl innerhalb von drei Taktzyklen nach dem Setzen der Bits BLBSET und SPMEN liest entweder die Sperr- oder die Fuse-Bits (abhängig von Z0 des Z-Zeigers) in ein Zielregister. Siehe Lesen der Fuse- und Sperrbits.

Wenn dieses Bit zur gleichen Zeit wie das SPMEN-Bit auf Eins gesetzt wird, wird der nächste SPM-Befehl innerhalb von vier Taktzyklen das Beschreiben einer Seite mit den Daten, die im temporären Buffer gespeichert sind, starten. Die Seitenadresse wird aus dem oberen Teil des Registerpaars Z entnommen. Die Daten in R1 und R0 werden ignoriert. Das PGWRT-Bit wird, nachdem die Seite geschrieben wurde automatisch gelöscht oder dann, wenn der SPM-Befehl nicht innerhalb der vier Taktzyklen ausgeführt wurde. Die CPU wird angehalten, wenn ein Schreibvorgang in dem NRWW-Bereich durchgeführt wird. Wenn dieses Bit gleichzeitig mit SPMEN auf Eins gesetzt wird, wird der nächste SPM-Befehl innerhalb von vier Taktzyklen das Löschen einer Seite starten. Die Seitenadresse wird aus dem oberen Teil des Registerpaars Z entnommen. Die Daten in R1 und R0 werden ignoriert. Das PGERS-Bit wird automatisch gelöscht, wenn die Seite gelöscht wurde oder wenn innerhalb der nächsten vier Taktzyklen kein SPM-Befehl ausgeführt wurde. Die CPU wird angehalten, wenn ein Löschvorgang in dem NRWW-Bereich durchgeführt wird. Dieses Bit gibt die Ausführung eines SPM-Befehls innerhalb der nächsten vier Taktzyklen frei. Wenn es zusammen mit einem der Bits RWWSRE, BLBSET, PGWRT oder PGERS gesetzt wird, hat der folgende SPM-Befehl eine besondere Bedeutung, wie oben beschrieben. Wenn nur SPMEN allein auf Eins besetzt wird, wird der folgende SPM-Befehl die Werte, die in R1:R0 stehen, in den Seitenpuffer speichern, der durch den Registerpaar Z adressiert ist. Dabei wird das LSB von Z ignoriert. Das SPMEN-Bit wird automatisch gelöscht, wenn ein SPM-Befehl ausgeführt wurde, oder spätestens nach vier Taktzyklen. Während des Löschens und Schreibens einer Seite verbleibt das SPMEN-Bit so lange High, bis die Operation vollständig abgeschlossen ist.

Das Schreiben anderer Werte als 0b10001, 0b01001, 0b00101, 0b00011 oder 0b00001 in die unteren fünf Bits hat keine Auswirkungen.