STM32F407 und Double/Float mit FPU

Gast #4220732
Lesenswert?

Hallo.
Ich habe ein Problem mit Keil 5.15 und der Verwendung der FPU auf dem 
STM32F407.

char buffer[100];
float dParam;
strcpy(buffer, (char *) &_cmd[0]); // Kopiert String in lok. Buffer
dParam = atof(Buffer);

In den Projektoptionen hab ich die FPU Hardware mit "Use Single 
Precision" ausgewählt. Obiger Code funktioniert solange dParam vom Typ 
float ist.

Sobald ich "double dParam" verwende erhalte ich immer "fast 0" zurück
(xxe-314).

Schaue ich mir die ASM Befehle im Disassembler an, kann ich sehen, dass 
beide Male __hardfp_atof verwendet wird. Da der STM32F407 aber ja nur 
Single Precision kann, glaube ich, dass dies mein Problem ist.

Ich brauche aber an einigen Stellen die Double-Genauigkeit, die Floats 
müssen aber schnell berechnet werden, da mir sonst meine Regelschleife 
zu langsam wird.

Was kann man da machen ?
#4220813
Lesenswert?

Wie du schon bemerkt hast, kann der STM32F4 nur Single Precision. Willst 
du double rechnen, so wird dir die FPU nicht weiterhelfen können.

atof() gibt normal einen double zurück. Ob das auch hier der Fall ist, 
musst du deiner Bibliothek entnehmen. Ich vermute jedoch, dass hier 
atof() auch nur mit single precision arbeitet.

Das Phänomen, was du beschreibst, kann ich daher nur auf einen 
Mislungenen typecast des compilers zurückführen. Was aber genau schief 
läuft, könnte man dem Disassembly entnehmen.

Was man machen kann?
Den Controller wechseln!
Cortex M haben generell nur eine single precision FPU. Double müssen 
also in Software berechnet werden. Sind dafür die etwa 200MHz zu wenig, 
bleibt nur die Wahl eines größeren Controllers.
Gast #4220831
Lesenswert?

Das sind die beiden Varianten des Disassemblys.

Mit "double dParam;":

   640:           dParam = atof(buffer);
0x08007088 A801      ADD           r0,sp,#0x04
0x0800708A F7FDFC8D  BL.W          __hardfp_atof (0x080049A8)
0x0800708E EEB08A40  VMOV.F32      s16,s0
0x08007092 EEF08A60  VMOV.F32      s17,s1

Mit "float dParam;"

0x08007088 A801      ADD           r0,sp,#0x04
0x0800708A F7FDFC8D  BL.W          __hardfp_atof (0x080049A8)
0x0800708E EEB0AA40  VMOV.F32      s20,s0
0x08007092 EEF0AA60  VMOV.F32      s21,s1
0x08007096 EC510B1A  VMOV          r0,r1,d10
0x0800709A F008FD1F  BL.W          __aeabi_d2f (0x0800FADC)
0x0800709E EE080A10  VMOV          s16,r0

Da ich nur an ganz wenigen Stellen mit double-Genauigkeit rechnen muss 
(z.B. beim Vorberechnen der Bahnparameter für eine Fahrt), hatte ich auf 
eine Lösung Richtung "Double = softfp & float = hardfp" gehofft.

Gibt es so was ? ( Am besten ohne die "SoftFP"-Lib selbst in ASM zu 
programmieren ;-) )
Gast #4220850
Lesenswert?

Little B. schrieb:
> Was man machen kann?
> Den Controller wechseln!
> Cortex M haben generell nur eine single precision FPU. Double müssen
> also in Software berechnet werden. Sind dafür die etwa 200MHz zu wenig,
> bleibt nur die Wahl eines größeren Controllers.

Obwohl ich nicht mit Keil arbeite, muß ich widersprechen. Weder muß der 
Controller gewechselt werden, noch ist er zu langsam. Auch gibt es 
Cortex M Prozessoren mit 'double-FPU' (Atmel war das, glaube ich).
Vom Keil-Compiler kannst Du erwarten, daß float und double in Deinem 
Programm gleichzeitig und unabhängig genutzt werden können.

Bevor Du Dich hier in die Irre führen läßt, frag bei Keil nach, welche 
Einstellungen sinnvoll sind, um beide Datentypen zu mischen. Vielleicht 
gibt es die passende Antwort auch schon unter FAQ.
Gast #4220879
Lesenswert?

@m.n.
Hab schon eine Supportanfrage am laufen. War aber bisher noch nicht 
erfolgreich. Und bei mir brennt gerade die Hütte... ich muss fertig 
werden. Deshalb frag ich gleich noch parallel :-)

@jojos
--fpmode=std hat nichts gebracht; die MicroLib hab ich eigentlich immer 
aus. Gerade bei Prozessoren wo ich kein Platzproblem habe.
Gast #4220932
Lesenswert?

Ich habe probeweise schon umgestellt von hardfp auf softfp.
Ich hab zwar die Dauer meiner Regelschleife dann nicht gemessen, aber 
ich
hab gesehen, dass ich meinen bisherigen Regeltakt um einiges sprenge.
Damit die Regelung wieder "in den Regelungstakt passt", müsste ich den 
Takt mind. 2x nehmen.
Da springt mir wahrscheinlich mein Kunde ins Gesicht :-)
Gast #4220969
Lesenswert?

Kannst Du Deine 'double'-Berechnungen vielleicht in eine separate 
.c-Datei auslagern und die Funktionen mit passenden Übergabewerten 
aufrufen?
Damit könnte man u.U. eine Kollison der Datentypen verhindern.

Eigentlich müßte doch die fixpoint-Fraktion eine einfache Lösung parat 
haben ;-)
Gast #4221027
Lesenswert?

Das Auslagern könnte ich mir ansehen. Wäre evtl. eine Lösung, da ich ja 
die Bahnsteuerung mit double/softfp und nur Regelung mit float/hardfp 
brauche.
Werd' ich mir morgen mal anschauen.

Festkomma mag ich eigentlich nicht so gern. Gerade bei einer 
Bahnsteuerung mit "Jerk" (Polynom 3.er Ordnung) kann es da schon mal 
unübersichtlich werden... sprich fehleranfällig.
Gast #4221233
Lesenswert?

m.n. schrieb:
> Ich mag Festkomma garnicht

Aber ehrlich gesagt, hab ich mir das schon überlegt. Bei kleineren 
Prozessoren (z.B. Atmega's) find ich Festkomma gar nicht so schlecht, 
wenn die Anwendung überschaubar ist. Aber ich hab noch keine Anwendung 
mit Festkomma gehabt, wo ich nicht beim Debuggen geflucht habe, weil ich 
wieder irgendwo ein Ergebnis hatte was um Welten daneben liegt.

PS. Hab zwischenzeitlich eine Aussage vom ARM Support: Ein "mixed mode" 
zwischen hardfp und softfp ist nicht vorgesehen.
#4222220
Lesenswert?

Nur weil die FPU keine double-Berechnungen ausführen kann muss man doch 
nicht gleich auf reine Softfloats umstellen.

Methoden, um die Präzision von Berechnungen durch Verwendung von 
mehreren Float-Zahlen zu erhöhen sind seit Jahrzehnten bekannt und 
wurden von der GPU-Compute-Fraktion wieder ausgegraben und teilweise 
erweitert, weil Grafikchips nicht immer (schnell) mit doubles rechnen 
können. Eine bei kurzem Überfliegen brauchbar aussehende Übersicht mit 
vielen Verweisen auf weitere Quellen gibts hier:
http://andrewthall.org/papers/df64_qf128.pdf

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren