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 ?
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.
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 ;-) )
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.
@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.
Pepe schrieb:> Und bei mir brennt gerade die Hütte... ich muss fertig> werden. Deshalb frag ich gleich noch parallel :-)
Wenn Du Alles mit 'double' rechnest, ist es tatsächlich zu langsam? Vor
ein, zwei Jahren hatten hier einige Leute Testwerte geliefert, die
zeigten, daß auch 'double'-Berechnungen sehr schnell gehen.
Ich habe es gefunden:
Beitrag "Re: Controller mit FPU"
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 :-)
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 ;-)
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.
Pepe schrieb:> Festkomma mag ich eigentlich nicht so gern.
Das war eine ironische Anmerkung. Ich mag Festkomma garnicht, obwohl ich
es mal vor 20 Jahren verwendet hatte.
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.
Pepe schrieb:> PS. Hab zwischenzeitlich eine Aussage vom ARM Support: Ein "mixed mode"> zwischen hardfp und softfp ist nicht vorgesehen.
Mixed hardfp und softfp geht tatsächlich nicht (da jeweils anderes ABI),
aber man kann trotzdem Double Berechnungen mit einem Cortex M4F und
hardfp ABI machen. IMO geht das mit GCC ARM Embedded einwandfrei.
Falls es für Dich eine Option ist den MCU zu wechseln, der neue CortexM7
von Atmel implementiert floating und double precision FPU (im Gegensatz
zu STM32F7 nur float).
Stefan schrieb:> im Gegensatz zu STM32F7 nur float
Ja, das hat ST wohl verpennt... Mich wundert sowieso das man nicht alle
Controller (bei denen es Sinn macht) mit ner double-precision FPU
ausstattet.
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
Pepe schrieb:> Stefan schrieb:>> der neue CortexM7 von Atmel>> Hab ich auch schon gesehen. Der ist aber ja noch weniger lieferbar wie> der STM32F7...
Digikey verkauft die SAMS70 schon