Physik-Seminar AVR-8-Bit-Mikrocontroller Bootloader Markus Schroeder, 203110686 Universität Koblenz-Landau schroeder@uni-koblenz.de Betreuer: Dr. Merten Joost c 2006
INHALTSVERZEICHNIS 2 Inhaltsverzeichnis 1 Einführung 3 1.1 Ziel der Abhandlung....................... 3 1.2 Was ist ein Bootloader...................... 3 2 Beschreibung der Bootfunktion 4 2.1 Architektur und Funktion des Bootbereichs........... 4 2.2 Die Assembler-Befehle LPM und SPM............. 9 2.3 RWW und NRWW........................ 12 3 Anwendung der Bootfunktion 14 3.1 Nutzungsmöglichkeiten...................... 14 3.2 Anwendungsbeispiel: Bootloader zur Reprogrammierung... 14
1 EINFÜHRUNG 3 1 Einführung 1.1 Ziel der Abhandlung Diese Abhandlung soll dazu dienen, einen Überblick über die Möglichkeiten und den Aufbau eines Bootloaders zu bekommen, wie er von vielen Modellen der AVR-8-Bit-Baureihe von Atmel 1 unterstützt wird. Dazu werden die Grundlagen eines AVR-Mikrocontrollers, wie beispielsweise I/O-Funktionen und Grundkenntnisse der Mikrocontroller-Programmierung und -architektur, als bekannt vorausgesetzt. Es wird zum einen erläutert, wie die Bootfunktion im Mikrocontroller aufgebaut ist und funktioniert, und zum anderen, wo der Vorteil in der Nutzung liegt und wie man die Bootfunktion sinnvoll nutzen kann. 1.2 Was ist ein Bootloader Zunächst sollte man klären, was ein Bootloader ist und warum man ihn überhaupt braucht. Ein Bootloader ist (hier) ein initiales Programm, welches beim Booten 2, was im Bereich der Mikrocontroller äquivalent zum Anschalten ist, abläuft. Eben durch diese Tatsache stellt sich die nächste Frage nach dem Zweck eines Bootloaders, da ein eigentliches Booten, wie es bei PC s nötig ist, beim Mikrocontroller entfällt. Die gesamte Hardware-Peripherie (RAM, I/O, etc.) ist schon fest verdrahtet und bekannt, und muß somit nicht wie bei PC s üblich, erkannt und konfiguriert bzw. initialisiert werden. Trotzdem lassen sich mit der Nutzung eines Bootloaders durchaus sinnvolle und mächtige Funktionen realisieren, was näher in Kapitel 3.1 auf Seite 14 behandelt wird. 1 www.atmel.com 2 Hochfahren
2 BESCHREIBUNG DER BOOTFUNKTION 4 2 Beschreibung der Bootfunktion 2.1 Architektur und Funktion des Bootbereichs Um eine Bootfunktion zu realisieren, bietet einige Modelle der AVR-8-Bit- Baureihe an, einen Teil des internen Flash-Speichers als Bootbereich zu benutzen. Dieser Teil liegt grundsätzlich am Ende des Flash-Speichers, wie es auf Abbildung 1 auf Seite 4 verdeutlicht wird. Abbildung 1: Flash-Speicher des ATmega16 Normalerweise beginnt ein Mikrocontroller nach dem Anschalten mit dem Abarbeiten des Programms ab der Adresse $0000. Um dieses Verhalten zu umgehen, was beim Nutzen der Bootfunktion gewünscht wird, gibt es das
2 BESCHREIBUNG DER BOOTFUNKTION 5 BOOTRST-Bit. Wird dieses gesetzt (was heißt, es auf 0 zu setzen!), wird der Reset-Vektor von der Adresse $0000 auf die Adresse des ersten Bytes des Bootbereichs umgelegt. Um besser an das Programm, welches sich im Bootbereich befindet, angepasst zu sein und um möglichst wenig Speicherplatz vom Flash-Speicher zu benutzen, lässt sich die Größe des Bootbereichs zusätzlich noch konfigurieren. Dazu gibt es vier Möglichkeiten, wie aus Abbildung 2 auf Seite 5 ersichtlich wird. Dort wird die Funktion anhand der Daten eines ATmega16 erklärt, bei anderen Mikrocontrollern aus der gleichen Baureihe ist die Architektur jedoch weitestgehend analog. Die Konfiguration der Bootbereichgröße wird anhand zweier Bits realisiert, BOOTSZ0 und BOOTSZ1. Auch hier bedeutet eine 0 gesetzt und eine 1 nicht gesetzt. Abbildung 2: Konfiguration der Bootbereichgröße Da im Bootbereich oftmals Programmkonstrukte stehen, die nicht bei jeder Neuprogrammierung modifiziert werden sollen oder dürfen, gibt es die Möglichkeit, den kompletten Bootbereich (und auch den Applikationsbereich) für einige Operationen zu sperren. Das beschränkt sich auf die Assembler-Befehler LPM und SPM und für die Ausführung von Interrupts.
2 BESCHREIBUNG DER BOOTFUNKTION 6 Die Funktion von LPM und SPM wird im Kapitel 2.2 auf Seite 9 erläutert. Um eine Sicherung des Boot- oder Applikationsbereichs zu erzielen, müssen die Bits BLB12, BLB11, BLB02 und BLB01 so in das Register R0 geschrieben werden, wie es auf Abbildung 3 auf Seite 6 zu sehen ist. Abbildung 3: Konfiguration der Bootlock-Bits mittels R0 Anschließend wird die gewünschte Konfiguration durch den SPM-Befehl (siehe Kapitel 2.2 auf Seite 9) bestätigt. Welche Auswirkung die verschiedenen Modi haben, ist aus Abbildung 4 auf Seite 7 ersichtlich. Eine weitere Konfigurationsmöglichkeit bei der Nutzung der Bootfunktion bietet sich durch das GICR 3 (siehe Abbildung 5 auf Seite 7). 3 General Interrupt Control Register
2 BESCHREIBUNG DER BOOTFUNKTION 7 Abbildung 4: Konfiguration der Bootlock-Bits Abbildung 5: General Interrupt Control Register
2 BESCHREIBUNG DER BOOTFUNKTION 8 Wie bereits erwähnt, bewirkt das Setzen des BOOTRST-Bits, dass der Reset-Vektor, der ebenfalls ein Interrupt-Vektor ist, auf die Adresse des ersten Bytes des Bootbereichs zeigt. Die Sprungadressen aller anderen Interrupts befinden sich aber nach wie vor am Anfang des Flash-Speichers, was bei Nichtbeachtung selbstverständlich fatale Programmfehler nach sich ziehen kann. Um die gesamte Tabelle der Interrupt-Vektoren in den Bootbereich zu verlegen, gibt es das IVSEL-Bit, welches sich im GICR (siehe Abbildung 5 auf Seite 7) befindet. Die vier möglichen Konfigurationen, die durch das Zusammenspiel von BOOTRST und IVSEL entstehen, zeigt Abbildung 6 auf Seite 8. Abbildung 6: Konfiguration der Interrupt-Vektoren Das IVSEL-Bit kann allerdings nicht auf beliebige Art und Weise verändert werden. Eine Modifikation ist nur durch folgenden Ablauf möglich: IVCE auf 1 setzen Innerhalb von 4 Takten IVSEL auf den gewünschten Wert setzen, gleichzeitig IVCE auf 0 setzen Während dieser Prozedur sind alle Interrrupts deaktiviert, auch wenn sie global, also durch ein gesetztes I-Bit im Status-Register SREG, aktiviert sind. Die Deaktivierung dauert entweder bis nach dem Befehl, der auf das Aktualisieren von IVSEL folgt, oder sie dauert 4 Takte ab dem Befehl, mit
2 BESCHREIBUNG DER BOOTFUNKTION 9 dem IVCE auf 1 gesetzt worden ist (falls das Modifizieren von IVSEL nicht rechtzeitig erfolgt). 2.2 Die Assembler-Befehle LPM und SPM Die beiden Befehle LPM und SPM sind die einzigen beiden Instruktionen, die Operationen mit dem Flash-Speicher ermöglichen. LPM liest ein beliebiges Byte aus jeder beliebigen Position des Flash- Speichers, wobei dieses Bytes immer durch den Z-Pointer 4 referenziert wird. Erfolgt der Aufruf ohne Parameter, wird das durch R31:R30 referenzierte Byte in R0 geladen. Zusätzlich gibt es noch zwei weitere, parameterbezogene Aufrufe: LPM Rd, Z Das vom Z-Pointer referenzierte Byte wird in Rd geladen LPM Rd, Z+ Das vom Z-Pointer referenzierte Byte wird in Rd geladen, Postinkrement des Z-Pointers LPM kann überall aus dem Flash-Speicher (also Applikations- und Bootbereich) aufgerufen werden, wo hingegen SPM nur aus dem Bootbereich ausgeführt werden kann. SPM ist der Befehl, der den kompletten Flash-Speicher modifizieren kann. Das bedeutet, dass er sogar das Programm aus dem Bootbereich, aus dem der SPM-Befehl aufgerufen wurde, überschreiben kann, was die Notwendigkeit der bereits erwähnten Bootlock-Bits (siehe Abbildung 4 auf Seite 7) erklärt. Allerdings arbeitet der Befehl nicht so wie einfach wie LPM, da er nicht ein beliebiges Byte an eine beliebige Adresse schreiben kann. Das liegt 4 16-Bit-Register, bestehend aus den zwei 8-Bit-Registern R31:R30
2 BESCHREIBUNG DER BOOTFUNKTION 10 daran, dass der komplette Flash-Speicher des Mikrocontrollers in Pages unterteilt ist, wobei jede Page 128 Byte beinhaltet. Ein Beschreiben des Flash- Speichers erfolgt immer, indem eine komplette Page geschrieben wird, auch wenn nur ein Byte aktualisiert werden soll. Dazu existiert ein temporärer Page-Speicher, der mit den gewünschten Daten geladen wird, um anschließend eine Page im Flash-Speicher zu aktualisieren. Bevor allerdings eine Page geschrieben wird, muss diese gelöscht werden, da ein direktes Überschreiben nicht möglich ist. Wann das Löschen erfolgt, ist nicht von Bedeutung, solange es vor dem Schreibvorgang erfolgt. Alle diese Aktionen, also Schreiben der temporären Page, Löschen der Page im Flash-Speicher und das eigentliche Schreiben der Page werden durch den SPM-Befehl und das SPMCR 5 realisiert und durchgeführt. Im SPMCR (siehe Abbildung 7 auf Seite 10) wird die entsprechende Funktion ausgewählt und durch den SPM-Befehl innerhalb von vier Takten bestätigt. Erfolgt der Aufruf von SPM nicht rechtzeitig, muss das SPMCR erneut konfiguriert werden. Das Register steuert ebenfalls das Modifizieren der Bootlockbits und die Aktivierung eines Interrupts, der dann bei Fertigstellung einer SPM-Aktion ausgelöst wird. Abbildung 7: Store Program Memory Control Register Das Bit für die Interrupt-Aktivierung (SPMIE) ist das einzige, welches ohne Zutun von SPMEN arbeitet. Sowohl BLBSET, als auch PGERS, PG- WRT und RWWSRE haben nur eine Wirkung, wenn zusammen mit ihnen das SPMEN-Bit gesetzt wird und diese Kombination durch Aufruf von SPM 5 Store Program Memory Control Register
2 BESCHREIBUNG DER BOOTFUNKTION 11 bestätigt wird. Das SPMEN-Bit hat aber noch eine weitere wichtige Funktion für die Modifikation des Flash-Speichers. Da die Aktionen PGERS, PGWRT und BLBSET nach [Atm05] eine Verzögerung von 3,7ms bis 4,5ms haben, die unabhängig vom Takt existiert, braucht man eine Möglichkeit, festzustellen, wann dieser Vorgang beendet ist. Dazu nutzt man ebenfalls das SPMEN, da dieses beim Auswählen der Aktion auf 1 gesetzt wird, und solange gesetzt bleibt, bis die Operation mit der Page abgeschlossen ist. Das Löschen einer Page mit anschließendem Warten auf die Beendigung der Operation könnte somit wie folgt geschehen: 1 erase_page : 2 l d i r16, 0 b00000011 ;PGERS und SPMEN werden g e s e t z t 3 out SPMCR, r16 ; Daten werden i n s SPMCR g e s c h r i e b e n 4 spm ; B e s t ä t i g u n g der Konfiguration im SPMCR 5 wait_loop : 6 in r16, SPMCR ; Daten aus SPMCR in R16 laden 7 sbrc r16, SPMEN ; Testen, ob SPMEN noch g e s e t z t i s t ( Löschen l ä u f t noch ) 8 rjmp wait_loop ; Sprung zum Label wait_loop, b i s SPMEN == 0 i s t 9... ; ab h i e r kommt w e i t e r e r Q u e l l t e x t, Löschen i s t beendet Listing 1: Löschen einer Page Völlig analog zu diesem Listing sähe ein Quelltext-Fragment zum Schreiben einer Page im Flash-Speicher aus. Eine wichtige Position für die SPM- Operationen erfüllt der aus R31:R30 bestehende Z-Pointer. Dieser übernimmt immer die Adressierung eines Datenwords (2Byte) beim Schreiben in den temporären Page- Pufferspeicher einer Page beim Schreiben in den Flash-Speicher einer Page beim Löschen im Flash-Speicher Wird der SPM-Befehl aufgerufen, wenn nur das SPMEN-Bit im SPMCR gesetzt ist, dient er immer dazu, den Page-Pufferspeicher zu füllen. Dies geschieht, indem die beiden Bytes aus R1:R0 an die vom Z-Pointer referenzierte
2 BESCHREIBUNG DER BOOTFUNKTION 12 Adresse geschrieben werden. Da der Z-Pointer eine Byte-Adresse referenziert, aber 2 Byte geschrieben werden, ist das LSB des Z-Pointers ohne Bedeutung. Weiterhin sind die oberen 9 Bit des Z-Pointers belanglos, da eine Page lediglich 128 Byte enthält. Wird der SPM-Befehl hingegen dazu genutzt, eine Page im Flash-Speicher zu löschen oder zu schreiben, werden die Daten aus R1:R0 ignoriert. Der Z- Pointer übernimmt auch hier die Adressierung, zeigt diesmal jedoch auf ein beliebiges Byte aus der Page, die bearbeitet werden soll. Somit sind hier die unteren 7 Bit des Z-Pointers bedeutungslos, da diese lediglich ausdrücken, welches Byte aus der Page adressiert wird. 2.3 RWW und NRWW Unabhängig von der Einteilung des Flash-Speichers in Boot- und Applikationsbereich existiert noch eine Einteilung in RWW 6 - und NRWW 7 -Bereiche. Im Unterschied zum Bootbereich existiert die Einteilung in RWW und NRWW immer und ist zudem fest. Die Größe des NRWW-Speichers ist immer gleich der des größtmöglichen Bootbereiches, wie Abbildung 8 auf Seite 13 verdeutlicht. Daraus wird klar, dass ein Programm im Bootbereich stets im NRWW- Bereich gespeichert ist. Der Vorteil des NRWW ist, dass man, während man eine Page im RWW-Bereich löscht oder schreibt, weiterhin ein Programm im NRWW-Bereich ausführen kann. Der RWW-Bereich hingegen ist in dieser Zeit für den Lesebetrieb gesperrt, was durch das RWWSB 8 -Bit im SPMCR angezeigt wird. Beachtet man die Lesesperre nicht, kann das zu einem undefinierten Zustand führen. Der Anwender hat also dafür zu sorgen, dass 6 Read While Write 7 No Read While Write 8 Read While Write Section Busy
2 BESCHREIBUNG DER BOOTFUNKTION 13 dort keine Programmteile ausgeführt werden, was natürlich auch Sprungbefehle und Interrupts einschließt. Diese Tatsache macht die bereits erwähnte Verlegung der Interrupt-Sprung-Tabelle in den Bootbereich sinnvoll. Abbildung 8: Einteilung des Flash-Speichers in RWW- und NRWW-Bereich Aktualisiert man jedoch eine Page in der NRWW-Sektion (was Boot- oder Applikationsbereich sein kann), wird die CPU während des gesamten Vorgangs angehalten. Hat man die komplette Modifikation des Flash-Speichers abgeschlossen, muss man mit dem RWWSRE-Bit im SPMCR den RWW- Bereich wieder für den Lesebetrieb freigeben.
3 ANWENDUNG DER BOOTFUNKTION 14 3 Anwendung der Bootfunktion 3.1 Nutzungsmöglichkeiten Prinzipiell sind die Nutzungsmöglichkeiten für den Bootbereich vielfältig und nicht begrenzt. Allein die Tatsache, dass der SPM-Befehl nur aus diesem Bereich ausgeführt werden kann, macht klar, dass jegliche Flash-Speicher- Modifikationen nur mit Hilfe der Bootfunktion realisierar sind. Diese Anwendung stellt wohl auch die häufigste und mächtigste dar, da SPM-Aktionen den gesamten Flash-Speicher manipulieren können, also auch den Speicherplatz des eigenen Aufrufs. Denkbar wäre aber jegliche initiale Anwendung, die aus irgendeinem Grund nicht am Beginn des Flash-Speichers stehen soll. 3.2 Anwendungsbeispiel: Bootloader zur Reprogrammierung In dieser Abhandlung soll die Nutzung des Bootbereiches durch einen Bootloader, der neue Daten für den Flash-Speicher über die serielle Schnittstelle des Mikrocontrollers empfängt, erläutert werden. Der komplette Bootloader ist im Rahmen einer Studienarbeit des Verfassers entstanden (siehe [Sch06]) und umfasst fast 200 Zeilen Assembler-Code, weshalb hier nur die Funktion der einzelnen Module erläutert wird. Zur Nutzung muss das BOOTRST-Bit gesetzt sein, damit nach einem Reset oder beim Anschalten stets an den Beginn des Bootbereichs gesprungen wird. Initialisierung einiger Konfigurationsregister Warten des µc auf Daten über die serielle Schnittstelle oder Drücken eines Tasters für Applikationsstart (jmp zu $0000)
3 ANWENDUNG DER BOOTFUNKTION 15 Initialisierungsbyte eines Hosts über die serielle Schnittstelle empfangen, Zurücksenden des Komplements an den Host Empfangen eines Page-Index über die serielle Schnittstelle, Testen auf terminierendes Byte (0xFF), Speichern des Index im RAM Empfangen der Datenbytes für eine komplette Page und Schreiben in den temporären Page-Speicher Löschen der indizierten Page Schreiben der indizierten Page mit den Daten aus dem Page-Pufferspeicher Reaktivierung des RWW-Bereiches, falls terminierender Index (0xFF) empfangen worden ist Lesen eines Page-Index aus dem RAM Senden des Page-Index und der dazugehörigen Page-Daten über die serielle Schnittstelle an den Host (zwecks Validierung der Übertragung) Senden eines terminierenden Bytes (0xFF) um Ende der Datenübertragung anzuzeigen Warten des µc auf Drücken eines Tasters für Applikationsstart (jmp zu $0000)
LITERATUR 16 Literatur [Atm04] Atmel: Application note AVR 109: Self Programming, 2004. [http://www.atmel.com/dyn/resources/prod_documents/doc1644.pdf]. [Atm05] Atmel: Datenblatt AVR ATmega16, 2005. [http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf]. [Lan05] Lanconelli, Claudio: Programmiersoftware Ponyprog, 2005. [http://www.lancos.com/prog.html]. [mik] [Sch06] Mikrocontroller.net. [http://www.mikrocontroller.net/]. Schroeder, Markus: Programmierboard und -software für ATmega16, 2005/2006. [http://www.uni-koblenz.de/ physik/informatik/studienarbeiten/schroeder.pdf].