Datum:
Angehängte Dateien: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
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!
Datum:
Hast du schon mal versucht die Sprungmarken manuell zu setzen? PS: Kann es sein, dass du auf Männer stehst? Kam mir gerade so rüber als ich zwischen den Zeilen las.
Datum:
Horst der Drachentöter schrieb: > Hast du schon mal versucht die Sprungmarken manuell zu setzen? Das würde gehen, aber dann müsste ich die ja nach jedem compilen von Hand neu setzen. > PS: Kann es sein, dass du auf Männer stehst? Kam mir gerade so rüber als > ich zwischen den Zeilen las. Klar, ich verwende nur Pinke Gucci-Mikrocontroller
Datum:
Habe jetzt nach unendlicher Suche und Fummelei und Starren auf den Hexeditor den Fehler doch noch gefunden. Im Linkerscript muss statt
/* used by the startup to initialize data */
_sidata = .;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
|
folgendes
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
|
stehen. Offenbar hat wird .data um ein word nach hinten geschoben, aber _sidata zeigt dann auf das word davor. Mit dieser Änderung zeigt _sidata immer auf die tatsächliche Adresse von .data . Hoffentlich ...