mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik GCC, Cortex-M3 (LPC1768) und Fließkommazahlen


Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

bei meinem LPC1768 Cortex-M3 in Kombination mit meiner GCC 4.4.1 
Toolchain (Linux) habe ich heute ein komisches Verhalten entdeckt, wenn 
Fließkommazahlen in Modulen auftauchen. Es geht dabei um folgende 
Beispielfunktion:
void demo_fail(unsigned long p1, unsigned long p2) {
  log("STEP 1");
  double f = 0.0, d = 1.0;

  log("STEP 2");
  f = (double)p1/(16.0*(double)p2*d);

  log("STEP 3");
  if (f <= 1.1 || f >= 1.9) {

    log("STEP 4");
    for (f = 1.1; f <= 1.9; f += 0.1)
      d++;
  }

  log("STEP 5");
}

Ist diese Funktion innerhalb meiner main.c, funktioniert deren Aufruf 
"demo_fail(1,1)" komplett. Ist sie hingegen in ein Modul ausgelagert, 
ist "STEP 2" die letzte Ausgabe, die ich sehe (also hängt die 
double-Berechnung).

Übersetzt wird das Ganze fehlerfrei mit:
arm-none-eabi-gcc -marm -mcpu=cortex-m3 -mthumb -msoft-float 
   -ffreestanding -Wall -std=gnu99 -Wno-parentheses
   -fomit-frame-pointer -fshort-wchar -O3 -g -c -o mod.o mod.c
arm-none-eabi-gcc -marm -mcpu=cortex-m3 -mthumb -msoft-float 
   -ffreestanding -Wall -std=gnu99 -Wno-parentheses
   -fomit-frame-pointer -fshort-wchar -O3 -g -c -o main.o main.c
arm-none-eabi-ld --no-wchar-size-warning -T lpc1768.x -o main.elf
   main.o mod.o

Die folgenden beiden Varianten der Funktion (1 ohne Funktionsparameter, 
2 ohne Fließkommazahlen) funktionieren auch in einem Modul einwandfrei:
void demo_ok1() {
  log("STEP 1");
  unsigned long p1 = 1, p2 = 1;
  double f = 0.0, d = 1.0;

  log("STEP 2");
  f = (double)p1/(16.0*(double)p2*d);

  log("STEP 3");
  if (f <= 1.1 || f >= 1.9) {

    log("STEP 4");
    for (f = 1.1; f <= 1.9; f += 0.1)
      d++;
  }

  log("STEP 5");
}

void demo_ok2(unsigned long p1, unsigned long p2) {
  log("STEP 1");
  int f = 0, d = 1;

  log("STEP 2");
  f = p1/(16*p2*d);

  log("STEP 3");
  if (f <= 1 || f >= 2) {

    log("STEP 4");
    for (f = 1; f <= 2; f += 1)
      d++;
  }

  log("STEP 5");
}

Hat jemand eine Idee, woran das liegen könnte?! Danke vorab.

Autor: arm-gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine Funktion log zu benennen halte ich nicht für gut, denn in math.h 
gibt es ja: double log(double x)  natürlicher Logarithmus ln(x), x > 0
vielleicht liegt da der Fehler.!?

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da habe ich beim Vereinfachen des Codes nicht nachgedacht. Ich habe die 
Funktion nur der Einfachheit halber hier log() genannt (auch wenn ich 
nicht gegen die libmath linke). Das ist also nicht das Problem. :)

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine weiteren Ideen?

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probiere mal -lc und -lm beim Linker mit an zu geben, unmittelbar vor 
dem -o Parameter

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe weder die libc noch die libm zur Verfügung.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das glaub ich nicht.

Schaue hier:
.... \CodeSourcery\arm-none-eabi\lib

Da gibt es die Datei libc.a und libm.a

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das kannst du mir ruhig glauben, ich habe eine eigens übersetzte 
Toolchain und absichtlich keine libc und libmath... wieso glaubst du, 
dass es damit funktioniert? Das sieht mir irgendwie eher nach einem Bug 
aus.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meine vor laaanger zeit hatte ich mal ein ähnliches Problem. Kann 
mich nur noch dunkel daran erinnern. Erst mit dem Einbinden ging es 
dann.

Im Setup von Codesourcery werden die Libs mit installiert.

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das kommt mir bekannt vor, ich kann mich ebenso dunkel an einen Fall 
erinnern, bei dem das Funktionieren von der Position der libgcc in der 
Parameterliste abhing.

Leider scheint das hier nicht der Fall zu sein, ich habe es gerade mit 
der Codesourcery Toolchain gemäß deinem Vorschlag versucht, das Ergebnis 
ist aber leider dasselbe. Trotzdem danke für die Idee.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst Du das nicht mit s32 rechnen und einen Multiplikator von z.B. 
1000 verweden?

Ich habe auch mal eine recht komplexe Formel auf s32 umgestellt:
Beitrag "Re: SHT11, Abweichung bei Temperatur"

Hier wäre die Float-Formel:
Beitrag "Re: SHT11, Abweichung bei Temperatur"

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bisher habe ich das auch immer so gemacht. Bei manchen Berechnungen wäre 
es aber halt viel einfacher und schöner, Fließkommazahlen zu haben.

Autor: Markus Müller (mmvisual)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe meine Formel wegen der Geschwindigkeit umgebaut. Du könntest 
vielleicht eine Float-Zahl wandeln in eine s32, dann berechnen, dann 
wiederzurück in Float. Ich weiß ja nicht wie komplex Deine Formeln sind, 
bzw. ob Du cos/sin Funktionen brauchst.

PS: Versuche es doch mal mit dem Datentyp float un nicht mit double.

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versteh mich bitte nicht falsch, aber mir geht's da eher ums Prinzip. 
Falls es tatsächlich ein Bug ist, ist er in den aktuellen Versionen auch 
noch vorhanden. Habe mittlerweile folgende Kombinationen durch:

gcc 4.4.1 / binutils 2.19.1
gcc 4.4.1 / binutils 2.19.51.20090709 (Sourcery)
gcc 4.5.0 / binutils 2.20

Mit "float" kommt er immerhin zu "STEP 3".

Autor: Mars (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann schau dir doch mal den generierten Assembler-Code an, bzw. poste 
diesen hier.

Autor: Eduard Steinberg (rfk)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Disassembly des Funktionsaufrufs in main() und von demo_fail() (mit 
Source) siehe Anhang.

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Push.

Autor: Uwe Hermann (uwehermann) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Halte ich zwar für unwahrscheinlich dass es daran liegt, aber trotzdem: 
Prober mal statt -O3 lieber -O2 oder -O0 (zumindest testweise), evtl. 
ist das schlicht ein Compilerbug oder sowas in der Richtung.

Außerdem könnten die Optionen die du beim bauen der Toolchain verwendet 
hast eine Rolle spielen (also nicht nur die Optionen mit denen du den 
Compiler aufrufst), z.B. --with-float=soft u.ä.

Und/oder probier auch mal eine andere toolchain-Version um festzustellen 
ob es evtl. ein Compilerbug in dieser Version ist.

HTH, Uwe.

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Unterschiedliche Optimierungsstufen habe ich schon hinter mir und 
unterschiedliche Toolchains auch, siehe oben. Die Toolchains sind wie 
folgt konfiguriert:
Target: arm-none-eabi
Configured with: ../gcc-4.4.1/configure --target=arm-none-eabi --prefix=/usr/local/toolchain/arm-none-eabi-4.4.1 --enable-interwork --enable-multilib --enable-languages=c --disable-fpu --disable-nls --disable-shared --disable-libssp --without-headers
Thread model: single
gcc version 4.4.1 (GCC)

Target: arm-none-eabi
Configured with: ../gcc-4.5.0/configure --target=arm-none-eabi --prefix=/usr/local/toolchain/arm-none-eabi-4.5.0 --enable-interwork --enable-multilib --enable-languages=c --with-newlib --with-headers=../newlib-1.18.0/newlib/libc/include --with-float=soft
Thread model: single
gcc version 4.5.0 (GCC)

Target: arm-none-eabi
Configured with: /scratch/julian/2010q1-release-eabi-lite/src/gcc-4.4-2010q1/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-eabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --enable-extra-sgxxlite-multilibs --with-gnu-as --with-gnu-ld --with-specs='%{O2:%{!fno-remove-local-statics: -fremove-local-statics}} %{O*:%{O|O0|O1|O2|Os:;:%{!fno-remove-local-statics: -fremove-local-statics}}}' --enable-languages=c,c++ --disable-shared --disable-lto --with-newlib --with-pkgversion='Sourcery G++ Lite 2010q1-188' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-headers=yes --with-sysroot=/opt/codesourcery/arm-none-eabi --with-build-sysroot=/scratch/julian/2010q1-release-eabi-lite/install/arm-none-eabi --with-gmp=/scratch/julian/2010q1-release-eabi-lite/obj/host-libs-2010q1-188-arm-none-eabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/julian/2010q1-release-eabi-lite/obj/host-libs-2010q1-188-arm-none-eabi-i686-pc-linux-gnu/usr --with-ppl=/scratch/julian/2010q1-release-eabi-lite/obj/host-libs-2010q1-188-arm-none-eabi-i686-pc-linux-gnu/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-cloog=/scratch/julian/2010q1-release-eabi-lite/obj/host-libs-2010q1-188-arm-none-eabi-i686-pc-linux-gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/julian/2010q1-release-eabi-lite/install/arm-none-eabi/bin --with-build-time-tools=/scratch/julian/2010q1-release-eabi-lite/install/arm-none-eabi/bin
Thread model: single
gcc version 4.4.1 (Sourcery G++ Lite 2010q1-188)

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch dieses Thema hat sich erledigt, seit ich gegen die korrekte 
thumb2-Variante der libgcc linke!

Autor: 900ss D. (900ss)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eduard Steinberg schrieb:
> ich habe eine eigens übersetzte
> Toolchain und absichtlich keine libc und libmath...

Weshalb eigentlich selbst übersetzt?
Gibt es nichts fertiges für dich?
Evtl. hättest du dir den Ärger sparen können aber jetzt hast du
was gelernt ;-)

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab's doch auch mit der Toolchain von CodeSourcery versucht, doch 
auch da muss man nun mal gegen die thumb2-libgcc linken... ;-) Zum Thema 
selbst übersetzen: ich habe da einfach die bessere Kontrolle über 
diverse Einstellungen (z.B. SMALLMEM bei der newlib).

Autor: falstaff (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vieleicht eine division durch 0? Ja ich weiss, sollte es ned sein, 
berechne den Divident und Divisior vor und schau ob diese 0 sind...

Ansonsten wäre ein direkter vergleich der Disassemblies interessant (als 
Modul vs. in Main, mit dem gleichen Compiler...)

Autor: Eduard Steinberg (rfk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eduard Steinberg schrieb:
> Auch dieses Thema hat sich erledigt, seit ich gegen die korrekte
> thumb2-Variante der libgcc linke!

Aber Danke. ;-)

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.