mikrocontroller.net

Forum: Compiler & IDEs [ARM] Nützliches newlib-nano float printf


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Lukas K. (carrotindustries)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
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

Autor: Jim M. (turboj)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Schaulus Tiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 Moderator
Autor: Lukas K. (carrotindustries)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Roland H. (batchman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Gahlen F. (gahlenfeld)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.