Hallo,
Nachdem ich ein Problem damit hatte, den STM32 zu starten und es im
Endeffekt ein Speicherproblem war
(Beitrag "STM32 ohne JTAG starten") möchte ich dem nun auf den
Grund gehen, weil ich sehr viele merkwürdige Phänomen habe.
Meine Debug-Ausgaben mache ich so:
while(*c)u_putchar(*c++);// send string char by char
11
}
12
13
#ifdef T_DEBUG
14
uputs("START\r\n");
15
#endif
Sobald ich alle (oder einige) Debug-Ausgaben ausschalte, funktioniert
das Programm fehlerfrei.
Sind alle Debug-Ausgaben aktiv, habe ich sehr merkwürdige Fehler.
Z.B. startet der STM32 nicht 2x, er stürzt ab, Variablen aus dem Eeprom
haben falsche Werte etc.
Beim AVR lag es daran, weil die Debug-Texte im RAM lagen und mir den
Stack zerstört haben. Mit PSTR und pgmspace konnte ich die Texte in den
Flash legen und das Problem lösen.
Aber der ARM hat eine andere Speicherarchitektur und legt Strings
automatisch in den Flash?
Ich benutze einen STM32F105RB. 128k Flash, 32k RAM.
Das Linkerskript ist von M.Thomas, nur angepasst auf 32k RAM.
Wie macht ihr Debug-Ausgaben bzw. arbeitet mit Strings?
Sieht das Linkerskript ok aus?
Wo kann ich noch schauen?
Vielen Dank :)
Florian Micro schrieb:> Aber der ARM hat eine andere Speicherarchitektur und legt Strings> automatisch in den Flash?
Das ist wohl weniger Aufgabe des ARM, als der Kombination
Compiler/Linker!
Schau Dir doch einfach das Map-File an, da steht doch die Adresse jeder
Konstante/Variable drin.
Dein uputs läuft den gesamten Speicher ab, da die while-Schleife immer
gültig ist. Versuchs entweder mit einer fixen Größe oder einer
vernünftigen Endbedingung für den String, z.B. mit (*c == '\r').
Wayne schrieb:> Dein uputs läuft den gesamten Speicher ab, da die while-Schleife immer> gültig ist.
Wieso? Ein Test auf '\0' ist bei Strings in C nicht eben selten.
Wayne schrieb:> Aber zeig mir, wo das im Code-Schnipsel des Threaderstellers> passiert?Florian Micro schrieb:> while(*c) u_putchar(*c++)
sobald eine \0 auftaucht ist *c == 0. D.h. die While-Schleife wird
verlassen. (In C sind alle werte ungleich 0 True, die 0 ist False)
Ist ziemlich egal, denn zumindest bei string literals ("abcd") ist
bekannt, was hinten dran hängt: '\0'. Bei Debug-Ausgaben sind meist
literals.
Interessanter wäre, wo die Debugs alle stehen. Mancher müllt sich seine
Interrupt-Handler mit Warteschleifen so voll, dass es eng wird. Oder hat
dort nicht genug Stack vorgesehen. Tausend Möglichkeiten.
Beim ersten Beispiel macht der Compiler die \0 automatisch ans Ende und
beim zweiten Beispiel macht das die sprintf Funktion.
Meine Variablen sind auch immer lang genug, dass die \0 reinpasst.
Das sollte nicht das Problem sein und deshalb stürzt er auch nicht ab.
Die Interrupts sind sauber und sehr kurz. Keinerlei Debug-Texte.
Den Stack habe ich von 1024 Byte auf 8192 Byte angehoben ohne jegliche
Änderung.
Jetzt ist er auf 4096 Byte.
Wenn ich das Programm aktuell ohne meine Debugs kompiliere habe ich
diese Ausgabe:
section size addr
.text 58660 134217728
.ARM.exidx 8 134276388
.rodata 5784 134276400
.data 1904 536870912
.bss 576 536872816
._usrstack 4096 536873392
.comment 1470 0
.debug_aranges 5048 0
.debug_pubnames 15278 0
.debug_info 76211 0
.debug_abbrev 13582 0
.debug_line 28193 0
.debug_frame 18532 0
.debug_str 25133 0
.debug_loc 51625 0
.debug_ranges 5176 0
.ARM.attributes 49 0
Total 311325
Mit meinen Debugs:
section size addr
.text 59468 134217728
.ARM.exidx 8 134277196
.rodata 6768 134277208
.data 1904 536870912
.bss 568 536872816
._usrstack 4096 536873384
.comment 1470 0
.debug_aranges 5064 0
.debug_pubnames 15322 0
.debug_info 76297 0
.debug_abbrev 13582 0
.debug_line 28322 0
.debug_frame 18564 0
.debug_str 25169 0
.debug_loc 51696 0
.debug_ranges 5192 0
.ARM.attributes 49 0
Total 313539
Wo läuft das was über? Bin ziemlich verzweifelt...
Florian Micro schrieb:> Den Stack habe ich von 1024 Byte auf 8192 Byte angehoben ohne jegliche> Änderung. Jetzt ist er auf 4096 Byte.
Bei ARMs vergessen manche die Interrupt-Stacks. Die meinte ich.
Muss man die Interrupt-Stacks noch definieren oder initialisieren?
Ich habe die startup Datei nochmal kontrolliert und korrigiert.
Das Linkerskript scheint ok.
Der Fehler bleibt...
Ich kann zwar die Zeilen auskommentieren, wo der ARM abstürzt, aber dann
stürzt er einfach ein bisschen später ab.
Er springt in den Default_Handler.
Eine konkrete Stelle wo er abstürzt:
1
charText[30]=" ";
2
sprintf(Text,"Bat: %0.1f",Battery);
Kommentiere ich das aus, stürzt er beim nächsten sprintf mit %f ab.
Andere sprintf mit %i dazwischen funktionieren.
1
sprintf(Name,"Temp: %i ",Temp);
Was ist da anders? Wird da ein bestimmtes Register oder besonders viel
Speicher benutzt?
Florian Micro schrieb:> Muss man die Interrupt-Stacks noch definieren oder initialisieren?
Sorry, ich war grad beim falschen Controller. Ist ein Standardfehler bei
den ARM7 aber nicht beim STM32.
Bei dem wär's hilfreich, wenn du erfährst, welche Exception ausgelöst
wurde (Default_Handler ist nicht hilfreich). Und anhand der
Steuerregister vom Core rauskriegst, welcher Zugriff d.h. welche Adresse
das war.
Ich habe jetzt folgende Handler noch implementiert:
MemManage_Handler
BusFault_Handler
UsageFault_Handler
Dann einen Breakpoint auf die Stelle gesetzt, wo er abstürzt und mit
Single Step rein.
OpenOCD zeigt dann das an:
Scheint so, dass ich den Fehler gefunden habe :)
Keine Abstürze mehr und das Teil startet auch nach Stromreset neu.
Vielen Dank fürs Helfen! Hab wieder viel gelernt :)
Ich hab viel über die Exceptions und Fault Handler gelesen.
Der BusFault kommt wohl nur, wenn etwas mit dem Speicher nicht stimmt.
Also bin ich das Linkerskript nochmal durch. Das war ok.
Aber ich benutze emuliertes Eeprom, das hinten im Flash liegt. Wird zwar
auch im Linkerskript definiert, aber nochmal in der eeprom.h!
Und da liegt das standardmäßig bei 64k.
Jetzt hat mein Programm wohl die 64k geknackt und sich damit mit dem
Eeprom überschnitten.
Das Eeprom liegt jetzt bei 124k (mein STM32 hat 2kb Pages und 2 braucht
man fürs Eeprom, also 4k).
Für mich ist das total nachvollziehbar.
Durch das auskommentieren der Debug-Meldungen wurde mein Programm
kleiner und hat damit nicht mehr im Eeeprom Bereich gewildert (bzw.
andersrum).
>Geh diesen Teil mal auf Maschinenebene Schritt für Schritt durch.
Wir kann ich das machen in Eclipse? Step into? Da ist er bei mir sofort
in den FaultHandler.
Meine Definition für das Eeeprom sieht im Linkerskript jetzt so aus:
>EEMUL (RWX) : ORIGIN = 0x08000000+128K-4K, LENGTH = 4K
Kann ich darauf aus meiner Header oder C-Datei irgendwie zugreifen?
Dann muss man nicht an zwei Stellen ändern.