Hallo Forum,
ich versuche mit dem ARM-GCC https://launchpad.net/gcc-arm-embedded/
unter Windows ein C/C++ Programm für den STM32F4 zu kompilieren. Ich
habe dazu das Linker-Script und den Startupcode aus dem Beispiel von ST
übernommen.
Das hat zunächst auch geklappt, dann habe ich eine Winzigkeit im Code
verändert, und es folgten obskure Probleme, die darauf zurückzuführen
sind, dass globale Variablen nicht richtig initialisiert wurden. Der
Grund ist:
Der Linker packt in den Flash den ISR-Vector, den Programmcode, und
danach drei Arrays preinit_array, init_array, fini_array aus
Funktionspointern (d.h. einfach Flash-Adressen), die beim Starten /
Beenden des Programms aufgerufen werden (Kon/de -struktoren von globalen
Instanzen von C++ Klassen). Danach folgen an einem Stück die
Initialisierungsdaten für die globalen Variablen.
Der Linker setzt dann, wie im ld-Script angegeben, folgende Labels:
- _sidata, die Anfangsadresse der Initialisierungen im Flash
- _sdata der Anfang der zu initialisierenden Daten im RAM
- _edata das Ende dieser Daten
Der Startupcode macht dann quasi ein
1 | memcpy(_sdata, _sidata, _edata-_sdata);
|
in Assembler, was alle globalen Variablen initialisiert. Nun scheint
aber bei mir der Linker das _sidata Label falsch zu setzen, und zwar um
4 Bytes zu klein, sodass der Startupcode die falschen daten (nämlich das
fini_array) in den RAM kopiert, sodass alle globalen Variablen falsch
gesetzt sind... Und ich habe keine Ahnung, woran das liegt!
Der angehängte Code lässt sich mit "ruby build.rb" kompilieren (dazu
muss man den ruby-Interpreter installiert haben) oder alternativ mit der
build.bat, müsste mit anpassen der Pfade auch unter Linux gehen. Das
kompilat ist um "Debug" Verzeichnis auch mitgeliefert, als .elf, .hex
und .bin sowie die Disassembly. Im letzteren sieht man, dass _sidata auf
0x080021ac gesetzt wird, während die Daten im Flash tatsächlich erst bei
0x080021b0 anfangen...
Hat jemand eine Ahnung was ich falsch mache? Vielen Dank im Voraus!