Hallo Zusammen, mal ausnahmsweise keine Frage, sondern (hoffentlich) nützliche Hinweise Leute, die vor ähnlichem Problem stehen: Auf dicken µCs, wie den STM32 kann man sich ja durchaus Dinge wie printf gönnen, auch für floats. Wie zu erwarten tut's mit den notwendigen Linker-Optionen -u _printf_float --specs=nano.specs -lnosys nicht auf anhieb. Aus der mapfile geht hervor, dass sprintf aus der 'normalen' libc kommt, nicht aus der 'nano'. Lösung: GROUP(-lc_nano) im Linkerscript angeben (Quelle: Google). Jetzt wird immerhin _printf_float aufgerufen, aber sprintf schreibt immer noch 0.000 in den Buffer. Reichlich debuggen (inkl. neu bauen von der newlib mit debug-symbolen) hat dann gezeigt, dass die Übergabe von double mit vararg nicht funktioniert (kommt immer 0 raus). Lösung: Damit double (8byte lang) (variadisch?) übergeben werden kann, muss der Stack auf 8bytes aligned sein (Quelle: Google). Floats in varargs werden automatisch zu double befördert. In dem Linkerscript von Atollic Truestudio, das den Beispielen von ST beiliegt, wird der Stack an die Adresse 0x2001FFFF gelegt, was natürlich kein ganzzahliges Vielfaches von 8 ist. Mit 0x2001FFF8 als Stack-anfang/ende tut nun printf für floats. Vielleicht findet's wer und spart sich langwieriges debuggen... Lukas
Lukas K. schrieb: > In dem Linkerscript von > Atollic Truestudio, das den Beispielen von ST beiliegt, wird der Stack > an die Adresse 0x2001FFFF gelegt, was natürlich kein ganzzahliges > Vielfaches von 8 ist. Schick das mal als Bugreport an den Hersteller. Das würde nicht nur bei Floats Probleme machen: Der GCC generiert auch schon mal LDRD Befehle wenn er 64 Bits auf einmal laden kann. Diese Instruktion besteht auf Alignment, anders als da normale LDR (wo das von einem normalerweise nicht gesetztem Bit anhängt).
Jim Meba schrieb: > Der GCC generiert auch schon mal LDRD Befehle wenn er 64 Bits > auf einmal laden kann. Diese Instruktion besteht auf Alignment, > anders als da normale LDR (wo das von einem normalerweise > nicht gesetztem Bit anhängt). Lukas K. schrieb: > Mit 0x2001FFF8 als Stack-anfang/ende tut nun printf für floats. Bist du sicher? Hängt das nicht auch von so einem Bit ab? Damit er 64-Bit aligned bleibt, muss er ja bei jedem push usw. bei Bedarf justiert werden. Das kostet RAM und ist deshalb bestimmt abschaltbar. Ich fürchte, der Default nach Reset ist von Chip zu Chip unterschiedlich.
Lukas K. schrieb: > Lösung: Damit double (8byte lang) (variadisch?) übergeben werden kann, > muss der Stack auf 8bytes aligned sein (Quelle: Google). Floats in > varargs werden automatisch zu double befördert. In dem Linkerscript von > Atollic Truestudio, das den Beispielen von ST beiliegt, wird der Stack > an die Adresse 0x2001FFFF gelegt, was natürlich kein ganzzahliges > Vielfaches von 8 ist. Mit 0x2001FFF8 als Stack-anfang/ende tut nun > printf für floats. Zwischenfrage, weil es mich interessiert. Was ist, wenn du printf nicht mit einem lausigen double alleine aufrufst, sondern da auch noch andere Dinge über den Stack wandern. Dann muss doch das Alignment immer noch garantiert sein. Ich sehe nicht, wie die Stackstartadresse in diesem Fall das Problem beheben könnte. Ein Missalignment ist doch dann unausweichlich.
:
Bearbeitet durch User
Karl Heinz schrieb: > Ich sehe nicht, wie > die Stackstartadresse in diesem Fall das Problem beheben könnte. Ein > Missalignment ist doch dann unausweichlich. Ohne das Problem jetzt nähers angesehen zu haben, meine Vermutung: Der GCC geht von einem 8byte-aligned Stack aus und fügt dann bei Bedarf 4bytes padding ein. Wenn der Stack nicht aligned ist, führt das eben nicht zum gewünschten Ergebnis. Jim Meba schrieb: > Schick das mal als Bugreport an den Hersteller Atollic gibt nur Support für zahlende Kunden, ein solcher bin ich nicht...
Lukas K. schrieb: > Mit 0x2001FFF8 als Stack-anfang/ende tut nun printf für floats. > Vielleicht findet's wer und spart sich langwieriges debuggen.. Danke! Habs vor ein paar Tagen beiseite geschoben, aber so klappts! Karl Heinz schrieb: > Dann muss doch das Alignment immer noch garantiert sein. Ich sehe nicht, wie > die Stackstartadresse in diesem Fall das Problem beheben könnte. Ein > Missalignment ist doch dann unausweichlich. Aus dem "reference manual": "Because the SP ignores writes to bits [1:0], it is autoaligned to a word, four-byte boundary." Schaulus Tiger schrieb: > Damit er 64-Bit aligned bleibt, muss er ja bei jedem push usw. bei > Bedarf justiert werden. Noch ein Zitat: "The Application Binary Interface (ABI) for the ARM architecture requires that the stack must be eight-byte aligned on all external interfaces, such as calls between functions in different source files. However, code does not need to maintain eight-byte stack alignment internally, for example in leaf functions." Schaulus Tiger schrieb: > Hängt das nicht auch von so einem Bit ab? Meinst Du das STKALIGN bit? Das gilt nur beim Auftreten einer Exception, und dann wird aus "four-byte" wieder "eight-byte alignment", so dass es im "fault handler" wieder passt.
Danke, danke, danke !!! Ich bin eigentlich baff, dass dies funktioniert! Ich habe den ganzen lieben langen Tag vor diesem Problem gesessen und alles mögliche untersucht, aber erst Dein Beitrag hat die Lösung gebracht! Ich habe nur den Stack auf 8 aligned, mehr nicht. Viele Grüße, Gahlen
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.