Hallo Cortex Cracks, ich betreibe einen STM32F405 unter C und GCC. Wenn ich int64_t benutze friert er irgendwo ein. Ich nehme an, dass ich nicht die richtigen libraries zulinke. Ich habe mal das Makefile angehängt. Jemand einen Rat? Danke Cheers Detlef
Detlef _. schrieb: > Wenn ich int64_t benutze friert er irgendwo ein. Und was sagt Dein Debugger dazu?
Hab keinen Debugger. Ich debugge mit printf und das geht ja dann nich :-/
Stimmt das Alignment? Wenn du einfach irgendwelche char Pointer zu int64_t Pointern castest werden manchmal Instructions generiert die korrektes Alignment voraussetzen.
Nee, mach ich nicht, ich setz die ganz normal auf int64_t bla; und will sie dann benutzen. Cheers Detlef
Detlef _. schrieb: > Ich debugge mit printf und das geht ja dann nich Machst du das etwa so:
1 | ...
|
2 | int64_t myInt64; |
3 | ...
|
4 | printf("My int64 value is: %d", myInt64); |
5 | ...
|
Bekommst du beim Kompilieren irgendwelche Warnings?
Initialer Stack Pointer im Linker Script falsch. Der muss auf das erste Byte nach dem RAM zeigen, nicht das letzte Byte im RAM. Leider weiß ST nicht wie die eigenen Chips funktionieren und macht das in den Beispiel Skripten teilweise falsch.
Detlef _. schrieb: > und will sie dann benutzen. Und machst was genau? Zeig mal den relevanten Codeteil in dem du den int64_t benutzt.
Detlef _. schrieb: > Hab keinen Debugger. Ich debugge mit printf und das geht ja dann nich > :-/ Du debuggst nicht, Du testest. Ist denn Dein Controller nicht zufälligerweise auf einer dieser "Discovery"-Platinen drauf? Die enthalten mit "ST-Link" die Hardware, die nötig ist, um via JTAG oder etwas artverwandtem Debuggen zu können.
Detlef _. schrieb: > Ich nehme an, dass ich nicht die richtigen libraries zulinke. Also auf meinem F405 geht das mit 64bit-Integern und GCC problemlos, und ich linke überhaupt keine Libraries zu. Folglich ist es irgendwas in Deinem Code oder Linkerscript, aber da Du die nicht hochgeladen hast, kann man da nichts weiter zu sagen.
Moegliche Ursachen: - printf kann keine 64 bit - Stack ist nicht 8 byte aligned
Hallo, danke erstmal an alle. Ich hab son Olimex board und flashe das Ding über den eingebauten bootloader und debugge (teste :/) über eine serielle Schnittstelle. Hab kein JTAG. @Uwe: Das ist ne Idee. Laut angehängtem, benutzten default-Linkerscript liegt der Stack bei _estack-__Stack_Size = 0x20020000-1024 , das ist 8 Byte aligned, oder? @NOP: "ich linke überhaupt keine Libraries zu.". Der STM32F405 kann keine 64Bit ints' nativ rechnen, der braucht dafür ne Software lib, die muss irgendwo her kommen. Mache kein printf auf die 64 Bit Variablen. Er friert bei sowas ein: int64_t bla; bla = (3355*bla)>>24; Denke immer noch, dass irgendwas mit der lib-Version zum tun hat oder diese 'thumb' Geschichte, ist mir auch nich so richtig klar, was man mischen darf und was nicht. Danke für Eure Aufmerksamkeit. Cheers Detlef
Detlef _. schrieb: > Der STM32F405 kann keine 64Bit ints' nativ rechnen, der braucht dafür ne > Software lib, die muss irgendwo her kommen. Das ist dann die Runtimelibrary Deines C-Compilers.
Rufus Τ. F. schrieb: > Detlef _. schrieb: >> Der STM32F405 kann keine 64Bit ints' nativ rechnen, der braucht dafür ne >> Software lib, die muss irgendwo her kommen. > > Das ist dann die Runtimelibrary Deines C-Compilers. Ja. Erwische ich da die richtige?
Detlef _. schrieb: > bla = (3355*bla)>>24; und damit kannste Dir einen signed int overflow einhandeln, was undefined behaviour ist. Wenn bla hinreichend groß ist, dann ist (3355*bla) ein Overflow. Abhilfe: entweder, Du begrenzt mit einem Check vorher den Wertebereich von bla, oder wenn der Overflow erwünscht ist, geh auf uint64_t, denn bei unsigned ist der Overflow definiert. Ansonsten, wie ich schon sagte, ich linke keine Library zu (auch nicht die Standardbibliothek), der GCC setzt die 64bit-Befehle trotzdem automatisch richtig um. Natürlich nicht in 64bit-Instruktionen, die es auf ARM32 ja nicht gibt, sondern zerlegt in 32bit-Instruktionen.
Es könnte natürlich auch sein, daß die int64_t-Unterstützung mit Inline-Code oder "intrinsincs" implementiert ist, d.h. der Code kommt nicht aus einer Library, die zum Programm dazugelinkt wird, sondern wird bereits vom Compiler selbst eingesetzt. Würdest Du einen Debugger verwenden, könntest Du darüber mehr Informationen selbst gewinnen.
Rufus Τ. F. schrieb: > Es könnte natürlich auch sein, daß die int64_t-Unterstützung... Der TO sollte doch erstmal nachschauen, was sich hinter diesem int64_t tatsächlich verbirgt. Wenn ich mich recht entsinne, dann konnte bereits der ARM7TDMI in der Lernbetty problemlos mit int64 umgehen - und zwar sowohl per Keil als auch per Gcc. W.S.
Mein Nucleo F411RE läuft auch mit u/int64_t ohne irgend eine lib mit gcc. Auch ohne mathlib.
Detlef _. schrieb: > Hab keinen Debugger. Ich debugge mit printf und das geht ja dann nich Dann gib doch mal nur die Addresse von der int64_t Variablen mit printf() aus. Wenn die nicht durch 4 teilbar ist, hast Du eine Ursache gefunden. Hint: Hardfault Handler implementieren und ein Blink Code ausgeben lassen. Dann sieht man Software Probleme schneller. Längerfristig will man sich aber einen Debugger zulegen. Die gibt es für ARM auch sehr preiswert.
Jim M. schrieb: > Dann gib doch mal nur die Addresse von der int64_t Variablen mit > printf() aus. Wenn die nicht durch 4 teilbar ist, hast Du eine Ursache > gefunden. durch 8 teilbar, oder !? > Längerfristig will man sich aber einen Debugger zulegen. Die gibt es für > ARM auch sehr preiswert. hm, hm. für solch einen komischen Fehler ist Kenntnis eines Debuggers gut. Aber ansonsten debugge ich den Code lieber vorher auf einer komfortableren Plattform als auf nem uC und teste den vorher so, dass er auf Anhieb läuft. Das klappt auch oft, jetzt aber nicht. Ausserdem habt ich meist fette Echtzeit, da hab ich schlechte Erfahrungen gemacht wenn mir der Debugger da reinfummelt. Liegt aber wahrscheinlich wie oft an meiner Unkenntnis. Danke Cheers Detlef
Jim M. schrieb: > Längerfristig will man sich aber einen Debugger zulegen. Die gibt es für > ARM auch sehr preiswert. Und? Was hat man davon? Es glauben gar viele Leute, daß ein Debugger das Allheilmittel sei. Ist er nicht. Die Fehler, die man mit ihm finden kann, sind zu 99% eigene Doofheit oder Unachtsamkeit. Die eigentlichen Sauereien, die einem gelegentlich das Leben schwer machen, findet man damit nimmer. Versuche doch mal, nen USB-Handler per Debugger zu debuggen... nur so, als Beispiel. W.S.
Ach ja, gewiss, gewiss. Wer einen Debugger verwendet, ist zu 99% unachtsam und doof. Natürlich. Was sonst. Geht's noch?
Ich nochma, TO. Habe Stück für Stück die Benutzung der int64_t reingenommen. Geht auch alles gut, bis ich eine int64_t Variable mit einer float Variable vergleiche: int64_t out; float maxx; if(out > maxx) maxx = (float)out; Für das Ding linkt er 700Byte mehr ein und 'friert ein' bei der Ausführung. Eigentlich sollte ich jetzt dem Fehler auf den Grund gehen, aber Zeit und Lust fehlen. Rest geht erstma bei mir und gut, die Abfrage hab ich mit int32_t gelöst, an der Stelle passte das noch. Die gewonnene Zeit nutze ich lieber, um meinen Olimex USB JTAG Adapter zum Fliegen zu bringen ;-/ Danke allen Beteiligten. Cheers Detlef
W.S. schrieb: > Versuche doch mal, nen USB-Handler per Debugger zu debuggen... nur so, > als Beispiel. Ich habe letzte Woche den USB Code von NXP für LPC debuggt und nur dank Debugger festgestellt dass an einer Stelle ein unaligned memory Zugriff war der den Cortex M0 abstürzen lässt. Ich bin gespannt wie man das in den Tausenden LoC ohne Debugger (schnell) hätte finden können.
dieses? https://www.olimex.com/Products/ARM/ST/STM32-405STK/ besorg dir ein Nucleo board ... der ST Link V2-1 da drauf kann alle ST flashen. Ich breche die gern ab und verwende die weiter ^^ Aber dann kannst du zB mit OpenSTM IDE auch ganz fix debuggen und spielen.
Rufus Τ. F. schrieb: > Ach ja, gewiss, gewiss. Wer einen Debugger verwendet, ist zu 99% > unachtsam und doof. Natürlich. Was sonst. > > Geht's noch? Ich habe den Eindruck, daß du dich getroffen fühlst. OK, ist ne Bestätigung für mich. Aber denk mal nach, wofür DU normalerweise einen Debugger auf nem Mikrocontroller verwendest. Zum Flashen? Oder wirklich zum Debuggen - und wenn, was hast du denn debuggt mit welchem Ergebnis? Also komm mal runter von deiner Palme und bleibe vernünftig. Das, was man per Debugger herausbekommen kann, ist wirklich zu 99% nur Unachtsamkeiten und sich zu doof angestellt haben. Letzteres besteht regelmäßig darin, daß man haben will, was man meint und nicht, was der Compiler davon hält. Nettes Beispiel sind konstante arrays von konstanten Zeigern auf konstante arrays im Flash. Irgendwo ein const fehlplaziert oder vergessen und ätsch. Aber warum der Systemtakt nicht so kommt, wie man es beim Aufsetzen der PLL sich gedacht hat oder warum anschließend die CPU sang- und klanglos verreckt ist (und auch kein Debugger-Frontend mehr läuft) oder warum man beim USB vom Host gnadenlos kaltgestellt wird, das findet man per Debugger eher NICHT. Ich bin nach wie vor davon überzeugt, daß der Debugger entweder nur zum Flaschen benutzt wird oder sein Nutzen deutlich überschätzt wird. Und, sag mal wie du das nennen würdest, wenn jemand seinen Fehler, den er beim Schreiben seiner Quelle gemacht hat, nicht durch kritisches Draufgucken aud seine Quelle finden kann und stattdessen meint, daß der Debugger es an seiner Stelle schon finden wird. Hier hat jemand geschrieben, "Ich habe letzte Woche den USB Code von NXP für LPC debuggt und nur dank Debugger festgestellt dass.." - ich glaube dem Jungen kein einziges Wort. Kein Einziges! W.S.
W.S. schrieb: > Und, sag mal wie du das nennen würdest, wenn jemand seinen Fehler, den > er beim Schreiben seiner Quelle gemacht hat, nicht durch kritisches > Draufgucken aud seine Quelle finden kann und stattdessen meint, daß der > Debugger es an seiner Stelle schon finden wird. Das klingt ziemlich überheblich und vor allem ... erfahrungsarm.
W.S. schrieb: > Aber denk mal nach, wofür DU normalerweise einen Debugger auf nem > Mikrocontroller verwendest. Es gibt Leute, die schreiben komplexere Dinge als LED-Blinker. Dafür ist ein Debugger enorm hilfreich. Bei großen Projekten mit komplexen Programmstrukturen helfen Watchpoints und Step-by-Step eine Menge. Nur weil du damit nicht umgehen kannst heißt das nicht dass man das nicht braucht. Nicht umsonst sind Debugger seit Jahrzehnten(!) integraler Bestandteil aller Entwicklungs-Toolchains (außer Arduino)... W.S. schrieb: > Also komm mal runter von deiner Palme und bleibe vernünftig. Das, was > man per Debugger herausbekommen kann, ist wirklich zu 99% nur > Unachtsamkeiten und sich zu doof angestellt haben. Selbst wenn es so wäre - ist doch gut, das damit schnell & einfach zu finden. Manche Leute wollen einfach ihre Arbeit machen anstelle sich durch Männlichkeit ( http://xkcd.com/378/ ) zu profilieren. W.S. schrieb: > Irgendwo ein const > fehlplaziert oder vergessen und ätsch. Das findet ja der Compiler, da sollte man sich mal die Compiler-Warnungen anschauen. W.S. schrieb: > das findet man per > Debugger eher NICHT. Debugger sind auch sehr hilfreich um Peripherie-Register anzuschauen und herauszufinden, warum die Peripherie nicht tut was man möchte. Dokumentationsfehler sind ja nun keine Seltenheit. W.S. schrieb: > Und, sag mal wie du das nennen würdest, wenn jemand seinen Fehler, den > er beim Schreiben seiner Quelle gemacht hat, nicht durch kritisches > Draufgucken aud seine Quelle finden kann Es gibt so etwas das nennt sich "Betriebsblind". Bei Millionen Zeilen Code wird es irgendwann schwierig den Fehler durch Hinschauen zu finden, wenn das Problem durch komplizierte Wechselwirkung der einzelnen Komponenten zustande kommt. W.S. schrieb: > Hier hat jemand geschrieben, "Ich habe letzte Woche den USB Code von NXP > für LPC debuggt und nur dank Debugger festgestellt dass.." - ich glaube > dem Jungen kein einziges Wort. Kein Einziges! Hahaha, du bist echt der Beste! Wenn dir was nicht passt steckst du den Kopf in den Sand? Aber bitte: https://github.com/una1veritas/ARMWork/blob/master/LPCLibrary/LPC11Uxx_USBDriver/usbhw.c#L803 Dies ist der Code von NXP. Die offizielle Quelle des Codes kannst du selber ausfindig machen, in diesem GitHub-Repo ist es am einfachsten öffentlich einsehbar. Der Trick mit *((__packed uint32_t *)dataptr) funktioniert vielleicht mit dem ARMCC, aber nicht mit dem GCC (der ignoriert das einfach). Sobald dataptr also unaligned ist gibt es beim Cortex-M0 einen Crash. Wenn du mir das nicht glaubst, probier's aus. Und dann bin ich gespannt, wie man einen solchen Crash ohne Debugger finden soll. Mit Debugger ging's recht schnell (Backtrace, Assemblercode, Register anschauen).
Mir fällt gerade ein dass ich auch mal per Debugger einen Buffer Overflow in ST's USB Code gefunden habe. Ich hatte das Phänomen dass virtuelle Funktionsaufrufe plötzlich nicht mehr funktionierten. Da habe ich einen Watchpoint auf den vtable Pointer gesetzt und sofort die fragliche Stelle im ST Code gefunden. Das ist aber jetzt so lange her dass ich die genaue Stelle nicht mehr weiß (aber hier im Forum wird ja oft von den vielen Bugs im ST USB Code geredet). Wie man das in sinnvoller Zeit ohne Debugger finden soll wüsste ich jetzt auch nicht.
Rufus Τ. F. schrieb: > vor allem ... erfahrungsarm. Wer nur vom Tisch springt, findet einen Fallschirm unnütze Ballast.
Ich habe vor einiger Zeit auch mal eine eigene Lib geschrieben um den ADC per DMA auszulesen. Ich habe ca. 4 Monate rumgetestet und es lief nicht. Ich bin zwar noch Rookie, aber dann habe ich mich mit dem Hardwaredebugger eingelesen. 2 Tage gebraucht bis ich das alles verstanden hatte und der Debugger lief. 2 Stunden später lief der DMA-ADC ohne Probleme.
Dr. Sommer schrieb: > Initialer Stack Pointer im Linker Script falsch. Der muss auf das erste > Byte nach dem RAM zeigen, nicht das letzte Byte im RAM. Leider weiß > ST nicht wie die eigenen Chips funktionieren und macht das in den > Beispiel Skripten teilweise falsch. Gilt das nur für den F4 oder die gesamte STM32 Familie? Gilt dies generell für alle Cortex-M auch anderer Hersteller?
Steffen R. schrieb: > Gilt das nur für den F4 oder die gesamte STM32 Familie? > Gilt dies generell für alle Cortex-M auch anderer Hersteller? Gilt für alle Cortex, weil das ein "fully descendent stack" ist. Der SP wird also VOR dem Push dekrementiert.
> Der muss auf das erste Byte nach dem RAM zeigen, nicht das letzte Byte > im RAM. Das in Kombination mit > Der SP wird also VOR dem Push dekrementiert. bedeutet also nur, daß ein Byte (oder vermutlich 4 Byte, da der Stack sicherlich auch besser mit Alignment angesprochen wird) "vergeudet" wird, der effektive Stack also um dieses eine Element kleiner ist als vermutet. Welche Programmfehler sollten dadurch entstehen? Ein Programmdesign, das den Stack bis aufs letzte Byte ausquetscht halte ich für eher fragwürdig.
Rufus Τ. F. schrieb: > Welche Programmfehler sollten dadurch entstehen? Auf ungerade Adressen kann man nur ineffizient zugreifen. Zudem scheitern Zugriffe mit Datentypen die größer als 4 Byte sind (double, (u)int64_t) bei solchen Adressen, da die ldrd/strd Instruktionen nur 4-Byte-Aligned Adressen unterstützten. Allerdings lese ich gerade dass der SP immer Zwangs-Aligned ist: Beitrag "Re: [ARM] Nützliches newlib-nano float printf" Daran liegt es also wohl doch nicht...
W.S. schrieb: > wenn jemand seinen Fehler, den > er beim Schreiben seiner Quelle gemacht hat, nicht durch kritisches > Draufgucken aud seine Quelle finden kann Das kann man grundsätzlich immer. Die Frage ist nur, wieviel Zeit das braucht. Denn man hätte es ja auch einfach gleich richtig schreiben können, so daß Debugging generell überflüssig ist. Theoretisch. Dummerweise wird man aber oftmals beim Drübergucken genau denselben Denkfehler machen wie auch schon beim Codieren. Noch schöner wird es, wenn man anders als offensichtlich W.S. nicht den Luxus hat, stets nur from scratch selbstgeschriebene Programme vor sich zu haben, sondern man es mit zigtausend Zeilen fremden Codes zu tun hat und der ursprüngliche Programmierer nicht mehr erreichbar ist. Das können dann durchaus auch unterhaltsame indirekte Fehler sein - etwa ein obendrein auch noch sehr seltener und schwer reproduzierbarer Absturz nicht an der Stelle, wo der Fehler liegt, sondern an völlig anderer Stelle, wo der ursächliche Fehler sich erst auswirkt. Sowas wie sehr seltenes, irrtümliches Überschreiben eines Pointers, der viel später und ganz woanders erst dereferenziert wird. Klar kann man dann erstmal wochenlang nur Quelltext lesen und überlegen, ob in einer der hunderten Funktionen womöglich ein Fehler stecken könnte. Blöd nur, wenn ein Fehler schlichtweg da ist und man nicht wochenlang auf einen Fix warten kann. Mitm Debugger habe ich in der genannten Lage von "da ist möglicherweise ein Problem" bis zu "Problem behoben" zwei Tage gebraucht. Ich will nicht wissen, wie lange ich ohne Debugger gebraucht hätte.
Rufus Τ. F. schrieb: > bedeutet also nur, daß ein Byte (oder vermutlich 4 Byte, da der Stack > sicherlich auch besser mit Alignment angesprochen wird) Mit dem Auto-Alignment werden es 4 Bytes sein, die vergeudet werden. Schlimmer ist aber, daß er zu Beginn dann eher nicht mehr 8-Byte-aligned ist, was er für Datentypen wie double aber zu sein hat. Es sei denn, man hat seinen Stack echt schräg dimensioniert, nämlich um genau diese 4 Bytes oberhalb des nächstniederen 8-alignments.
Nop schrieb: > Noch schöner wird es, wenn man anders als offensichtlich W.S. nicht den > Luxus hat, stets nur from scratch selbstgeschriebene Programme vor sich > zu haben, sondern man es mit zigtausend Zeilen fremden Codes zu tun hat > und der ursprüngliche Programmierer nicht mehr erreichbar ist. Eins rauf! Du bist in diesem Thread wohl der Einzige, der ein wirklich überzeugendes Argument gebracht hat. Nicht mal Rufus hat es fertig gebracht, auf ne sachliche Frage eine sachliche Antwort zu geben. W.S.
Nochwas: Nop schrieb: > Das kann man grundsätzlich immer. Die Frage ist nur, wieviel Zeit das > braucht. Denn man hätte es ja auch einfach gleich richtig schreiben > können Ja, eigentlich ein fettes JA... ABER: Die meisten C-Programmierer (auch hier in diesem Forum) haben eine unendliche Abscheu davor, einen biederen und in den Statements simpel gehaltenen Code zu schreiben. Das ist ihnen zu poplig und so werden oft genug Formulierungen geschrieben (einschließlich unangenehm vieler Casts), die fehlerträchtig sind und eben beim Durchgehen der Quellen einem partout nicht auffallen. Eben genau deshalb predige ich hier, daß man lieber die Dinge simpel schreiben soll und das Optimieren dem Compiler überlassen soll. Ist aber in den Wind gesprochen, und so wachsen die Leute immer wieder nach, die sich selbst ein Bein stellen. Die brauchen den Debugger dann dafür, herauszukriegen, was ihre Formulierung in der Quelle tatsächlich bewirkt. Kleines Beispiel am Rande: Ich hatte neulich in einer Quelle von der "blackmagic"-Jtag/Swd-Probe eine void function gefunden, die einen Wert zurückliefert. Was mich dabei gewundert hat war, daß der Gcc offenbar sowas hat durchgehen lassen. Bei meinem Versuch, den Kram per Keil zu übersetzen, hab ich natürlich ne fette Ohrfeige vom Compiler abgekriegt - welch Wunder.. W.S.
W.S. schrieb: > Was mich dabei gewundert hat war, daß der Gcc offenbar > sowas hat durchgehen lassen. Bei meinem Versuch, den Kram per Keil zu > übersetzen, hab ich natürlich ne fette Ohrfeige vom Compiler abgekriegt > - welch Wunder.. Wie, Du benutzt einen Compiler? Das hätte ich jetzt nicht gedacht!
W.S. schrieb: > Eins rauf! Du bist in diesem Thread wohl der Einzige, der ein wirklich > überzeugendes Argument gebracht hat. thx ;-) Wobei ich Debugger aber auch nur in solchen Extremfällen brauche. Im Normalfall habe ich ja ohnehin einen vernünftigen Hardfault-Handler, der nach Art eines Bluescreens die abstürzende Programm-Adresse aus dem Exception-Stack fummelt und loggt, und da sehe ich dann über das Mapfile schnell, in welcher Funktion das Problem liegt (weswegen ich für die Testbuilds inlining deaktiviere). Ging nur nicht im genannten Beispiel. > Ja, eigentlich ein fettes JA... ABER: Die meisten C-Programmierer (auch > hier in diesem Forum) haben eine unendliche Abscheu davor, einen > biederen und in den Statements simpel gehaltenen Code zu schreiben. Ich mach's da eher umgedreht - erstmal KISS und gucken, daß es überhaupt wie gewollt läuft. Dann schauen, ob weitere Optimierung sinnvoll ist. Wenn ja, dann erstmal auf algorithmischer Ebene verbessern anstatt mit Programmiertricks. Bevor ich einen Bubblesort optimier-verpfriemele, nehme ich gleich einen Shellsort. Was dann noch übrig bleibt, das kann dann schon tricky werden. Mit Pointergecaste, ggf. manuellen alignment-checks und mehrfachem Loop-Unrolling, was der Compiler so schlichtweg nicht kann. Ich hab mit solchen Tricks mal bei einem embedded Ethernettreiber den Durchsatz um den Faktor 3 erhöhen können, das war ordentlich. Die einzelnen Statements halte ich dabei aber auch simpel, statt mit kryptischer C-Syntax möglichst viel in eine Zeile zu klatschen. Fragezeichenoperator mit gleichzeitigen Seiteneffekten in einer Indexierung kann ich, mache ich aber nicht. Der Compiler optimiert beides ohnehin gleichermaßen gut. Da ich meinen Quelltext viel häufiger lese als schreibe, würde ich mir ja mit sowas nur selbst ein Bein stellen. Meine Fehler finde ich normalerweise nicht erst beim Testen, sondern schon vorher beim Review. Meiner Meinung nach zeichnet sich ein Profi nicht dadurch aus, daß er kryptischen Code schreiben kann, sondern daß er komplizierte Sachen mit übersichtlichem Code ausdrücken kann. Überhaupt, an jeder Stelle, wo ich beim Codieren nachdenken mußte, schreibe ich auch einen Kommentar, WAS ich mir gedacht habe - denn offensichtlich war das ja nicht offensichtlich. > (einschließlich unangenehm vieler Casts) Und dann auch noch oftmals verkehrte Casts. Da wird dann zum Alignment-Check wahlweise ganz ohne Cast direkt auf Pointern mit Bitmasken rumgemacht (unzulässig), oder wenn gecastet wird, dann nach irgendeinem unsigned int (oder noch schlimmer, nur int) anstatt nach uintptr_t. > Eben genau deshalb predige ich hier, daß man lieber die Dinge simpel > schreiben soll und das Optimieren dem Compiler überlassen soll. Auf dem Level, wo er das kann ja. Geht aber nicht immer. Das o.g. Beispiel des Ethernettreibers hat der Compiler nicht so optimieren können. > Kleines Beispiel am Rande: Ich hatte neulich in einer Quelle von der > "blackmagic"-Jtag/Swd-Probe eine void function gefunden, die einen Wert > zurückliefert. Was mich dabei gewundert hat war, daß der Gcc offenbar > sowas hat durchgehen lassen. Vermutlich ohne -Wall compiliert. Mit -Wall gibt das eine Warnung auch bei GCC; hab's gerade getestet. Allerdings gibt's ja auch Spezis, deren Code so schlecht ist, daß sie die Warnungen abschalten, um "Ruhe" zu haben. Bei mir ist Grundforderung, daß der Code mit -Wall ohne Warnungen compilieren muß - denn meistens verbirgt sich dahinter irgendwas Unerwünschtes. Zusätzlich lasse ich dann auch noch CppCheck auf meinen Code los. Die eine oder andere Warnung bleibt, das ist aber dann im Einzelfall technisch notwendig und gehört auch in die Projekt-Dokumentation.
Ach ja, und sogar ich habe an C Sachen zu meckern: - Das keyword "inline" ist Schrott. Es ist nur ein Vorschlag an den Compiler, mehr nicht. Bin ich auf dem Basar oder wie, daß ich mit meinem Compiler verhandele?! - Will ich ernsthaft "inline", dann geht das über Funktionsattribute, die aber compiler-spezifische Erweiterungen sind. Muß man sich also einmal irgendwo als Makro definieren, damit man Portabilität wahrt. - Manchmal will ich dem Compiler strikt verbieten, trotz allgemein erlaubtem Inlining eine bestimmte Funktion zu inlinen. Beispielsweise, wenn sie einen hohen Stackverbrauch hat. Die Inline-Logik jedenfalls beim GCC ist da ziemlich kaputt, weswegen ich ihm das explizit verbieten muß. Dafür gibt es nichtmal ein Surrogat eines keyword, aber immerhin Attribute - compilerspezifisch. - Es gibt zwar goto, und es gibt Pointer-Arithmetik, aber beides zusammen gibt's nur als compilerspezifische Erweiterung, nämlich das computed goto. Das hätte man auch in den Sprachstandard aufnehmen können. Kann durchaus nützlich sein.
W.S. schrieb: > Jim M. schrieb: >> Längerfristig will man sich aber einen Debugger zulegen. Die gibt es für >> ARM auch sehr preiswert. > > Und? Was hat man davon? > Es glauben gar viele Leute, daß ein Debugger das Allheilmittel sei. Ist > er nicht. Die Fehler, die man mit ihm finden kann, sind zu 99% eigene > Doofheit oder Unachtsamkeit. Alter Schwede, der W.S. ist heute wieder mal voll in seinem Element > Die eigentlichen Sauereien, die einem > gelegentlich das Leben schwer machen, findet man damit nimmer. Versuche > doch mal, nen USB-Handler per Debugger zu debuggen... nur so, als > Beispiel. Hab schon lang nicht mehr so einen Nonsens der mit so einer Vehemenz vorgetragen wurde gelesen. Das bringen in dieser ausgeprägten Form nur wenige in diesem Forum zustande.
Hallo, ich bins nochmal, der TO. Ich hab noch ne Frage zu 64Bit und STM32. Plus und mal mit 64Bit geht wunderbar, jetzt möchte ich zwei int64_t dividieren, dann kommen vom Linker Beschwerden: "main.out uses VFP register arguments, libgcc.a(bpabi.o) does not" "failed to merge target specific data of file libgcc.a(bpabi.o)" Das ganze für eine Anzahl .o Files, unter anderem _divdi3.o und _udivdi3.o Dann noch hinten was: "DISCARD has both ordered ['.ARM.exidx' in libgcc.a(_divdi3.o)] and unordered ........" Ich nehme an, dass ich die nativen 64Bit Operationen Plus und Mal nehmen kann, dass der linker aber für emulierte Operationen wie dividieren die falsche lib vorgesetzt kriegt. (Das würde wahrscheinlich auch das Problem lösen, weswegen ich diesen thread geöffnet habe und das ich nur umschifft aber nicht gelöst habe) Wie bringe ich dem linker denn die richtige lib nahe? THX Cheers Detlef
Deine FPU Optionen in der Nutzerfiles sind unterschiedlich von den Optionen in den Bibliotheken. Uebersetzte die Nutzfile mit den FPU Optionen der Bibliothek!
So sehen die Compile- und Linkflags aus: # Flags CFLAGS = -Wall -fno-common -c -g -mcpu=cortex-m4 -mthumb CFLAGS += -mfloat-abi=hard CFLAGS += -mfpu=fpv4-sp-d16 CFLAGS += -fno-math-errno CFLAGS += -ffast-math CFLAGS += -g $(OPTIMIZATION) $(INCLUDES) -DTRACE_LEVEL=$(TRACE_LEVEL) ASFLAGS = -g -mapcs-32 LDFLAGS = -g -v -nostartfiles -mfloat-abi=hard -mfpu=fpv4-sp-d16 LDFLAGS+= -mcpu=cortex-m4 -mthumb LDFLAGS+= -fno-math-errno LDFLAGS+= -ffast-math -specs=nosys.specs Wie findet der gcc denn dann die Bibliothken oder was muss ich hier ändern damit das zu den Bibliotheken passt? THX Cheers Detlef
Hoppla, was hat float und int64_t miteinander zu tun? Brauchst Du an anderer Stelle die Floating point unit? Wenn nicht, verwende CFLAGS += -mfloat-abi=soft. Anderenfalls brauchst Du ein libgcc was mit mfloat-abi=hard kompiliert ist.
Wie Uwe schon geschrieben hat, mischt du hard-float und soft-float. Das geht nicht! Entweder nur hard oder nur soft!
1 | -mfloat-abi=soft |
2 | -mfloat-abi=hard |
mfg
Also bei mir erzeugt mein Makefile (ebenfalls handgeklöppelt) folgende Compiler- und Linkeraufrufe und hard-float funktioniert: Vielleicht kannst Du Dir da die passenden Flags und Optionen rausklauben. Auch die Reihenfolge der Optionen und Argumente ist stellenweise relevant. [CC] src/main.c: arm-none-eabi-gcc -MMD -c -o build/src/main.o -Isrc/STM32F401XE -ffunction-sections -mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -std=gnu11 -ggdb -Os -flto -Wall -Wextra -Wstrict-prototypes -Werror -Wno-error=unused-function -Wno-error=unused-variable -Wfatal-errors -Warray-bounds -Wno-unused-parameter src/main.c [LD] build/hello_world.elf: arm-none-eabi-gcc -o build/hello_world.elf build/src/STM32F401XE/gcc_startup_system.o build/src/main.o -ffunction-sections -mlittle-endian -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -std=gnu11 -ggdb -Os -flto --specs=nano.specs --specs=nosys.specs -nostartfiles -Wl,--gc-sections -Tsrc/STM32F401XE/gcc_linker.ld -lm -Wl,-Map=build/hello_world.map Ich verwende den offiziellen gcc von Arm auf Launchpad.
Hallo,
habs gefunden.
>>>>
Brauchst Du an anderer Stelle die Floating point unit?
Ja, brauche ich und da hatte ich vor einiger Zeit mit dieser -lm Option
rumgebastelt, die muss nämlich komischerweise ganz hinten stehen beim
Linkerkommando.
Das sah dann bei mir so aus:
$(LD) $(LDFLAGS) -T$(LINKER_SCRIPT) -o $(OUTPUT).out $(C_OBJECTS)
$(ASM_OBJECTS) libgcc.a -lm
Er linkte mir dann eine lokale Version von libgcc mit ein, die die
Probleme machte.
So gehts':
$(LD) $(LDFLAGS) -T$(LINKER_SCRIPT) -o $(OUTPUT).out $(C_OBJECTS)
$(ASM_OBJECTS) -lm
Der es wissen will, ein sehr interessanter Hintergrund:
Ich möchte die Abweichung d zweier Zähler (int32_t)a und b in ppb 'parts
per billion' berechnen d=1e9*(a-b)/a. a und b werden sehr gross, 1e8
Grössenordnung. Für diese Rechnung reicht die Stellenanzahl von 32 Bit
floats (ca. 6 Stellen) nicht mehr aus. Wenn a und b langsam in gleichem
Abstand hochlaufen sollte sich das Ergebnis langsam und stetig ändern.
Bei float32-Rechnung springt es hin und her, bei 64 Bit Rechnung ist
alles gut.
Danke für die Hilfe.
Cheers
Detlef
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.