GPS-Logger
In der Make-Ausgabe 3/17 beschreibt Oliver Kraus ausführlich seinen selbstgebauten GPS-Logger. Im folgenden Zusatzartikel geht er auf Details des Codes ein – insbesondere, was zwischen einem Reset und dem Aufruf der main()-Funktion passiert.
- Oliver Kraus
- Peter König
Wie man in jeder Schulung zu C lernt, beginnt das eigene Programm mit dem ersten Befehl in der Prozedur main(). Das gilt nicht ohne weiteres beim Arbeiten mit einem Mikrocontroller. Abgesehen davon, dass jeder Hersteller einen eigenen Weg beschreitet, wie der Code gestartet wird, mĂĽssen vor der AusfĂĽhrung von main() noch einige Daten kopiert und initialisiert werden.
Im LPC11U35 geschieht nach einem Reset folgendes:
- Die ersten acht 32-Bit-Werte ab Adresse
0x00000000werden addiert. Nur wenn das Ergebnis 0 ist, wird beim nächsten Punkt weiter gemacht. - Der Stackpointer wird mit dem 32-Bit-Wert geladen, der an Adresse
0x00000000abgelegt ist. - Der 32-Bit-Wert an Adresse
0x00000004wird als Startpunkt des Programmcodes fĂĽr den Mikrocontroller verwendet (Reset Handler). - Im Reset Handler mĂĽssen nun die notwendigen Daten fĂĽr das C-Programm initialisiert und dann die Prozedur
main()gestartet werden.
Wenn man seine eigene Software erstellt, müssen also neben der Prozedur main() und dem Reset Handler die oben erwähnten acht 32-Bit-Werte angelegt und an der richtigen Stelle im Speicher (0x00000000) platziert werden. Tatsächlich handelt es sich hierbei um die ersten acht Werte der Interrupt-Vector-Tabelle, die insgesamt 48 Werte enthält (siehe Seite 445 im Datenblatt des LPC11U35 [PDF]).
| Die verkĂĽrzte Form der Interrupt-Vector-Tabelle | |
| 0x00000000 | Startwert fĂĽr den Stack-Pointer |
| 0x00000004 | Adresse des "Reset Handlers" |
| 0x00000008 | Adresse des "non-maskable interrupt handlers" |
| 0x0000000c | Adresse des Handlers zur Behandlung von Hardwarefehlern |
| ... | – |
| 0x0000001c | PrĂĽfsumme (so dass die ersten 8 Werte dieser Tabelle 0 ergeben) |
| ... | – |
| 0x000000bc | Handler fĂĽr IRQ31 |
In C wird nun genau dieses Array mit 48 Werten angelegt. Bei der Firmware des GPS-Loggers passiert das in der Dateistartup.c. Jedoch kann in C nicht direkt festgelegt werden, dass dieses Array an der Adresse0x00000000starten soll. Dies erfolgt in der zugehörigen Linker Description (das ist die Dateilpc11u35.ld): Über einen zusätzlichen Namen ("section identifier", hier:".isr_vector") wird die Tabelle durch die Linker Description genau an die Adresse0x00000000platziert. Im C-Code sieht das ganze etwas kompliziert aus:
isr_handler_t __isr_vector[48] __attribute__ ((section(".isr_vector"))) __attribute__ ((aligned(4))) =
{
__StackTop, /* 0x00: Top of Stack, calculated by the linker script */
Reset_Handler, /* 0x04: Reset Handler */
NMI_Handler, /* 0x08: NMI Handler */
HardFault_Handler, /* 0x0c: Hard Fault Handler */
0, /* 0x10: Reserved, must be 0 */
0, /* 0x14: Reserved, must be 0 */
0, /* 0x18: Reserved, must be 0 */
LPC_checksum, /* 0x1c: Checksum, calculated by the linker script */
...
Entscheidend ist vor allem das section(".isr_vector"). Das ist noch nicht alles. Das Linkerscript muss dem C-Code noch zwei wichtige Informationen liefern:
- Den Startpunkt des Stackbereichs (im Code:
__StackTop) - Die PrĂĽfsumme (
LPC_checksum)
__StackTop wird in der Linker Description auf das Ende des RAM-Bereichs gesetzt (der Stack wächst von oben nach unten). Die Berechnung des Werts LPC_checksum erfolgt am Ende der Linker Description:
LPC_checksum = 0- (__StackTop + Reset_Handler + NMI_Handler + HardFault_Handler + 3 /* three entries */);
Wie bereits oben erwähnt, müssen die ersten acht Werte 0 ergeben. Umgeformt kommt hier jedoch 3 heraus:
LPC_checksum __StackTop + Reset_Handler + NMI_Handler + HardFault_Handler = 3
@$:Diese Korrektur um 3 hängt damit zusammen, dass ARM-Prozessoren mehrere Befehlssätze unterstützen. Da das unterste Bit der Adresse nicht benötigt wird (alle Adressen müssen gerade sein), wird das unterste Bit verwendet, um anzuzeigen, dass sich an der Zieladresse Programmcode im sogenannten "thumb"-Befehlssatz abgelegt ist. Weil aber einerseits C-Compiler und Linker Description mit den geraden Adressen arbeiten, andererseits aber später im Binärcode die um eins höheren Adressen stehen werden, muss die Prüfsumme für jeden Handler um eins, in Summe also um 3, korrigiert werden.
- Den vollständigen Artikel zum GPS-Logger von Oliver Kraus lesen Sie in der Make-Ausgabe 3/17 ab Seite 46.
(pek)