funktioniert wie erwartet im Debug Mode. Sobald die Optimierung -O oder
-O1 eingestellt wird, so wird das Ergebnis je nach Aufrufstelle
manchmal geändert, und zwar demhingehend, dass beide Multiplikanten
vmtl. erst uint16_t gecastet werden und dann erst multipliziert. Konkret
ist das Ergebnis physical=3.05f factor=16.5f ohne Optimierung 50 und mit
der Optimierung 48 (!). Offensichtlich wurde mindestens aus "factor"
eine 16. Je nach Aufruf optimiert der Compiler das ganz simpel
entsprechend des assemblercodes zu einem 4-fach shift (klingt ja
praktisch).
Frage: Was habe ich falsch gemacht/eingestellt, wieso optimiert der
Compiler hier ungefragt und ändert das Ergebnis durchaus derart
drastisch? Sollte ich ein C-Buch kaufen oder einen anderen Compiler^^?
Danke für Tipps!
Stefan M. schrieb:> Frage: Was habe ich falsch gemacht/eingestellt, wieso optimiert der> Compiler hier ungefragt und ändert das Ergebnis durchaus derart> drastisch?
Das wird doch eher der übliche Fehler in Zeile 42 sein.
Oliver
Ok, danke für den Hinweis auf die fehlende Auflistung der Einstellungen.
Es ist so, dass das Problem, soweit ich weiß*, auch ohne jede Änderung
der "Defaults" auftritt (bis auf -O1). Das bringt vmtl hier nicht
weiter, daher lassen Sie mich es anders Formulieren:
- Möchte man so ein Problem in Zukunft umgehen, welche Einstellungen im
Compiler oder Code-Guidelines wäre denn zu beachten?
Der Hintergrund ist: Stelle ich die Funktion by luck um, schreibe etwas
volatile oder rechne halt durchgehend in Float, so ist das Problem
gelöst. Darum geht's mir für einen Einzelfall gar nicht, mich würde viel
eher interessieren, wie ich sowas in Zukunft verhindern kann - Also was
könnte hier falsch gelaufen sein? Was kann ich daraus lernen? Wie kann
ich anhand diesen Beispiels C-Code so schreibe, dass rauskommt, was ich
will? ;) Guidelines zu Casting, zu C-Funktionen und z.B. zu
Compilereinstellungen Richtung fast-Math oder Hardware-float Optionen
haben keine Auskunft über derartige Fehler gebracht.
*Wie man sieht, habe ich nur die Funktion geschrieben, jemand anderes
hat diese verwendet. Compilereinstellungen kann/werde ich ab nächster
Woche noch nachliefern. (sorry dass ichs nicht direkt griffbereit habe)
danke soweit!
Compiliere mal mit -Wextra und -Wall und schau dir die warnings an.
im C++-Modus ist meiner Erfahrung nach die Anzahl der Warnings und deren
"Qualität" besser... kann aber auch nur Zufall und Einbildung sein.
Normalerweise sagt dir dein Compiler, wenn er etwas tut, bei dem er
vermutet, dass es das Ergebnis beeinflusst.
73
Also ich tippe ja sehr selten auf "Compilerbug", weil es zu 99% kein
Compilerbug ist, sondern ein Anwenderhirnbug.
Aber in diesem Fall, wenn das tatsächlich die verwendete Funktion und
nicht eine neu fürs Forum eingetippte Version ist, dann würde ich
tatsächlich auf Compilerbug tippen.
Anscheinend wird der Cast vor der Multiplikation durchgeführt.
Also: Ist das wirklich die Funktion, oder hast du sie für das Forum neu
getippt und dabei evtl. unbeabsichtigt leicht verändert?
MaWin schrieb:> Aber in diesem Fall, wenn das tatsächlich die verwendete Funktion und> nicht eine neu fürs Forum eingetippte Version ist, dann würde ich> tatsächlich auf Compilerbug tippen.
Ganz ehrlich? Bei Fehlern bei solchen Basics muß der dann aber doch
schon arg kaputt sein.
Oliver
Stefan M. schrieb:> Sollte ich ein C-Buch kaufen oder einen anderen Compiler^^?
Im Zweifel immer ersteres. ;-)
Zeig doch mal die Codestellen, wo er 48 einsetzt.
Ein Disassembly der mutmaßlich fehlcompilierten Funktion (mit
Optimierung an) wäre jedenfalls sehr hilfreich zur Beurteilung der Lage.
objdump --disassemble file.o
Oliver S. schrieb:> Ganz ehrlich? Bei Fehlern bei solchen Basics muß der dann aber doch> schon arg kaputt sein.
Compilerbugs treten oft, wenn sie denn auftreten, auch gerne einmal in
recht einfach erscheinenden Situationen auf.
Und ja, ich bin da auch skeptisch. So gut wie immer ist es stattdessen
ein Programmierfehler.
Aber aufgrund der hier gegebenen Informationen sehe ich keine andere
Möglichkeit als einen Compilerbug oder halt, wie bereits gesagt,
fehlende Informationen oder leicht anderer Code.
Markus F. schrieb:> Dir ist bewusst, dass die M4 FPU nur single precision (float) kann?
Wie kann das Ergebnis 48 bei single precision bei dieser Eingabe
(physical=3.05f factor=16.5f) vorkommen?
Jörg W. schrieb:> Markus F. schrieb:>> Dir ist bewusst, dass die M4 FPU nur single precision (float) kann?>> Hat er ja auch benutzt.
Schon klar. Aber was passiert, wenn man die single precision FPU mit
Binaries füttert, die mit den falschen Compileroptionen erzeugt wurden?
Ich jedenfalls habe die (verwirrlich vielen) möglichen Optionen noch
nicht in sämtlichen (falschen) Kombinationen durchprobiert
Markus F. schrieb:> Jörg W. schrieb:>> Markus F. schrieb:>>> Dir ist bewusst, dass die M4 FPU nur single precision (float) kann?>>>> Hat er ja auch benutzt.>> Schon klar. Aber was passiert, wenn man die single precision FPU mit> Binaries füttert, die mit den falschen Compileroptionen erzeugt wurden?
Alles, aber bestimmt kein Shift an Stelle der float-Multiplikation.
Oliver
Hallo, sehr vielen Dank an Alle für die ersten Tipps und Nachfragen.
Leider ist das ganze Projekt mit RTOS, Tasks, Tokens und verschiedensten
Aufrufen so umfangreich, dass ich das natürlich auf das Problem
"herunterkürzen" muss :/
Aber bei der vielen Antworten hier setze ich mich ab morgen früh nochmal
hin und poste den ganzen Funktionscode und die Aufrufe, also solche in
denen es funktioniert und bei denen es hakt.
Auch die Warnings schaue ich mit den empfohlenen Options nochmal durch
und schau mal was sich mit dem disassembly in der Umgebung machen lässt.
Ja, erfahrungsgemäß liegt das Problem immer woanders, wo mans nicht
vermutet. Den C-Code irgendwo zwischen Compiler, Anwender und Ergebnis
(auf dem CAN-Bus) anzusehen halte ich für ein guten Schuss,
nachzuforschen was los ist ;)
EDIT: Hier der original Code, unverändert, 100% copy,
aber auch andere Varianten mit Klammern, Zwischenwerten, afaik auch wie
oben gezeigt ohne Summand, zeigtes das gleiche Problem (Varianten kann
ich auch schicken bei Bedarf)
Und ein Beispielaufruf, der funktioniert (daher halte ich den Summanden
nicht für interessant - er sorgt dafür, dass der Code sich ändert und
dass es geht):
mit CAL_U_OUT_FACTOR und CAL_U_OUT_OFFSET als defines -> float
konstanten -> genaue Prüfung aber nochmal morgen.
Und hier das Problem: Hier versagt der Aufruf bzw. die Rückgabe:
Bei Optimierung verschwindet der Aufruf an der Stelle und es ist
schwierig hier den Rückgabewert zu "identifizieren".
Aber nochmal konkret: Alleine das Umstellen von ohne Optimierung auf
Optimierung bringt statt 50 (Ampere) hartnäckig 48A auf einem
CAN-Interface. Und auch im Assemblercode ist zu sehen / soll zu sehen
sein (liegt mir leider gerade nicht vor, -> morgen), dass statt der
floatoperations nun ein shift drinn steht. Von der Funktion bis zum CAN
ist es ein weiter Weg, ich weiß - ich kann also nur sagen, dass es auf
die genannten stellen bisher herunterdebugged wurde und ich aktuell
davon ausgehe, dass die Funktion Usache ist. -> mehr morgen :)
Guten Abend und danke!
Stefan M. schrieb:> Bei Optimierung verschwindet der Aufruf an der Stelle und es ist> schwierig hier den Rückgabewert zu "identifizieren".
Was zu erwarten ist. Der Compiler berechnet das Ergebnis schon zur
Compilezeit, und im Compilat findet sich nur noch das Ergebnis.
Oliver
Stefan M. schrieb:> static int16_t PhysicalToDigits(float physical, float factor, float> offset)
Trenne doch als Test mal die Berechnung und die Rückgabe als int.
Was sagt dann der debuger?
Irgend W. schrieb:> Was sagt dann der debuger?
Den kannst du an der Stelle vergessen. Der Compiler optimiert ja die
Aufrufe der (statischen) Funktionen in zur Compilezeit berechnete
Konstanten um.
Stefan M. schrieb:> Bei Optimierung verschwindet der Aufruf an der Stelle und es ist> schwierig hier den Rückgabewert zu "identifizieren".
Ok.
Was passiert, wenn du das static entfernst?
Ist der Fehler dann immer noch da?
Wird dann die Funktion nicht wegoptimiert?
Wenn ja+ja, dann bitte disassembly.
MaWin schrieb:> Was passiert, wenn du das static entfernst?
Dann wird der Compiler sie nicht mehr inlinen wollen.
Ist aber nur ein Würgaround, keine echte Lösung.
Hallo zusammen,
- Wall und Wextra bringen keine Fehler in unserem Code (Nur 140 Fehler
in den Dave-Apps und XMC Libs)
"Ok.
Was passiert, wenn du das static entfernst?" - bleibt identisch
also es ist so wie folgt:
Ohne Optimierung (alles funktioniert) ist der Aufruf der Funktion zu
sehen (branch to 8004914)
Interessant wäre zumindest noch, was auf 8002988 für eine Konstante
steht. Die wird ja anfangs nach r15 geladen.
Ich denke trotzdem, dass das so einfach nicht zu analysieren ist, weil
da ziemlich viele Dinge reinspielen, die du hier nicht zitiert hast.
Insbesondere, welche der von dir benutzten Symbole alle schon zur
Compilezeit bekannt sind, spielt hier eine große Rolle, denn das sind
die Stellen, an denen der Compiler halt optimieren kann.
Ganz blicke ich bei der Doku für VCVT auch nicht durch. Die #2 scheint
die Anzahl der fraction bits zu sein, was ja letztlich einer
Schiebeoperation nahe kommt.
Jörg W. schrieb:> Interessant wäre zumindest noch, was auf 8002988 für eine> Konstante> steht. Die wird ja anfangs nach r15 geladen.>> Ich denke trotzdem, dass das so einfach nicht zu analysieren ist, weil> da ziemlich viele Dinge reinspielen, die du hier nicht zitiert hast.> Insbesondere, welche der von dir benutzten Symbole alle schon zur> Compilezeit bekannt sind, spielt hier eine große Rolle, denn das sind> die Stellen, an denen der Compiler halt optimieren kann.
Ok, stimmt, ich versuche die Infos aufzulisten:
Der genaue betreffende Aufruf ist im c code wie folgt:
also wie schon ersichtlich ist I_OUT_max erst zur Laufzeit bekannt, die
anderen schon vorher:
- dritte Parameter "0" ist 0
- zweite Parameter ist ein define:
1
#define CAL_I_OUT_FACTOR 4.16//Digits per Ampere
- der erste Parameter ist ein float und kommt von
1
FPGA_SetLimitsI_OUT(controlLimits.I_OUT_max);
und wird instantiiert durch
1
limits_tcontrolLimits;
das struct sieht wiederum so aus:
1
typedefstruct{
2
floatU_IN_max;
3
floatU_IN_min;
4
floatU_OUT_max;
5
floatU_OUT_min;
6
floatU_ZK_max;
7
floatU_ZK_min;
8
floatIPh_max;
9
floatI_OUT_max;
10
}limits_t;
etc.. die Zuweisungen ziehen sich durch noch mehrere Ebenen. Aber selbst
falls I_Out_max mal mit einem int oder sonstigem zugewisen werden
sollte, erklärt es mir noch nicht, warum ausgerechnet die harte
definition von 4.16 zu einem 2-fach shift wegignoriert wird :( ?
Wie ihr seht, ist das eine zweite Stelle, an der das fehlschlägt
(identisch zu dem oberen 16.5f Beispiel)
-> Mitstreiter haben empirisch herausgefunden, dass die Optimierung
immer fehlschlägt, wenn der Multiplikator eben nahe eines 2^n wertes
liegt. Ansonsten bleibts korrekt bei float, also andere Werte werden auf
Basis einer kleinen nicht dokumentierten Versuchsrunde nicht durch den
Shift wegoptimiert (!)
Was sollte/könnte ich noch an Details schicken?
Stefan M. schrieb:> Was sollte/könnte ich noch an Details schicken?
Am einfachsten:
Poste deinen Code-Schnippsel auf
https://godbolt.org/, diverse ARM-GCCs sind dort verfügbar.
Wenn er dort compiliert und den Fehler zeigt, stell den Link hier rein.
Dann kann jeder daran rumdrehen und verschiedene Theorien austesten...
Εrnst B. schrieb:> Am einfachsten:> Poste deinen Code-Schnippsel auf> https://godbolt.org/, diverse ARM-GCCs sind dort verfügbar.> Wenn er dort compiliert und den Fehler zeigt, stell den Link hier rein.> Dann kann jeder daran rumdrehen und verschiedene Theorien austesten...
ein compiler für den M4 ARM scheint mir dort nicht auswählbar :/
Aber immerhin habe ich den Compiler von Version 4.9 auf 10.3 mal
geupdated. Leider ist auch der 6 Jahre neuere Compiler immernoch
gleicher oder ähnlicher Meinung. Übrigens @ Jörg W: Zeile
8002988: 00000000 .word 0x00000000
was mir so dermaßen nutzlos ist/erscheint (wozu 0 laden und auch noch
float addieren?) dass ich mich wirklich Frage what the hell hier falsch
läuft. Stuxnet?
Hier übrigens noch die ganzen Flags:
-O1 -ffunction-sections -fdata-sections -Wall -Wextra -std=gnu99
-mfloat-abi=softfp -Wa,-adhlns="$@.lst" -pipe -c -fmessage-length=0
-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mthumb -g -gdwarf-2
Stefan M. schrieb:> Übrigens @ Jörg W: Zeile> 8002988: 00000000 .word 0x00000000> was mir so dermaßen nutzlos ist/erscheint (wozu 0 laden und auch noch> float addieren?)
Du addierst den ersten Parameter (r0). Ich denke, die Addition mit 0.0f
macht dann eine Float-Zahl draus. Aber so sehr sattelfest bin ich da
auch nicht, ich würde mich mit dem Debugger durch hangeln.
> -O1 -ffunction-sections -fdata-sections -Wall -Wextra -std=gnu99> -mfloat-abi=softfp
Warum eigentlich softfp, wenn du eine FPU hast?
Jörg W. schrieb:> Ich denke trotzdem, dass das so einfach nicht zu analysieren ist, weil> da ziemlich viele Dinge reinspielen, die du hier nicht zitiert hast.> Insbesondere, welche der von dir benutzten Symbole alle schon zur> Compilezeit bekannt sind, spielt hier eine große Rolle, denn das sind> die Stellen, an denen der Compiler halt optimieren kann.
Ok, ich bin dem Nachgegangen. Ändere ich
1
#define CAL_I_OUT_FACTOR 4.16//Digits per Ampere //
zu
1
#define CAL_I_OUT_FACTOR 4.16//Digits per Ampere //
2
#define CAL_I_OUT_FACTOR2 4.16//Digits per Ampere //
Das Problem liegt also "woanders", also beim nutzen des #defines ? Wenn
ich das gesamt GIT-Repo nach "CAL_I_OUT_FACTOR" finde ich nur eben genau
diese eine einzige Stelle, wo es definiert ist. Genutzt wird es an genau
3 Stellen, dem genannten Code, sowie hier: (praktisch die
Kehrfunktionen)
und
Was könnte die Ursache sein, dass nur bei genau dem Define-Wording der
Compiler der Meinung ist, bei -O1 daraus eine 4 machen zu wollen? Oder
ist es eben einfach Zufall, man ändert hier etwas und ausversehen passt
es gerade wieder ?
Jörg W. schrieb:> Warum eigentlich softfp, wenn du eine FPU hast?
weil ich die IDE gerade ganz frisch aufgesetzt habe und keinen Parameter
ändern wollte. Anscheinend greift er so aber auch von gerne alleine nach
der hwfpu, ansonsten hab ichs aber tatächlich immer auf -mfloat-abi=hard
error: Scania_150kW.elf uses VFP register arguments, c:/program files (x86)/gnu arm embedded toolchain/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/softfp\libg_nano.a(lib_a-closer.o) does not
Stefan M. schrieb:
zu
> void FPGA_SetLimitsI_OUT(float I_OUT_max){> Send_SPItoFPGA(WRITE_I_OUT_MAX, PhysicalToDigits(I_OUT_max,> CAL_I_OUT_FACTOR, 0));> }, so ist es gefixt:
heißt natürlich zu
Moin,
Stefan M. schrieb:> #define CAL_I_OUT_FACTOR 4.16//Digits per Ampere //
Da haette ich aber schon alleine wegen des dusseligen c++ Kommentar
hinter dem Macro uebelste Bauchschmerzen.
Gruss
WK
Stefan M. schrieb:> Was könnte die Ursache sein, dass nur bei genau dem Define-Wording der> Compiler der Meinung ist, bei -O1 daraus eine 4 machen zu wollen?
Dass dein #define irgendwo anders überbügelt wird.
Schau dir mal die Ausgabe des Präprozessors an. Die bekommst du, indem
du in der Compiler-Kommandozeile das -c durch ein -E ersetzt (und dann
natürlich sinnvollerweise hinter -o einen anderen Dateinamen angibst).
Am besten fügst du auch noch die Option -dM hinzu, das dumpt dir die
finalen Werte aller mittels #define generierten Makros am Ende.
Stefan M. schrieb:> Scania_150kW.elf uses VFP register arguments, c:/program files (x86)/gnu> arm embedded toolchain/10> 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/li
b/thumb/v7e-m+fp/softfp\libg_nano.a
Klar, da steht ja in der Angabe der libg_nano auch ein "softfp" drin. Du
müsstest dort natürlich schon auch die hardfp-Variante auswählen.
Aber bleib erstmal bei einer Baustelle. ;-)
Dergute W. schrieb:> Moin,>> Stefan M. schrieb:>> #define CAL_I_OUT_FACTOR 4.16//Digits per Ampere //>> Da haette ich aber schon alleine wegen des dusseligen c++ Kommentar> hinter dem Macro uebelste Bauchschmerzen.>> Gruss> WK
Danke - auch eine Lösung. Ich halte fest:
Alle 4 Stellen im Repo von CAL_I_OUT_FACTOR auf CAL_I_OUT_FACTOR2
ersetzen geht.
1
#define CAL_I_OUT_FACTOR 4.16//Digits per Ampere //
durch
1
#define CAL_I_OUT_FACTOR 4.16 //Digits per Ampere //
ersetzen geht auch
Ist das eben Zufall und bei nächster Gelegenheit habe ich das gleiche
Problem wieder? Oder ist die Antwort "keine dusseligen c++ Kommentar ins
Define weil -O1 das nicht mag?/ wenigestens ein Leerzeichen dazwischen?
Ist "//" ein geheime O1 Anweisung das Define nicht so genau zu nehmen?
Stefan M. schrieb:> - zweite Parameter ist ein define:#define CAL_I_OUT_FACTOR 4.16//Digits> per Ampere
das ist ein double. Scheint aber nicht das Problem zu sein.
Jörg W. schrieb:> Dass dein #define irgendwo anders überbügelt wird.
Kann es aber nicht finden :/. Irgendwie evtl außerhalb des Repos in
einer Bib oder sonstiges. (Google kennt den Ausdruck soweit nicht, also
wohl keine Doppelbelegung anderswo)
Auch weiterhin seltsamst der Unterschied O0 und O1. :/
Ich vermute mal unterschiedliche Rounding-Modes zwischen Compile- und
Run-Time. Insb wenn die CPU kein double kann, gibt's da krasse
Unterschiede. Gibt beim GCC ne Masse an Switches (-ffast-math,
-frounding-math, ...).
Stefan M. schrieb:> Kann es aber nicht finden :/.
Daher meine Empfehlung, sich die Ausgabe des Präprozessors anzusehen.
Das hat mir schon oft beim Debuggen seltsamer Effekte geholfen.
Dergute W. schrieb:> Da haette ich aber schon alleine wegen des dusseligen c++ Kommentar> hinter dem Macro uebelste Bauchschmerzen.
Der ist hässlich, keine Frage. :-) Allerdings werden Kommentare bereits
vom Präprozessor durch Leerzeichen ersetzt, insofern ist das hier nicht
das Problem.
Hallo,
leider funktioniert es jetzt. Per GIT kann ich sehen, dass der
identische C-Code nun funktioniert. Es funktioniert nun zuverlässig,
seitdem ich an den Kommentaren geschraubt habe und auf Rebuild Project
gegangen bin. Ich muss wohl noch etwas an der Umgebung geändert haben,
kann es aber nicht mehr zurückstellen. Eigentlich ist nur noch der große
Unterschied, dass ich den neuen Compiler verwende, der aber heute
Vormittag noch falsche Ergebnisse brachte. Evtl ein Cache-Problem von
Neu auf Alt? Habe ich wirklich seit dem nichtmehr auf full-rebuild
geklickt? Hat ein Eclipse-Restart zum Mittagessen was geändert?
Ich sichere jetzt mal den Zustand soweit es geht und setze alles wieder
neu auf um den Fehler überhaupt wieder zu bekommen. Aber evtl erst ab
morgen wieder. Nicht zu wissen was los war ist noch schlechter als der
Zustand in Post #1.
EDIT:
Ok, hab alles neu installiert.
Es ist nun so: Frischer Repo-Pull, frische DAVE Installation, NICHTS
ändern (ok, auf optimize auf O1 stellen), den Compiler entsprechend der
Anleitung* von
ARM-GCC-49 auf GCC 10-2021.10
ändern führt zur Lösung.
*https://community.infineon.com/t5/DAVE/Upgrading-GCC-in-DAVE4/td-p/310321
*->> Also wohl ein Compilerbug aus 2015.*
Sorry für die letzten Posts über die Kommentare, es war wohl ein
cache-Problem. Wäre auch zu crazy gewesen. Mal sehen ob das jetzt stabil
ist und bei den Kollegen auch hilft. Falls das nun die Lösung ist,
vielen VIELEN vielen Dank für das Mitdenken/Anregen. Ansonsten bis
bald/gleich wieder **irresmilie**
Stefan M. schrieb:> Der Aufruf wird weggelassen (ist ja soweit ok, inling) und der ganze> Spaß durch VCVT ersetzt.>> Ist das die Info die Ihr/Ich braucht/e um dem Problem auf die Spur zu> kommen?
Das sieht für mich ziemlich eindeutig nach einer Fehlcompilierung aus.
Stefan M. schrieb:> Hallo,> leider funktioniert es jetzt. Per GIT kann ich sehen, dass der> identische C-Code nun funktioniert. Es funktioniert nun zuverlässig,> seitdem ich an den Kommentaren geschraubt habe und auf Rebuild Project> gegangen bin. Ich muss wohl noch etwas an der Umgebung geändert haben,> kann es aber nicht mehr zurückstellen. Eigentlich ist nur noch der große> Unterschied, dass ich den neuen Compiler verwende, der aber heute> Vormittag noch falsche Ergebnisse brachte. Evtl ein Cache-Problem von> Neu auf Alt?
Ok, sehr interessant :)
Das heißt du nutzt nun den neuesten Compiler mit einem sauberen Rebuild
und es ist weg? Dann würde ich es dabei belassen.
Stefan M. schrieb:> 8002988: 00000000 .word 0x00000000> was mir so dermaßen nutzlos ist/erscheint (wozu 0 laden und auch noch> float addieren?) dass ich mich wirklich Frage what the hell hier falsch> läuft.
Vermutlich ein Dis-Assembly mit denen von dir angegebenen Optionen:
> Hier übrigens noch die ganzen Flags:>> -O1 -ffunction-sections -fdata-sections -Wall -Wextra -std=gnu99> -mfloat-abi=softfp -Wa,-adhlns="$@.lst" -pipe -c -fmessage-length=0> -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mthumb -g -gdwarf-2
Mit "-c" wird nur ein Object-File erzeugt, das noch RELOCs enthält, also
nicht aufgelöste Symbole. RELOCs kann man anzeigen lassen, wenn man
objdump zusätzlich mit -r aufruft.
Wenn das Listing per
> -Wa,-adhlns="$@.lst"
erstellt wird, ist es ja auch vom Assembler, also nicht gelinkt?
...andererseits sind die Konstanten wohl schon dem Compiler bekannt,
also keinen Grund für 'nen RELOC.
MaWin schrieb:> Das sieht für mich ziemlich eindeutig nach einer Fehlcompilierung aus.
Ja, sieht nun danach aus, dein Tip scheint so zu stimmen. Also ich habe
es nun auch nochmal auf einem komplett fremden System exerziert. Hier
praktisch nochmal für die Nachwelt zusammengestellt:
-> Neueste Version von DAVE (4.5.0), Frisches Repo. Output:
Die Schachtelung und die fehlende abschließende } verstehe ich auf
anhieb nicht. Aber nach Installation von
gcc-arm-none-eabi-10.3-2021.10-win32.exe
und full rebuild ändert sich das auf eine deutlich übersichtlichere
Version:
Ich habe leider noch keine Möglichkeit das zur Laufzeit zu checken, aber
sieht ja erstmal gut aus :)
Abschließend Frage ich mich aber noch zwecks Lessons learned:
- Pech? oder selbst schuld und in Zukunft:
- Immer neuesten Compiler installieren? (Immerhin wars die neusteste
DAVE Version!) oder
- Keine "tote", d.h. nicht weiterentwickelte Software (DAVE) mehr
verwenden und zu STM TI etc wechseln? oder
- Kein GCC für wirklich kritische Projekte? oder
- Testen Testen Testen, oder
?
Stefan M. schrieb:> Abschließend Frage ich mich aber noch zwecks Lessons learned:
Da du die Ursache nicht finden konntest, kann man da auch kein allgemein
gültiges Fazit ziehen. Du schiebst es jetzt auf eine bestimmte
Compilerversion, aber ich halte das für sehr gewagt.
Um wirkklich Verhaltensregeln abzuleiten, müsstest du den Bug schon
nochmal reproduzieren können und finden, was es genau war.
> Die Schachtelung und die fehlende abschließende } verstehe ich auf> anhieb nicht.
Nun, das ist ein Disassembly, bei dem nachträglich anhand der
Zeilennummern aus der Debuginformation der zugehörige Sourcecode hinein
gemappt wird. Dass das (je nach Optimierung) zuweilen mal seltsame
Artefakte produziert, ist nicht groß verwunderlich.
Etwas anderes wäre es, wenn du dir den vom Compiler generierten
Assemblercode mit eingeblendetem Sourcecode ausgeben lässt. Da gibt's
auch eine Option dafür. Wenn du aber im finalen Resultat link time
optimization angeschaltet hast, muss das wiederum nicht mehr mit dem
überein stimmen, was der Compiler initial als Assemblercode produziert
hatte.
MaWin schrieb:> Stefan M. schrieb:>> Kein GCC für wirklich kritische Projekte?>> Dann steige besser nie wieder in Autos und Flugzeuge ein.
Blöde Frage, aber wie sollte das gehen? Kenne keinen zertifizierten GCC
mit ASIL. Gibt es den?
Markus F. schrieb:> Ich glaube nicht, dass Du irgendwo einen ausgiebiger getesteten Compiler> als gcc findest.
Für Cortex M? Da lehne ich mich mal arg aus dem Fenster und behaupte,
dass der Keil, der nunmal der offizielle Compiler von ARM ist, deutlich
mehr getestet ist.
Jörg W. schrieb:> Stefan M. schrieb:> Wenn du aber im finalen Resultat link time> optimization angeschaltet hast, muss das wiederum nicht mehr mit dem> überein stimmen, was der Compiler initial als Assemblercode produziert> hatte.
Bei link time optimization wird gar kein Assemblercode "initial"
erzeugt. Da findet der Compilerlauf halt erst später statt.
Oliver
Stefan M. schrieb:> Habe ich wirklich seit dem nichtmehr auf full-rebuild> geklickt?
Das vermute ich. Da sind noch Objekte vom alten Compiler liegen
geblieben.
Ein Kollege hatte auch mal seltsame Effekte. Die Ursache war dann, daß
nach dem Compilerwechsel die Lib aber noch mit dem alten erzeugt gewesen
war.