mikrocontroller.net

Forum: Compiler & IDEs Verdacht auf GCC / Library Fehler ARM - Toolchain


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.
von Thilo H. (thaala)


Bewertung
0 lesenswert
nicht lesenswert
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:
main {
   int32_t maxY;
   double base_y;

   init_fpu();

   base_y = 168.0;
   maxY = (int32_t)base_y;
....
}

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

von Johann L. (gjlayde) Benutzerseite


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

von A. K. (prx)


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

von A. K. (prx)


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

von Thilo H. (thaala)


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

von A. K. (prx)


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

von A. K. (prx)


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

von Thilo H. (thaala)


Bewertung
0 lesenswert
nicht lesenswert
>>> Probiers mal mit -mfloat_abi=softfp statt -mhard-float. FPU Support
hab ich gemacht.
Gerechnet wir richtig, aber FPU - Support scheint weg zu sein.
    dy = 168.0;
    fx = (float)dy;
    dy = 202.0;
    double d = dy * fx;
    intx = (int)fx;
    inty = (int)dy;
    intz = (int)d;

heraus kommt:
08029bb2:   add r3, pc, #404        ; (adr r3, 0x8029d48 <main+424>)
08029bb4:   ldrd r2, r3, [r3]
08029bb8:   strd r2, r3, [sp, #64]  ; 0x40
08029bbc:   ldrd r0, r1, [sp, #64]  ; 0x40
08029bc0:   bl 0x8000a90 <__truncdfsf2>
08029bc4:   mov r3, r0
08029bc6:   str r3, [sp, #60]       ; 0x3c
08029bc8:   add r3, pc, #388        ; (adr r3, 0x8029d50 <main+432>)
08029bca:   ldrd r2, r3, [r3]
08029bce:   strd r2, r3, [sp, #64]  ; 0x40
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
08029bf0:   vldr s15, [sp, #60]     ; 0x3c
08029bf4:   vcvt.s32.f32 s15, s15
08029bf8:   vmov r3, s15
08029bfc:   str r3, [sp, #44]       ; 0x2c
08029bfe:   ldrd r0, r1, [sp, #64]  ; 0x40
08029c02:   bl 0x8000a40 <__fixdfsi>
08029c06:   mov r3, r0
08029c08:   str r3, [sp, #40]       ; 0x28
08029c0a:   ldrd r0, r1, [sp, #48]  ; 0x30
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

von Thilo H. (thaala)


Bewertung
0 lesenswert
nicht lesenswert
Korrektur:

irgendwas hab ich übersehen:
08029bf0:   vldr s15, [sp, #60]     ; 0x3c
08029bf4:   vcvt.s32.f32 s15, s15
08029bf8:   vmov r3, s15

is das nun meine Multiplikation ?

von A. K. (prx)


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

von A. K. (prx)


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

von Thilo H. (thaala)


Bewertung
0 lesenswert
nicht lesenswert
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:
    dy = 168.0;
    fx = (float)dy;
    dy = 202.0;
    float d = (float)dy * fx;
    intx = (int)fx;
    inty = (int)dy;
    intz = (int)d;

der hier entstandene Code gibt Dir Recht:
08029bb2:   add r3, pc, #396        ; (adr r3, 0x8029d40 <main+416>)
08029bb4:   ldrd r2, r3, [r3]
08029bb8:   strd r2, r3, [sp, #56]  ; 0x38
08029bbc:   ldrd r0, r1, [sp, #56]  ; 0x38
08029bc0:   bl 0x8000a90 <__truncdfsf2>
08029bc4:   mov r3, r0
08029bc6:   str r3, [sp, #52]       ; 0x34
08029bc8:   add r3, pc, #380        ; (adr r3, 0x8029d48 <main+424>)
08029bca:   ldrd r2, r3, [r3]
08029bce:   strd r2, r3, [sp, #56]  ; 0x38
08029bd2:   ldrd r0, r1, [sp, #56]  ; 0x38
08029bd6:   bl 0x8000a90 <__truncdfsf2>
08029bda:   vmov s14, r0
08029bde:   vldr s15, [sp, #52]     ; 0x34
08029be2:   vmul.f32 s15, s14, s15
08029be6:   vstr s15, [sp, #48]     ; 0x30
08029bea:   vldr s15, [sp, #52]     ; 0x34
08029bee:   vcvt.s32.f32 s15, s15
08029bf2:   vmov r3, s15
08029bf6:   str r3, [sp, #44]       ; 0x2c
08029bf8:   ldrd r0, r1, [sp, #56]  ; 0x38
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

von A. K. (prx)


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

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.