Hi,
Ich möchte über die UART Schnittstelle ein paar Daten ausgeben, doch
leider scheint das Programm bei sprintf(str, "Acceleration X: %d",5) zu
hängen, alles andere wird nicht mehr ausgeführt. Anscheinend
funktioniert das mit dem %d nicht, kennt das Problem Jemand? Strings
kann ich sonst problemlos ausgeben. Ich habe das mit dem Debugger
getestet, der Wert von i existiert und es crasht nicht vor sprintf.
hp-freund schrieb:> sprintf(str,"Test");>> Funktioniert?
Ja das geht, da kann ich auch die schleife laufen lassen und ich bekomme
etwa alle halbe Sekunde ein Test im Terminal.
Hallo Sebastian,
du musst lernen, das Problem auf das Wesentliche zu reduzieren. Isoliere
dein Problem und analysiere es dann. All die Schleifen die so manchmal
nicht funktionieren(int ist oft nur 2 Byte lang, dann besser uint32_t
nutzen, das stimmt immer) verschleiern doch nur die Problemchen. Ist
deine Senderoutine Interrupt-basierend? Sind die Puffer richtig gesetzt?
Sende am besten erst mal ein Byte und bastle dir dann den String selbst
zusammen. Das hilft beim Verständnis ungemein.
Sebastian T. schrieb:> int i=MPU6050_Data.Accelerometer_X;> sprintf(str, "Acceleration X: %d",5)
was soll das bewirken? Das funktioniert doch nicht. wo kommt den da die
5 her, wofür ist die gut? Wo ist die Variable?
Stromverdichter schrieb:> Das funktioniert doch nicht. wo kommt den da die 5 her, wofür ist die> gut? Wo ist die Variable?
Vielleicht geht es um die Reduzierung auf das wesentliche?
Würde auch auf zu kleinen Stack tippen, printf ist da sehr hungrig.
Oder falsches/fehlendes include? Wird alles ohne Warnings übersetzt?
Klingt für mich spontan auch nach einem Stack-Überlauf.
Da die STMF4xx Derivate mehrere KB RAM bereitstellen, einfach mal mit
"großzügigen" Werten
_Min_Heap_Size = 0x1000;
_Min_Stack_Size = 0x1000;
in der Linker-Steuerdatei testen. Die Datei ist an der Endung .ld
erkennbar.
Stromverdichter schrieb:> was soll das bewirken? Das funktioniert doch nicht. wo kommt den da die> 5 her, wofür ist die gut?
Das war nur zum testen, ich habe das Programm nun mal auf das
wesentliche reduziert, das Versenden von Integer Variablen.
Ich habe die _Min_Heap_Size auf 0x1000 gesetzt, doch leider ohne Erfolg.
Nop schrieb:> Ich nehme mal an, itoa wäre zu einfach als Lösung, ne?
itoa funktioniert, es wird nur ein bisschen mühsamer alle Sensordaten zu
senden. Mich laust es aber, warum das mit sprintf nicht geht.
Gab es bei dem STM32 mit GCC nicht Alignment Probleme im Demo-Code? Ich
hab es jetzt nicht genau im Kopf, aber die linker files hatten afair
eine falsche Stack-Adresse drin stehen. Welches Linker Script benutzt
du?
Jannyboy schrieb:> Sebastian T. schrieb:>> sprintf(str, "Test Number: %d",5);>> So kann das nicht funktionieren 5 ist keine Integer Variable.
Unsinn, natürlich funktioniert das (gerade getestet). Es muß ein Integer
übergeben werden, und selbstverständlich kann das auch eine Zahl sein.
Zum testen könntest du mal
char str[16];
kleiner machen und alternativ das array außerhalb der main global
deklarieren, dann sollte es doch nicht auf dem Stack liegen.
Hoffentlich findest du bald den Fehler, ich bin echt gespannt, wo er
liegt. Den Stack kannst du dir nicht einfach mal mit dem Debugger
anschauen?
Sebastian T. schrieb:> TM_USART_Puts(USART1, str);
Und Du bist sicher, dass TM_USART_Puts blockierend arbeitet und den
Inhalt von str nicht vorher umkopiert?
Ich habe alles mögliche probiert, leider immer noch kein Erfolg. Ich
kann auch nicht mit dem Debugger in sprintf rein um zu sehen, was genau
passiert. Auf den Mikrocontrollern ist ja meist eine gekürzte Version
von printf drauf, doch wo kann ich die einsehen/ändern? Es liegt ganz
klar an sprintf und nicht an einer anderen Codezeile, es crasht mir
sogar wenn ich nur ein sprintf in der Hauptschleife habe, aber eben nur
wenn ich noch Werte dem String hinzufügen will.
>
a) Schau Dir an, ob Du printf oder sprintf verwenden wolltest
b) schalte die Warnmeldungen ein. Alle.
c) RTFM für sprintf. Egal wo, die ersten 2 Absätze reichen, notfalls nur
die Declaration.
wenn nach 2 Minuten noch etwas unklar sein sollte, melde Dich.
Sebastian T. schrieb:> sprintf(str,"Test");
Da wird aber auch kein sprintf aufgerufen. Der gcc ist mittlerweile so
schlau zu merken, dass dafür ein strcpy(str,"Test"); reicht und sprintf
hier "mit Kanonen nach Spatzen" wäre.
Ich denke das liegt an _sbrk. Das wird bei "sprintf(str,"Test");" nicht
aufgerufen, nur bei "sprintf("test %d",1);"
Was heißt crasht? Was passiert denn wenn du im gecrashten Zustand im
Debugger das Programm unterbrichst? Landest du da im Hardfault oder wo?
Ansonsten die _sbrk mal aus dem Header nehmen und normal mit in das
c-File packen ohne #define. Dann kannst du auch da mal einen Breakpoint
setzen.
>>>> a) Schau Dir an, ob Du printf oder sprintf verwenden wolltest> b) schalte die Warnmeldungen ein. Alle.> c) RTFM für sprintf. Egal wo, die ersten 2 Absätze reichen, notfalls nur> die Declaration.>> wenn nach 2 Minuten noch etwas unklar sein sollte, melde Dich.
Ich habe das hier im Forum nur falsch geschrieben, ich meinte natürlich:
temp schrieb:> Was heißt crasht? Was passiert denn wenn du im gecrashten Zustand im> Debugger das Programm unterbrichst? Landest du da im Hardfault oder wo?
Wenn ich den Debugger verwende und in die Funktion gehen will, passiert
einfach nichts und es scheint in einer loop zu hängen.
temp schrieb:> Ansonsten die _sbrk mal aus dem Header nehmen und normal mit in das> c-File packen ohne #define. Dann kannst du auch da mal einen Breakpoint> setzen.
Werde ich mal probieren, danke.
temp schrieb:> laut deinem mapfile gibt es eine src/syscalls.c. Da stehen normalerweise> diese Sachen drin die für sprintf noch interessant sind. Poste die doch> mal.
Ok, habe das syscalls.c im Anhang. Dort ist ja auch _sbrk definiert.
temp schrieb:> mach doch mal einen Breakpoint da drauf. Da siehst du wenigstens was> passiert.
Das habe ich probiert, doch ich komme gar nie in _sbrk hinein. Auch wenn
ich "step in" klicke im debugger für sprintf(...), dann passiert nichts.
Ich komme auch nicht in sprintf(str,"test"); hinein, obwohl dies
funktioniert.
Kannst du denn den Debugger nicht anhalten und dann sehen wo er steht?
Wenn nicht, dann denk mal über ne vernünftige Entwicklungsumgebung nach.
passt den deine Implementierung der syscall.c zum Linkerscript?
Sebastian T. schrieb:> Ich komme auch nicht in sprintf(str,"test"); hinein, obwohl dies> funktioniert.
Das habe ich eben schon versucht zu erklären. Da steht zwar sprintf aber
der Compiler merkt das da keine Parameter übergeben werden und macht ein
strcpy draus. Deshalb brauchst du da auch nicht weiter forschen.
Hier noch ein Auszug aus deinem map-File:
LOAD
c:/ac6/systemworkbench/plugins/fr.ac6.mcu.externaltools.arm-none.win32_1
.7.0.201602121829/tools/compiler/bin/../lib/gcc/arm-none-eabi/5.2.1/armv
7e-m/fpu/crtn.o
0x20020000 _estack = 0x20020000
0x00000000 _Min_Heap_Size = 0x0
0x00000400 _Min_Stack_Size = 0x400
.isr_vector 0x08000000 0x188
ohne Heap wird das halt nichts. Bau mal ein malloc in deinen Code ein.
Das wird dann auch crashen.
temp schrieb:> c:/ac6/systemworkbench/plugins/fr.ac6.mcu.externaltools.arm-none.win32_1> .7.0.201602121829/tools/compiler/bin/../lib/gcc/arm-none-eabi/5.2.1/armv> 7e-m/fpu/crtn.o> 0x20020000 _estack = 0x20020000> 0x00000000 _Min_Heap_Size = 0x0> 0x00000400 _Min_Stack_Size = 0x400>> .isr_vector 0x08000000 0x188>> ohne Heap wird das halt nichts. Bau mal ein malloc in deinen Code ein.> Das wird dann auch crashen.
Ich habe den Heap und Stack auch schon auf 0x1000 getan, leider kein
Erfolg.
Sorry, aber das passt alles nicht zusammen. Wenn du in deiner IDE was an
den Einstellungen drehst muss sich das auch im map-File wieder finden.
Auch die Symbole im Code müssen zum Linkerscript passen. Ich vermute mal
das wurde alles irgendwie zusammen kopiert ohne zu wissen wie es
zusammenhängt. Deshalb nochmal die Frage: Wer hat dir den die syscalls.c
ins src Verzeichnis gezaubert und wie passt die zum Linkerscript? Poste
das Linkerscript oder ein mini-Projekt mal komplett. Im Moment stocherst
du nur im trüben und bist meilenweit von einer systematischen
Fehlersuche entfernt.
nimm die syscalls.c mal raus aus deinem Projekt und berichte die
Linkerfehler. Vielleicht hat dir die IDE, das unbekannte Wesen, schon
alles richtig zusammengebaut und du versuchst krampfhaft deine eigenen
Versionen zu linken und gewinnst.
Sebastian T. schrieb:> temp schrieb:>> mach doch mal einen Breakpoint da drauf. Da siehst du wenigstens was>> passiert.>> Das habe ich probiert, doch ich komme gar nie in _sbrk hinein. Auch wenn> ich "step in" klicke im debugger für sprintf(...), dann passiert nichts.> Ich komme auch nicht in sprintf(str,"test"); hinein, obwohl dies> funktioniert.
Bei derart hartnäckigen Problemen hilft Assembler-Level Debugging.
Benutze "stepi" im GDB um jede Instruktion einzeln auszuführen.
Irgendwann wird es dann ja abstürzen/stehen bleiben/Im Fault Handler
landen. Dann siehst du woran es gelegen hat.
Ich tippe mal auf eine andere Baustelle. Fpu benutzt und nicht
initialisiert.
Schreib das mal an den Anfang deines Codes:
volatile float f=1.123f;
f/=3.567f;
Wenn es dann schon abschmiert hast du die Ursache.
SCB->CPACR|=((3UL<<10*2)|(3UL<<11*2));/* set CP10 and CP11 Full Access */
6
#endif
7
/* Reset the RCC clock configuration to the default reset state ------------*/
8
/* Set HSION bit */
9
RCC->CR|=(uint32_t)0x00000001;
10
11
/* Reset CFGR register */
12
RCC->CFGR=0x00000000;
13
14
/* Reset HSEON, CSSON and PLLON bits */
15
RCC->CR&=(uint32_t)0xFEF6FFFF;
16
17
/* Reset PLLCFGR register */
18
RCC->PLLCFGR=0x24003010;
19
20
/* Reset HSEBYP bit */
21
RCC->CR&=(uint32_t)0xFFFBFFFF;
22
23
/* Disable all interrupts */
24
RCC->CIR=0x00000000;
25
26
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
27
SystemInit_ExtMemCtl();
28
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
29
30
/* Configure the Vector Table location add offset address ------------------*/
31
#ifdef VECT_TAB_SRAM
32
SCB->VTOR=SRAM_BASE|VECT_TAB_OFFSET;/* Vector Table Relocation in Internal SRAM */
33
#else
34
SCB->VTOR=FLASH_BASE|VECT_TAB_OFFSET;/* Vector Table Relocation in Internal FLASH */
35
#endif
36
}
__FPU_PRESENT wird an anderer Stelle automatisch gesetzt wenn
__FPU_USED=1 definiert ist.
Oder kommentier das #if und #endif vor und nach
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11
Full Access */
aus. Bin mir zu 95% sicher dass das dein Problem ist!
temp schrieb:> Bin mir zu 95% sicher dass das dein Problem ist!
Wow, vielen Dank, genau das war das Problem. Ich verwende Openstm32 und
die syscalls.c sowie die system_stm32f4xx.c wurden automatisch erzeugt.
In SystemInit() hat SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));
komplett gefehlt.
Grüsse und Danke
Sebastian