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.

vorlesen Druckansicht
Lesezeit: 4 Min.
Von

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:

  1. Die ersten acht 32-Bit-Werte ab Adresse 0x00000000 werden addiert. Nur wenn das Ergebnis 0 ist, wird beim nächsten Punkt weiter gemacht.
  2. Der Stackpointer wird mit dem 32-Bit-Wert geladen, der an Adresse 0x00000000 abgelegt ist.
  3. Der 32-Bit-Wert an Adresse 0x00000004 wird als Startpunkt des Programmcodes fĂĽr den Mikrocontroller verwendet (Reset Handler).
  4. 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 Datei startup.c. Jedoch kann in C nicht direkt festgelegt werden, dass dieses Array an der Adresse 0x00000000 starten soll. Dies erfolgt in der zugehörigen Linker Description (das ist die Datei lpc11u35.ld): Über einen zusätzlichen Namen ("section identifier", hier: ".isr_vector") wird die Tabelle durch die Linker Description genau an die Adresse 0x00000000 platziert. 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)