Forum: Compiler & IDEs Verdacht auf GCC / Library Fehler ARM - Toolchain
Hallo Forum,
ich habe auf dem Bugzilla - Howto vom GCC gelesen, das die meisten
falsch gemeldeten Fehler zum Thema GCC im zusammenhang mit
Fließkommazahlen gemacht werden. Damit gemeint sind Beobachtungsfehler,
Rundungsfehler usw.
Ich möchte gerne vermeiden als Idiot dazustehen und hätte gerne zuerst
eure Meinung dazu.
Ich nutze das STM32F4 - Discovery Board zu Testzwecken und versuche nun
die FPU einzubinden: 1 | main {
| 2 | int32_t maxY;
| 3 | double base_y;
| 4 |
| 5 | init_fpu();
| 6 |
| 7 | base_y = 168.0;
| 8 | maxY = (int32_t)base_y;
| 9 | ....
| 10 | }
|
leider enthält die Variable maxY den Wert 0 statt 168.
Disassembly der Zeile "maxY = (int32_t)base_y;":
08028f5c: vldr d0, [sp, #40] ; 0x28
08028f60: bl 0x8000a40 <__fixdfsi>
Ohne Nutzung der FPU:
08029de2: ldrd r0, r1, [sp, #40] ; 0x28
08029de6: bl 0x8000a40 <__fixdfsi>
Getestet habe ich es bisher mit den drei mir bekannten Toolchains:
Codesourcery, Yagarto und Germia.
Ich habe es mit dem Betriebssystem Chibios versucht, als auch mit der
BlinkLED - Demo - App von MMVisual.
Hier das Topic bei Chibios-Support:
http://forum.chibios.org/phpbb/viewtopic.php?f=2&t=337
Immer mit dem gleichen negativen Ergebnis.
FPU - CompilerOtionen:
-ggdb -fomit-frame-pointer -falign-functions=16 -mhard-float
-mfpu=fpv4-sp-d16 -fsingle-precision-constant
MCU = cortex-m4
Was sagt Ihr ?
Könnt Ihr den Fehler nachvollziehen ?
Gibt es sonstige Hints - z.B. doubles darfst du nicht verwenden o.Ä. ?
gruß Thilo
Der Code, d.g. die jeweils 2 Zeilen Disassembly sehen doch gut aus. Der
Fehler ist also entweder hier:
> ....
oder in der Verwendung/Configury der Tools.
Und wiese "negatives Ergebnis": Wieso ist 0 negativ?
Johann L. schrieb:
> Der Code, d.g. die jeweils 2 Zeilen Disassembly sehen doch gut aus.
Vorausgesetzt er erwischt die richtige Lib, und damit eine
Implementierung der Funktion __fixdfsi, die den Parameter in D0/D1 statt
R0/R1 erwartet.
Im anderen Thread schreibt er allerdings
"this lib function is linked from Codesourcery (both variant use same
library)
__fixdfsi
d:/winarm/sourcery_codebench_lite_for_arm_eabi/bin/../lib/gcc/arm-none-e
abi/4.6.1/thumb2\libgcc.a(_arm_fixdfsi.o)"
und das kann natürlich nicht funktionieren.
Johann L. schrieb:
> Und wiese "negatives Ergebnis": Wieso ist 0 negativ?
Manchmal ist sogar negativ = positiv. Wenn das eine der Laborbefund beim
Arzt ist und das andere die Stimmung des Patienten nachher. ;-)
Hallo Helfer,
>>> Und wiese "negatives Ergebnis": Wieso ist 0 negativ?
ich meine wenn man den Wert 168 erwartet und 0 kommt raus - ist das
negativ.
library) __fixdfsi
d:/winarm/sourcery_codebench_lite_for_arm_eabi/bin/../lib/gcc/arm-none-e
abi/4.6.1/thumb2\libgcc.a(_arm_fixdfsi.o)"
>>> und das kann natürlich nicht funktionieren.
warum sagst Du das ?
meinst du den Thumb2 - Befehlssatz ?
Wer ist verantwortlich für die Auswahl der "richtigen" libs ?
Ich war der Ansicht, dass der Linker gesteuert wird über die
Command-line switches..... Insbesondere der -mhard-float
-mfpu=fpv4-sp-d16 müsste doch die Verwendung der FPU - Libs
"einschalten".
Liege ich da falsch ?
>>> Vorausgesetzt er erwischt die richtige Lib, und damit eine
>>> Implementierung der Funktion __fixdfsi, die den Parameter in D0/D1
>>> statt R0/R1 erwartet.
D0 ist die 64 Bit Bezeichnung der zuammengefassten 32-Bit FPU Register
S0 und S1. Davon gibt es dann 16 Stück.... D0 ist also ein Äquivalent zu
R0/R1
Klar muss __fixdfsi zur Verwendung von "vldr d0, [sp, #40]" passen,
evtl. könnt Ihr mir ja mal ein paar command line switches nennen, die
mehr Auskunft über die verwendeten Libs geben ?
Danke im voraus.
Gruß Thilo
Thilo Haala schrieb:
> Liege ich da falsch ?
Vermutlich schon, das steuert m.W. nur die Codegenerierung des
Compilers, nicht aber die Auswahl der Library.
> D0 ist die 64 Bit Bezeichnung der zuammengefassten 32-Bit FPU Register
> S0 und S1.
Ok.
> Davon gibt es dann 16 Stück.... D0 ist also ein Äquivalent zu
> R0/R1
Nur ist R0 nicht identisch mit S0, d.h. mit VLDR landet der Parameter in
FPU-Register(n) und mit LDRD in Integer-Registern.
Probiers mal mit -mfloat_abi=softfp statt -mhard-float. FPU Support
gibts damit trotzdem, aber die Aufrufkonvention entspricht dann Soft-FP
und __fixdfsi wird korrekt aufgerufen.
>>> Probiers mal mit -mfloat_abi=softfp statt -mhard-float. FPU Support
hab ich gemacht.
Gerechnet wir richtig, aber FPU - Support scheint weg zu sein. 1 | dy = 168.0;
| 2 | fx = (float)dy;
| 3 | dy = 202.0;
| 4 | double d = dy * fx;
| 5 | intx = (int)fx;
| 6 | inty = (int)dy;
| 7 | intz = (int)d;
|
heraus kommt: 1 | 08029bb2: add r3, pc, #404 ; (adr r3, 0x8029d48 <main+424>)
| 2 | 08029bb4: ldrd r2, r3, [r3]
| 3 | 08029bb8: strd r2, r3, [sp, #64] ; 0x40
| 4 | 08029bbc: ldrd r0, r1, [sp, #64] ; 0x40
| 5 | 08029bc0: bl 0x8000a90 <__truncdfsf2>
| 6 | 08029bc4: mov r3, r0
| 7 | 08029bc6: str r3, [sp, #60] ; 0x3c
| 8 | 08029bc8: add r3, pc, #388 ; (adr r3, 0x8029d50 <main+432>)
| 9 | 08029bca: ldrd r2, r3, [r3]
| 10 | 08029bce: strd r2, r3, [sp, #64] ; 0x40
| 11 | 08029bd2: ldr r0, [sp, #60] ; 0x3c
| 12 | 08029bd4: bl 0x8000458 <__extendsfdf2>
| 13 | 08029bd8: mov r2, r0
| 14 | 08029bda: mov r3, r1
| 15 | 08029bdc: mov r0, r2
| 16 | 08029bde: mov r1, r3
| 17 | 08029be0: ldrd r2, r3, [sp, #64] ; 0x40
| 18 | 08029be4: bl 0x8000500 <__muldf3>
| 19 | 08029be8: mov r2, r0
| 20 | 08029bea: mov r3, r1
| 21 | 08029bec: strd r2, r3, [sp, #48] ; 0x30
| 22 | 08029bf0: vldr s15, [sp, #60] ; 0x3c
| 23 | 08029bf4: vcvt.s32.f32 s15, s15
| 24 | 08029bf8: vmov r3, s15
| 25 | 08029bfc: str r3, [sp, #44] ; 0x2c
| 26 | 08029bfe: ldrd r0, r1, [sp, #64] ; 0x40
| 27 | 08029c02: bl 0x8000a40 <__fixdfsi>
| 28 | 08029c06: mov r3, r0
| 29 | 08029c08: str r3, [sp, #40] ; 0x28
| 30 | 08029c0a: ldrd r0, r1, [sp, #48] ; 0x30
| 31 | 08029c0e: bl 0x8000a40 <__fixdfsi>
|
da ist noch nicht einmal ein fpu - register mehr im Spiel...
Heiße Frage - wie kann ich die Verwendung der Libs steuern ?
Gruß,
Thilo
Korrektur:
irgendwas hab ich übersehen: 1 | 08029bf0: vldr s15, [sp, #60] ; 0x3c
| 2 | 08029bf4: vcvt.s32.f32 s15, s15
| 3 | 08029bf8: vmov r3, s15
|
is das nun meine Multiplikation ?
Thilo Haala schrieb:
> 08029bf0: vldr s15, [sp, #60] ; 0x3c
> 08029bf4: vcvt.s32.f32 s15, s15
> 08029bf8: vmov r3, s15
> da ist noch nicht einmal ein fpu - register mehr im Spiel...
Ach nee...
Was hast du denn erwartet? Dass die single precision FPU deines CM4 auf
einmal Flügel kriegt und zu einer double precision FPU wird? In deinem
Code ist m.E. exakt eine reine single precision Operation drin und die
wurde auch in FPU-Befehle umgesetzt.
> Heiße Frage - wie kann ich die Verwendung der Libs steuern ?
Sinnlos, gibt im CS keine Lib für 64-Bit Softfloat und 32-Bit Hardfloat.
Ich hatte da noch irgendwelche früheren ARM Compiler-Packages mit einem
Dutzend Libs für alle Varianten von Byteorder und FP-Support in
Erinnerung.
Thilo Haala schrieb:
> is das nun meine Multiplikation ?
Nö. Das ist
intx = (int)fx;
Deine Multiplikation ist das da, erst wird fx zu double konvertiert,
dann mit Laufzeitfunktion in double precision multipliziert:
08029bd2: ldr r0, [sp, #60] ; 0x3c
08029bd4: bl 0x8000458 <__extendsfdf2>
08029bd8: mov r2, r0
08029bda: mov r3, r1
08029bdc: mov r0, r2
08029bde: mov r1, r3
08029be0: ldrd r2, r3, [sp, #64] ; 0x40
08029be4: bl 0x8000500 <__muldf3>
08029be8: mov r2, r0
08029bea: mov r3, r1
08029bec: strd r2, r3, [sp, #48] ; 0x30
Wenn du die FPU nutzen willst, dann nimm "float". Durchgängig. Bei
"double" besteht effektiv kein Unterschied zwischen deinem CM4 und einem
CM3 ohne FPU, du kriegst die gleichen Softfloat Operationen.
Hallo prx,
is ja gut... hau doch nicht gleich so auf mich ein...8-)
Ich hatte ja Eingangs gefragt ob man in diesem Kontext überhaupt
"double" verwenden darf.
als kleine Abwandlung: 1 | dy = 168.0;
| 2 | fx = (float)dy;
| 3 | dy = 202.0;
| 4 | float d = (float)dy * fx;
| 5 | intx = (int)fx;
| 6 | inty = (int)dy;
| 7 | intz = (int)d;
|
der hier entstandene Code gibt Dir Recht:
1 | 08029bb2: add r3, pc, #396 ; (adr r3, 0x8029d40 <main+416>)
| 2 | 08029bb4: ldrd r2, r3, [r3]
| 3 | 08029bb8: strd r2, r3, [sp, #56] ; 0x38
| 4 | 08029bbc: ldrd r0, r1, [sp, #56] ; 0x38
| 5 | 08029bc0: bl 0x8000a90 <__truncdfsf2>
| 6 | 08029bc4: mov r3, r0
| 7 | 08029bc6: str r3, [sp, #52] ; 0x34
| 8 | 08029bc8: add r3, pc, #380 ; (adr r3, 0x8029d48 <main+424>)
| 9 | 08029bca: ldrd r2, r3, [r3]
| 10 | 08029bce: strd r2, r3, [sp, #56] ; 0x38
| 11 | 08029bd2: ldrd r0, r1, [sp, #56] ; 0x38
| 12 | 08029bd6: bl 0x8000a90 <__truncdfsf2>
| 13 | 08029bda: vmov s14, r0
| 14 | 08029bde: vldr s15, [sp, #52] ; 0x34
| 15 | 08029be2: vmul.f32 s15, s14, s15
| 16 | 08029be6: vstr s15, [sp, #48] ; 0x30
| 17 | 08029bea: vldr s15, [sp, #52] ; 0x34
| 18 | 08029bee: vcvt.s32.f32 s15, s15
| 19 | 08029bf2: vmov r3, s15
| 20 | 08029bf6: str r3, [sp, #44] ; 0x2c
| 21 | 08029bf8: ldrd r0, r1, [sp, #56] ; 0x38
| 22 | 08029bfc: bl 0x8000a40 <__fixdfsi>
|
Danke für deine Mühe.
Offensichtlich ist der Switch -mfloat_abi=softfp die Lösung des
Problems.
Unabhängig davon ob die FPU genutzt wird oder nicht sollte das richtige
Ergebins ja schon rauskommen...
Gruß Thilo
Thilo Haala schrieb:
> is ja gut... hau doch nicht gleich so auf mich ein...8-)
Sorry, passiert manchmal.
> Ich hatte ja Eingangs gefragt ob man in diesem Kontext überhaupt
> "double" verwenden darf.
Dürfen schon. Hat aber Konsequenzen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|