Hallo zusammen! Ich habe folgendes getan: 1.) Bestehendes Keil-Projekt (zuvor erstellt mit ARMCC & Co.) mit Änderungen in Startups versehen und mittels Gcc compiliert (im Visual Studio). Das lief dann auch nach einigen Verrenkungen recht gut. Die Option "-ggdb" liefert mir auch schönen Debug-Code, wie's scheint. 2.) Das Gebinde: Mittels diverser Linker-Skript-Vorlagen und der ausführlichen Beschreibung des "ld" habe ich mir ein STM32-Linker-Skript gebastelt, was meiner Ansicht nach funktionieren müsste. Kann ich auch auf Anfrage gerne mal posten. Das Linken funktoiniert dann auch ohne Warnung und Fehler. Ich lade das Programm mittels ULINK2 auf mein MCBSTM32E (bestückelt mit STM32F103ZE) und gehe in den Debugger (und ja, der Debugger akzeptiert das anscheinend, zu meiner größten Überraschung). Das Programm läuft in meine liebliche main()-Routine und ich steppe frohen Mutes durch die ersten Funktoinen (RCC_Init, GPIO_Init...). Und jedoch: Just im UART_Init passiert es dann in einer der Unterfunktionen, die den UART einstellen: Die Baudrate hat total krude Werte. Ich hatte im Laufe meiner Versuche das Vergnügen, irgendeine Konstellation im Linker-Skript (denn nur dort habe ich dann noch Änderungen vorgenommen) zu haben, die mir eine gültige UART-Konfiguration ermöglichten. Später dann, mit der endgültigen Fassung aber nicht mehr. Ich muss also etwas "verschlimmbessert" haben, und weiß nicht was. Ich konnte die fehlerhafte Baudraten-Konfiguration auf ein Variablen-Feld im Modul für die UART-Konfiguration (keine Lib, Bestandteil des bestehenden Projekts, also quasi selsbtgetrickt und mit ARMCC voll funktionsfähig) zurückführen. Dort stehen definitiv bei jedem Run mittels Gcc-Umgebung eben falsche Werte drin. Das verhält sich ungefähr so: Modul UART.c: static aucWichtigWerte[] = {0, 1, 2, ..., n}. { blah; blubb; Baudrate = {Rechnerei, mittsl aucWichtigWerte}; ] ... Ende des Moduls. Nur, dass da statt 0, 1, 2,... 13, 76, 7, usw. drin steht, wenn ich mit dem Debugger das Modul betrete. Meine Schlussfolgerung: Aufgrund eines Fehlers im Linker-Skript geht die Variablen-Initialisierung schief! Ich poste das Skript auch gerne mal, habe es nur gerade nicht greifbar. Grundsätzlich muss ich aber doch folgendes tun: .text-Sektion .data-Sektion .bss-Sektion festlegen; sowie evtl. zu exporierender Symbole... Oder ist da bereits ein Denkfehler? Müssen evtl. noch weitere Sektionen definiert werden? Oder muss ich in der Daten-Sektion mittels "KEEP" festlegen, dass mir auch nicht explizit referenzierte Variablen erhalten bleiben; wobei ich diese Option, ehrlich gesagt, noch nicht ganz verstanden habe. Naja, vielleicht hat ja jemand eine Idee. Vielen Dank im voraus! Thomas.
Stammen die in der Berechnung verwendeten Variablen aus einer anderen C-Datei? Dann ist vermutlich dieses Problem: https://isocpp.org/wiki/faq/ctors#static-init-order
Hi Fabian, nein, das ist es nicht. Die Datei heisst stm32f10x_rcc.c und definiert dort das Feld: static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; Diese Initialisierung stimmt schon nicht, wie ich auch im Debugger sehen kann. Da stehen dann Werte 68,... usw. Irgendwie scheint der Linker nicht die korrekten Init-Werte zu übernehmen. Ich hänge die Linker-Datei und das MAP-File einmal an. Seltsam ist, dass das Variablenfeld sich die Lade-Addresse mit anderen zu teilen scheint... Aber vielleicht täuscht das auch. Ich gebe zu, die Tiefen des Gcc-Linkers sind Neuland für mich. Gruß, Thomas.
Hi, stimmen denn die Werte im Flash? was steht im Hex-File?(ELF) oder vorher ins List-File schauen. So sieht es doch IO aus. oder wo meinst du liegt der Fehler genau? Die anderen Symbole haben aber eine Länge von 0 Byte.
Stephan schrieb: > Hi, > stimmen denn die Werte im Flash? > was steht im Hex-File?(ELF) oder vorher ins List-File schauen. > So sieht es doch IO aus. oder wo meinst du liegt der Fehler genau? > Die anderen Symbole haben aber eine Länge von 0 Byte. Hallo Stephan, ja, im List-File zu stm32f10x_rcc stehen die richtigen Initialwerte drin. Das ELF müsste ich dahingehend mal mit einem Hex-Editor anschauen. Die Länge von 0 der übrigen Symbole macht mich ebenfalls nachdenklich... Jedenfalls müsste das Array ADCPrescTable eben tatsächlich die Werte des List-Files haben (hänge ich an!): 0, 0, 0, 0, 1, 2, 3, 4, usw. Es stehen dann aber Werte wie 58, 40, usw. dort, sobald ich das Modul im Debugger betrete. Im Simulations-Modus des µVision funktioniert das ganz prächtig, falls ich dann auch im Linker-File die Anweisung weglasse, dass die Initialisierungswerte im ROM (APP) zu finden sind. Dann scheint sich der Debugger die Werte anderweitig zusammenzuklauben. Natürlich taugt das für das Laden ins reale Flash nicht. Ein weiteres Phänomen ist, dass ich zwar im Einzelschritt-Betrieb in die einzelnen Funktionen hereinkomme, im Aufruf ("F10") jedoch in eine Exception gesprungen wird. Wahrscheinlich stimmen da auch weitere Sachen noch nicht. (Gilt nur für Betrieb mit realem STM32-Board!) Gruß, Thomas.
Hi, also so sieht es doch gut aus. Kann es am Startup code liegen? - die Daten werden ja vom Flash in den RAM kopiert (von 0x08005904 nach 0x20000010) Thomas Bartzick schrieb: > Im Simulations-Modus des µVision funktioniert das ganz prächtig, falls > ich dann auch im Linker-File die Anweisung weglasse, dass die > Initialisierungswerte im ROM (APP) zu finden sind. Dann scheint sich der > Debugger die Werte anderweitig zusammenzuklauben. Das verstehe ich nicht!?!
>static aucWichtigWerte[] = {0, 1, 2, ..., n}.
Wenn das schiefgeht, fehlt in deinem Startupcode die Initialisierung des
entsprechenden Speichersegments.
Oliver
Hallo Oliver & alle anderen, es verhält sich wirklich so: Der Initialisierungscode, der angesprungen wird, ist anscheinend nur für Simulationsbetrieb bestimmt ("__cs3_start" und folgende Routinen). Nach einem Hinweis aus dem Netz habe ich mir nun meine eigene Initialisierungsroutine in C-Code geschrieben, die das Problem löst. Des Weiteren ergab sich noch das Problem, dass die Interrupt-Vektor-Tabelle, die ich aus einem Beispiel-Projekt übernommen habe nicht mit entsprechendem Code "unterfüttert ist". Wird dann ein Interrupt (z.B. SysTick) ausgelöst, springt der ins Leere. Dies erklärt auch, warum ich zwar im Einzelschritt-Betrieb debuggen konnte (auf realem Board), aber im Falle eines Freilaufs ins Nirvana gesprungen bin. Auf die schnelle habe ich daraufhin nach der Takt- IVEC und Timer-Initialisierung alle Interrupts verboten (da ich diese im Augenblick nicht benötige). Zusammen mit besagter Initialisierungs-Routine läuft nun alles einwandfrei. Gruß & Danke, Thomas. P.S.: Code-Schnippsel, falls das mal jemand nachvollziehen möchte: In der main.c: --- //! Some linker imports. extern t_uint32_t _etext; extern t_uint32_t __cs3_region_start_ram; extern t_uint32_t __cs3_region_end_ram; extern t_uint32_t __cs3_region_start_bss; extern t_uint32_t _end; --- Dies sind Symbole aus meinem Linker-File, die hier extern geholt werden. Es folgt der Initialisierungs-Code: --- int main(void) { //! Configuration of the system. /* Configure the system clocks */ RCC_Configuration(); /* NVIC Configuration */ NVIC_Configuration(); GPIO_Configuration(); TIMER_Configuration(); //! Disable interrupts, therefore not used here. __ASM volatile ("cpsid i" : : : "memory"); USART_Configuration(); uprintf("\n\r"); ... } // main() void Init(void) // Hier werden die Initialisierungswerte ins RAM kopiert. Die Regionen entsprechen dem mit *(.data)-Bereich aus dem Linker-File. { unsigned long *src, *dst; /* copy the data segment into ram */ src = &_etext; dst = &__cs3_region_start_ram; if (src != dst) while(dst < &__cs3_region_end_ram) *(dst++) = *(src++); /* zero the bss segment */ dst = &__cs3_region_start_bss; while(dst < &_end) *(dst++) = 0; } void __cs3_start_c(void) // Hier wird auf die vom Linker erwartete Startup-Routine für C-Code Bezug genommen. { Init(); main(); } --- (Mit Dank an den Autor der Vorlage aus dem Netz!)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.