Hallo zusammen,
ich suche nun schon länger nach einer Lösung für folgende Aufgabe:
Ich möchte in einem C-Programm (für den ATMega2560) ermitteln, mit
welchen Optimizer-Einstellungen der Code compiliert wurde. Dabei genügt
es mit, -O0 bis -O3 zu erkennen. Wer hat das mal gemacht? Vielen Dank.
Ich compiliere mit avr-gcc im AVR Studio.
Grüße an alle Leser,
RichardHi
Hallo,
ja, das hatte ich auch schon gefunden. Aber den Level kann ich damit
nicht abfragen - oder: Ich wüsste nicht, wie.
Am Liebsten hätte ich gerne die Nummer des Levels zurück, ob Macro oder
Funktion ist egal.
Wofür brauche ich das?
Ich möchte sicherstellen, dass ich den richtigen Optimizer-Level
benutze, weil ich zum debugen und testen oft daran ändere wegen
zeitkritischer Routinen, und in der Final-Version möchte ich sicher
sein, dass ich mit -O2 kompiliert habe.
Danke für weitere Ideen,
RichardHi
RichardHi schrieb:> Ich möchte sicherstellen, dass ich den richtigen Optimizer-Level> benutze,
Klingt nach einem ziemlichen Hack, im Source-Code zu prüfen ob im
Build-System der "richtige" Level ausgewählt wurde! Und wie prüfst du im
Code ob die Optimierungen jetzt wirklich an sein sollen oder nicht?
Normalerweise macht man das so, dass man im Build System oder in der IDE
zwei (oder mehr) Konfigurationen, z.B. namens "Debug" und "Release"
anlegt, welche eben zum Debuggen bzw. auf Effizienz optimieren. Da kann
man mit einem Klick so kompilieren wie man es braucht, und muss nicht
von Hand den Optimierungs-Level umstellen.
Dr. Sommer schrieb:> Klingt nach einem ziemlichen Hack, im Source-Code zu prüfen ob im> Build-System der "richtige" Level ausgewählt wurde!
Naja, ganz so abwegig scheint das erstmal nicht zu sein. Man kann ja
auch Anderes aus dem Build-System in das Programm bekommen, z.B. die
Compiler-Version. Warum nicht auch den Optimizer-Level - das ist Idee.
Hat noch jemand einen Vorschlag ?
RichardHi schrieb:> Naja, ganz so abwegig scheint das erstmal nicht zu sein. Man kann ja> auch Anderes aus dem Build-System in das Programm bekommen, z.B. die> Compiler-Version. Warum nicht auch den Optimizer-Level - das ist Idee.>> Hat noch jemand einen Vorschlag ?
Mir erscheint das schon ein wenig abwegig. Wenn man eine vernünftige
Build-Umgebung hat, die einmal erzeugte Binaries reproduzierbar wieder
erzeugen kann (VCS), dann braucht man so was m.E. nicht. Im Zweifel
erzeugt man das Programm eben nochmal und macht einen Vergleich.
Wenn's denn unbedingt sein muss, bau' dein Makefile eben entsprechend
aus:
RichardHi schrieb:>
und in der Final-Version möchte ich sicher
> sein, dass ich mit -O2 kompiliert habe.
Nur mal rein interessehalber: warum -O2 und nicht -Os ?
Oliver
Oliver S. schrieb:> warum -O2 und nicht -Os ?
-Os ist Optimierung nach SIZE und lässt laut Doku die Optimierungen weg,
die zur Vergößerung des Binär-Codes führen würden. Das brauche ich nicht
auf dem Mega. Dann lieber schnelleren Code.
Markus F. schrieb:> Wenn's denn unbedingt sein muss, bau' dein Makefile eben entsprechend> aus:> .PHONY: flags> flags:> echo "const char used_flags[] = \"$(CFLAGS)\";" > flags.c>> Das Ergebnis baust Du irgendwo in dein Compilat ein und machst dir noch> eine Abfragefunktion dazu.
Ja gute Idee, das scheint prinzipiell ein Weg zu sein.
Aber ich habe kein eigenes Make-File, sondern das generiert AVR Studio
für mich. Kann ich das irgendwie ergänzen, so ähnlich wie ein
Include-File?
Ich benutze allerdings noch 4.18 (never change a running system) und bin
zufrieden damit.
Markus F. schrieb:> Mir erscheint das schon ein wenig abwegig. Wenn man eine vernünftige> Build-Umgebung hat, die einmal erzeugte Binaries reproduzierbar wieder> erzeugen kann (VCS),
Nur als Zwischenfrage: Welche Build-Umgebung kann aus einem bestimmten
Quelltext-Stand wieder das gleiche Binary erzeugen? Bei einem Artikel
über den Review von TrueCrypt wurde erwähnt, daß ein nicht unerheblicher
Aufwand schon allein darin entstand, daß moderne Build-Umgebungen mit
mehreren parallelen Threads aus dem gleichen Quellmaterial selten das
gleiche Binary erzeugen, selbst wenn auf Konstrukte wie __DATE
verzichtet wird, da hier Laufzeiteffekte zum tragen kommen.
RichardHi schrieb:> Kann ich das irgendwie ergänzen, so ähnlich wie ein> Include-File?
Du kannst in Atmel-Studio Pre-Build und Post-Build Scripte definieren.
Ich nutze das gerne, um die Revisionsnummer aus dem
Versionsverwaltungssystem in ein *.c-File einzubauen.
RichardHi schrieb:> Oliver S. schrieb:>> warum -O2 und nicht -Os ?>> -Os ist Optimierung nach SIZE und lässt laut Doku die Optimierungen weg,> die zur Vergößerung des Binär-Codes führen würden. Das brauche ich nicht> auf dem Mega. Dann lieber schnelleren Code.
Nun ja, und du hast nachgemessen, ob O2 tatsächlich schneller ist als
Os?
Denn ich bezweifele das ganz stark. gcc ist ein toller Compiler, der ist
aber primär nicht für AVRs gemacht. Dessen Optimierungen sind vor allem
für die Hauptplattformen optimiert.
Und selbst auf Intels oder Arms gilt immer noch : messen, messen,
messen, nicht glauben.
Oliver
Oliver S. schrieb:> Nun ja, und du hast nachgemessen, ob O2 tatsächlich schneller ist als> Os?>> Denn ich bezweifele das ganz stark. gcc ist ein toller Compiler, der ist> aber primär nicht für AVRs gemacht. Dessen Optimierungen sind vor allem> für die Hauptplattformen optimiert.>> Und selbst auf Intels oder Arms gilt immer noch : messen, messen,> messen, nicht glauben.
Ich habe zeitkritischen Programmcode, bei dem die
Optimierungseinstellung weiterhilft oder eben nicht. Deshalb muss ich
auch immer mal "an diesen Schrauben drehen".
Insbesondere habe ich einen Codeabschnitt gehabt, den der Optimizer
kaputt-optimiert hat. Den musste ich einklammern in
#pragma GCC optimize ("-O1")
<Codeabschnitt>
#pragma GCC reset_options
Dr. Sommer schrieb:> Korrekter Code funktioniert immer unabhängig von> der Optimierung.
Denkste. Wäre schön, ist aber wohl nicht generell so:
Insbesondere habe ich einen Codeabschnitt gehabt, den der Optimizer
kaputt-optimiert hat. Den musste ich einklammern in
#pragma GCC optimize ("-O1")
<Codeabschnitt>
#pragma GCC reset_options
Walter T. schrieb:> Du kannst in Atmel-Studio Pre-Build und Post-Build Scripte definieren.
Hab ich leider nicht gefunden in der IDE. Gib mir bitte mal nen Tipp.
Oliver S. schrieb:> Und selbst auf Intels oder Arms gilt immer noch : messen, messen,> messen, nicht glauben.
Genau. Deshalb habe ich häufig einen Frequenzzähler an einem Pin, über
den ich Loops ausmessen kann, wenn ich in der Loop das Pin toggle.
Meinst du sowas?
RichardHi schrieb:> Hab ich leider nicht gefunden in der IDE. Gib mir bitte mal nen Tipp.
Tut mir leid, aus Atmel Studio 4 bin ich jetzt seit 2012 heraus.
Irgendwo bei den Build-Optionen.
RichardHi schrieb:> Insbesondere habe ich einen Codeabschnitt gehabt, den der Optimizer> kaputt-optimiert hat.
Dann war er falsch geschrieben. ;-)
Wenn du zyklengenauen Code brauchst, musst du (Inline-)Assembler
benutzen. In allen anderen Fällen sollte es bestenfalls „zu schlecht
optimiert“ (=> zu groß oder zu langsam für die Aufgabe) geben, aber
nicht „zu gut optimiert“.
Auf dem AVR ist kürzerer Code in der überwiegenden Anzahl der Fälle
auch schnellerer Code¹, weshalb man mit -Os meist gar nicht so
schlecht fährt.
¹Ausnahme: die aggressiven (und platzintensiven) Optimierungen von -O3
wie das Aufrollen von Schleifen bewirken tatsächlich nochmal eine
Steigerung der Geschwindigkeit, allerdings für einen vergleichsweise
hohen Preis.
RichardHi schrieb:> Genau. Deshalb habe ich häufig einen Frequenzzähler an einem Pin, über> den ich Loops ausmessen kann, wenn ich in der Loop das Pin toggle.>> Meinst du sowas?
Das, oder ähnliches. Wenn dein Code mit O2 nachgewiesenermaßen schneller
läuft als mit Os, dann ist das so.
Oliver
Walter T. schrieb:> Markus F. schrieb:>> Mir erscheint das schon ein wenig abwegig. Wenn man eine vernünftige>> Build-Umgebung hat, die einmal erzeugte Binaries reproduzierbar wieder>> erzeugen kann (VCS),>> Nur als Zwischenfrage: Welche Build-Umgebung kann aus einem bestimmten> Quelltext-Stand wieder das gleiche Binary erzeugen? Bei einem Artikel> über den Review von TrueCrypt wurde erwähnt, daß ein nicht unerheblicher> Aufwand schon allein darin entstand, daß moderne Build-Umgebungen mit> mehreren parallelen Threads aus dem gleichen Quellmaterial selten das> gleiche Binary erzeugen, selbst wenn auf Konstrukte wie __DATE> verzichtet wird, da hier Laufzeiteffekte zum tragen kommen.
Antwort: jede, die sorgfältig genug zusammengebaut wurde. Hier:
https://reproducible-builds.org wird das Thema erschöpfend behandelt.
RichardHi schrieb:> Denkste. Wäre schön, ist aber wohl nicht generell so:
Ist so, bis auf sehr seltene Compiler Fehler.
> Insbesondere habe ich einen Codeabschnitt gehabt, den der Optimizer> kaputt-optimiert hat.
Die Wahrscheinlichkeit, dass dein Code falsch war, ist wesentlich höher.
Es gibt in C und C++ viele Möglichkeiten, solche Fehler zu machen, von
denen viele Programmierer nicht wissen. Es gibt hier öfters Fragen nach
solchen Problemen...
Kann man in deinem alten Atmel Studio denn keine 2 Build Configurations
anlegen (das neue kann's)? Da macht man einfach 2 für Debug/Release, und
hat das Problem mit einem Mausklick erledigt und muss nie wieder an den
Compiler Optionen rumfummeln. So ist das üblich, keiner außer dir
braucht dafür Makros für den Optimizer Level.
Dr. Sommer schrieb:> Die Wahrscheinlichkeit, dass dein Code falsch war, ist wesentlich höher.> Es gibt in C und C++ viele Möglichkeiten, solche Fehler zu machen, von> denen viele Programmierer nicht wissen.
Hallo zusammen,
es geht hier im Grunde gar nicht um die Frage, ob irgendein Code falsch
oder richtig war. Das ist ein weites Feld, das wir hier sicher nicht
erschöpfend behandeln können. Darüber gibt es viele Abhandlungen, auch
im Rahmen der theoretischen Informatik z.B. über Berechenbarkeit und
Entscheidbarkeit.
Alan Turing lässt grüßen.
Für die Interessierten, was der Compiler/Optimizer wegoptimiert hat:
Ich hatte zweimal kurz hintereinander den ADC abgefragt und die Werte
in zwei Variable gestellt. Eine ADC-Abfrage wurde nach dem Optimieren
mit -O2 oder -O3 nicht ausgeführt. Auch volatile half da nicht.
Jetzt aber zurück zum eigentlichen Thread:
Wer kann mir zeigen, wie ich in AVR Studio 4.18 das automatisch
generierte make-File um einen Schritt ergänzen kann, in dem ich den
Optimizer-Level in ein Includefile schreibe, was ich im C-Programm
mitkompiliere? Das muss vor dem Kompilieren passieren.
Dr. Sommer schrieb:> Kann man in deinem alten Atmel Studio denn keine 2 Build Configurations> anlegen (das neue kann's)?
Man kann. Und da die Build-Zeiten naturgemäß überschaubar sind, ist ein
kompletter rebuild ja auch kein Beinbruch.
Oliver
Oliver S. schrieb:> Und da die Build-Zeiten naturgemäß überschaubar sind, ist ein> kompletter rebuild ja auch kein Beinbruch.
Kommt drauf an, wie viel C++ template Wahnsinn man verwendet ;-)
Um die Optimierung zu ändern, muss man ja aber sowieso alles neu
kompilieren.
RichardHi schrieb:> Eine ADC-Abfrage wurde nach dem Optimieren> mit -O2 oder -O3 nicht ausgeführt. Auch volatile half da nicht.
Klingt seltsam, bei allen Programmen bisher funktioniert das. Sicher,
dass das Programm nicht einfach nur zu schnell war und die Abfragen zu
schnell hintereinander ausgeführt wurden oder so?
RichardHi schrieb:> Darüber gibt es viele Abhandlungen, auch> im Rahmen der theoretischen Informatik
Na, mit Halteproblem & Co hat das weniger zu tun, mehr mit dem
C(++)-Standard und den magischen Worten "undefined behaviour"...
RichardHi schrieb:> Jetzt aber zurück zum eigentlichen Thread:
Die wichtigste Frage ist noch nicht geklärt: Angenommen du hast im Code
den tatsächlichen Optimizer Level abgefragt, woher weiß der Code dann
welcher Level korrekt ist? Du müsstest im Code dann ja noch zusätzlich
eintragen, wie du optimieren möchtest. Das ist komplizierter und
fehleranfälliger als die schlichte Nutzung von 2 Build Configurations.
Dr. Sommer schrieb:> woher weiß der Code dann welcher Level korrekt ist?
Vielleicht ist es keine Information, die der Quelltext auswertet,
sondern der Nutzer?
Ich mache bei meinen Projektchen, sobald ein LCD dran ist, auch immer
eine kleine Info-Darstellungsfunktion, wo Versionsstand,
Compilerversion, usw. dargestellt werden. Das hilft, wenn man die Geräte
nach langer Zeit wieder in die Hand bekommt, durchaus weiter.
Walter T. schrieb:> Vielleicht ist es keine Information, die der Quelltext auswertet,> sondern der Nutzer?
Der Workflow wäre also:
1.) In den Build-Einstellungen die Optimierung auswählen
2.) flashen
3.) Im LCD schauen ob der richtige Optimierungslevel ausgewählt wurde
Anstatt:
1.) Auf "Release" klicken (Siehe Anhang, Screenshot aus VS, auf dem neue
Atmel Studio Versionen basieren)
Klingt total praktisch...
Dr. Sommer schrieb:> Der Workflow wäre also:> 1.) In den Build-Einstellungen die Optimierung auswählen> 2.) flashen> 3.) Im LCD schauen ob der richtige Optimierungslevel ausgewählt wurde
Nein, der Workflow wäre:
1.) In den Build-Einstellungen die Optimierung auswählen
2.) Flashen
3.) Erste Geräte an diejenigen verteilen, die es auch nutzen
4.) Firmware weiterentwickeln
...
5<m<n-2.) Vielleicht für einen speziellen Zweck eine Firmware-Variante
stricken, die sich von den anderen unterscheidet.
n-2.) Zu einem Gerät kommt eine Frage vom Benutzer
n-1.) Benutzer macht Foto von Infoscreen
n.) Ich weiß wieder genau, welches Gerät mit welcher Firmwarerevision
überhaupt gemeint ist.
Walter T. schrieb:> Ich weiß wieder genau, welches Gerät mit welcher Firmwarerevision> überhaupt gemeint ist.
Um so ein Problem ging es in diesem Thread aber überhaupt nicht:
RichardHi schrieb:> Wofür brauche ich das?> Ich möchte sicherstellen, dass ich den richtigen Optimizer-Level> benutze, weil ich zum debugen und testen oft daran ändere wegen> zeitkritischer Routinen, und in der Final-Version möchte ich sicher> sein, dass ich mit -O2 kompiliert habe.
Dr. Sommer schrieb:> Um so ein Problem ging es in diesem Thread aber überhaupt nicht
Ich habe keine Ahnung, was für den TO eine "finale Version" ist. Für
mich ist eine "finale Version" etwas, (notwendige aber leider manchmal
nicht hinreichende Bedingung), was meinen Schreibtisch vor langer Zeit
verlassen hat.
Nachtrag: Ausnahme sind natürlich Gadgets für meinen Schreibtisch.
RichardHi schrieb:> Hat noch jemand einen Vorschlag ?
Generier doch einfach immer beides, dauert bei heitigen PCs vielleicht
maximal 1 Sekunde länger.
Das eine nennst du porjekt-debug.elf und das andere projekt-release.elf.
Ersteres verwendest du zum Debuggen, zweiteres zur Release. Oder gleich
alle generierten Dateien in eigene Ordner:
debug/projekt.elf
debug/modul1.o
debug/modul2.o
...
release/projekt.elf
release/modul1.o
release/modul2.o
...
Walter T. schrieb:>> woher weiß der Code dann welcher Level korrekt ist?>> Vielleicht ist es keine Information, die der Quelltext auswertet,> sondern der Nutzer?
Das denke ich auch. Wenn der Optimizer-Level beim Programmstart
angezeigt wird, kann der Nutzer entscheiden: Shit happens, nochmal
kompilieren.
> Ich mache bei meinen Projektchen, sobald ein LCD dran ist, auch immer> eine kleine Info-Darstellungsfunktion, wo Versionsstand,> Compilerversion, usw. dargestellt werden. Das hilft, wenn man die Geräte> nach langer Zeit wieder in die Hand bekommt, durchaus weiter.
Jawoll, genau so sehe ich das auch! Walter versteht mich. D A N K E
Zeigst du auch Compiler-Parameter an, wie z.B. den Optimizer-Level?
-- das wäre ja die Lösung --
RichardHi schrieb:> Das denke ich auch. Wenn der Optimizer-Level beim Programmstart> angezeigt wird, kann der Nutzer entscheiden: Shit happens, nochmal> kompilieren.
Du willst also Walter's Ansatz, der ein ganz anderes Problem löst, nur
eingeschränkt nutzbar ist (nur wenn LCD vorhanden und flashen einfach
ist), auf dein Problem anwenden, für welches es bereits eine etablierte
Lösung gibt, die bei Tausenden Projekten wunderbar funktioniert und
gegen die bisher kein einziges Gegenargument genannt wurde? Man kann es
sich auch schwer machen...
PS: Du kannst ja in der Build-Configuration so etwas wie
-DCONF=\"Relase\" bzw. -DCONF=\"Debug\" übergeben, und dann im Programm
auf dem LCD CONF ausgeben, da kannst du dann sehen wie es kompiliert
wurde. Da du in der Build-Configuration nie den Optimierungs-Level
ändern solltest, kannst du so folgern welche Optimierung angewendet
wurde.
Dr. Sommer schrieb:> .., für welches es bereits eine etablierte> Lösung gibt, die bei Tausenden Projekten wunderbar funktioniert
Sorry, wo ist die Lösung? Nur weil ich zwischen zwei Configurations in
der IDE umschalten kann, weiß ich doch auf dem ATmega nicht, welche
Build-Variante gefahren wurde, und ob die vielleicht geändert wurde,
z.B. der Optimizer-Level.
RichardHi schrieb:> weiß ich doch auf dem ATmega nicht, welche> Build-Variante gefahren
Musst du ja auch nicht. Du flasht grundsätzlich immer die
Release-Variante, die ist immer mit Optimierungen. Da brauchst du dann
auch nix mehr zu prüfen.
RichardHi schrieb:> und ob die vielleicht geändert wurde,> z.B. der Optimizer-Level.
Du lässt bei Release immer die Optimierung an, und bei Debug aus.
Genau. Und weil du das nicht weißt, ist der Ansatz, sich auf gar nichts
zu verlassen, sondern einfach ein komplettes rebuild mit nachgeprüften
und bekannten Optionen durchzuführen und zu flashen.
Oliver
RichardHi schrieb:> Zeigst du auch Compiler-Parameter an, wie z.B. den Optimizer-Level?> -- das wäre ja die Lösung --
Nein, ich kenne keine Lösung für das Problem. Ich zeige einfach nur an,
-ob es ein Debug-Build ist oder nicht (im Screenshot: kein Debug) und
-ob der Quelltext des Builds ins Versionsverwaltungssystem eingecheckt
wurde (hier: noch nicht.)
Die Optimierungs-Optionen in Release ändere ich so selten, da meine
Firmware immer massig Reserve hat, daß ich sie bei Bedarf mit der
Kenntnis der Versionsnummer immer aus dem Makefile auslesen kann.
Sprich: Für mich ist das Problem keins.
Dr. Sommer schrieb:> Du flasht grundsätzlich immer die> Release-Variante, die ist immer mit Optimierungen
Ich muss doch aber auch mal eine andere Variante flashen können, um
Tests auf der echten Hardware zu machen - nicht alles geht im Debugger.
Besonders nicht, wenn vom ATmega noch einiges an Elektronik gesteuert
wird.
Und dann habe ich die Notwendigkeit, auf der LCD-Anzeige (die ich immer
dran habe) zu sehen, ob und wie optimiert wurde.
Vertrauen ist gut - Kontrolle ist besser. Meistens sitzt das Problem
davor.
RichardHi schrieb:> Insbesondere habe ich einen Codeabschnitt gehabt, den der Optimizer> kaputt-optimiert hat. Den musste ich einklammern in> #pragma GCC optimize ("-O1")> <Codeabschnitt>> #pragma GCC reset_options
Das hättest Du auch beheben können indem Du stattdessen einfach Deinen
defekten Code repariert hättest.
RichardHi schrieb:> Ich muss doch aber auch mal eine andere Variante flashen können, um> Tests auf der echten Hardware zu machen - nicht alles geht im Debugger.
Kannst du ja...
RichardHi schrieb:> Und dann habe ich die Notwendigkeit, auf der LCD-Anzeige (die ich immer> dran habe) zu sehen, ob und wie optimiert wurde.
Statt zu prüfen, kannst du auch einfach die Release Variante drüber
flashen. Wenn die schon drauf war, sollte der Programmer das merken und
nichts tun, um Flash-Zyklen zu sparen.
Bernd K. schrieb:> Das hättest Du auch beheben können indem Du stattdessen einfach Deinen> defekten Code repariert hättest.
Sage mal: warum behauptest du, der Code wäre defekt gewesen?
Wenn du etwas Produktives beizutragen hast, kannst du dich gerne wieder
melden. Aber das ist gar nix: Behauptungen aufzustellen, ohne überhaupt
die Idee eines Beweises zu haben.
Übrigens geht es in diesem Thread nicht um das ADC-Codestück.
Es geht um was ganz anderes.
"Wer lesen kann ist klar im Vorteil"
So.
RichardHi schrieb:> Sage mal: warum behauptest du, der Code wäre defekt gewesen?
Aus purer Neugier: Zeig den Code doch einfach mal... Wenn er wirklich
korrekt ist, hattest du ja Recht ;-)
Wenn Du ständig damit beschäftigt bist immer wieder aufs Neue auf gut
Glück an den Optimierungsoptionen herumzuschrauben und dann ausprobieren
ob es jetzt zufällig besser oder schlechter wird oder gar nicht mehr
gehtr dann ist was anderes faul (Das ganze Konzept, die gewählte
Hardware, die Umsetzung, die Fertigkeiten, etc).
Normalerweise hat man eine Einstellung für Release mit den üblichen
empfohlenen Optionen und noch ne zweite Einstellung für Debug. Die
meiste Zeit verbringt man empfohlenerweise damit sich über die Hardware
und den Code und deren Zweck und Funktionsweise Gedanken zu machen
anstatt dauernd blind an den Compileroptionen rumzuspielen.
Dr. Sommer schrieb:> PS: Du kannst ja in der Build-Configuration so etwas wie> -DCONF=\"Relase\" bzw. -DCONF=\"Debug\" übergeben, und dann im Programm> auf dem LCD CONF ausgeben
Das möchte ich jetzt mal ausprobieren.
> auf dem LCD CONF ausgeben
Was kommt im Programm an?
Wie greife ich darauf zu?
RichardHi schrieb:> Was kommt im Programm an?> Wie greife ich darauf zu?
Einfach CONF reinschreiben. Das wird dann zu "Debug" bzw. "Release",
d.h. einem schnöden String-Literal. Wie du vielleicht weißt, kann man
String-Literale einfach hintereinander schreiben, um sie zu
konkatenieren:
RichardHi schrieb:> Aber das ist gar nix: Behauptungen aufzustellen, ohne überhaupt> die Idee eines Beweises zu haben.
Du hast doch angefangen zu behaupten der gcc würe Deinen Code
kaputtmachen ohne den Hauch eines Beweises vorzulegen. Mein Rasiermesser
sagt mir daß es überwältigend viel wahrscheinlicher ist daß Dein Code
schon vorher kaputt war und der tausende von Mannjahren alte gcc alles
vollkommen richtig gemacht hat.
Bernd K. schrieb:> dauernd blind an den Compileroptionen rumzuspielen
Wieso behauptest du das? Du weißt doch gar nicht, ob ich weiß was ich
tue.
Weißt du was du schreibst?
Jetzt: konkreter Vorschlag und nicht so ein "du machst es
falsch"-Gesabbel.
RichardHi schrieb:> Bernd K. schrieb:>> Du hast doch angefangen zu behaupten der gcc würe Deinen Code>> kaputtmachen>> Hab ich nie gesagt. So, und jetzt geh mal offline.
Doch, und zwar da:
Beitrag "Re: AVR GCC Optimizer Level in C-Programm abfragen"
und zwar wörtlich "kaputt" soll er ihn gemacht haben, ich zitiere:
> habe ich einen Codeabschnitt gehabt, den der Optimizer kaputt-optimiert hat
RichardHi schrieb:> Hab ich nie gesagt.
Doch, hast du.
Beitrag "Re: AVR GCC Optimizer Level in C-Programm abfragen"RichardHi schrieb:>> dauernd blind an den Compileroptionen rumzuspielen>> Wieso behauptest du das? Du weißt doch gar nicht, ob ich weiß was ich> tue.
Jedenfalls irgendwas Seltsames.
Ich programmiere nun schon ziemlich lange Mikrocontroller, aber ich
habe eigentlich so gut wie nie die Notwendigkeit gehabt, an den
Optimierungseinstellungen herumzuschrauben. Wenn ich ein
Zwischenergebnis im Debugger sehen will, welches mir der Compiler
ansonsten wegoptimiert, dann werf' ich mal schnell eine "volatile"
deklarierte Variable da hinein, in der das Ergebnis notiert wird.
Debuggt wird bei mir prinzipiell mit den Einstellungen, mit denen das
am Ende im Feld laufen soll, denn ich möchte das debuggen, was dann
auch benutzt wird, und nicht ein völlig anderes Compilat.
Bei dieser Vorgehensweise erübrigt sich das ganze Ansinnen, das zu
diesem Thread geführt hat, eigentlich von vornherein.
Dr. Sommer schrieb:> Aus purer Neugier: Zeig den Code doch einfach mal... Wenn er wirklich> korrekt ist, hattest du ja Recht ;-)
Nochmal: Ich will gar nicht Recht haben.
Ich zeige euch den Code, damit Ruhe ist.
1
#define mess_delay 5 // Verzögerung vor der Messung
2
#define mess_delta 50 // Differenz, die 0 und 1 unterscheidet
3
#define ADC_pin_check 0 // der ADC-Channel für Pin-Kontaktmessung
4
uint16_tmessung0;
5
uint16_tmessung1;
6
7
initADC_single();
8
9
// Bit ausschalten
10
switch(pin[k].reg)
11
{
12
case'A':PORTA&=~(1<<pin[k].bit);break;
13
case'B':..hierweitereFälle
14
default:error(4,tx_wrong_case);
15
}
16
17
delay_ms(mess_delay);
18
messung0=ADC_read_avg(ADC_pin_check,2);
19
20
// Bit einschalten
21
switch(pin[k].reg)
22
{
23
case'A':PORTA|=(1<<pin[k].bit);break;
24
case'B':..hierweitereFälle
25
default:error(4,tx_wrong_case);
26
}
27
28
delay_ms(mess_delay);
29
messung1=ADC_read_avg(ADC_pin_check,2);
30
31
iniADC_singleist:
32
33
voidinitADC_single(void)
34
{
35
ADCSRA|=((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));//Prescaler at CPUclock/128
36
ADMUX|=(1<<REFS0);//internal Reference
37
ADMUX&=~(1<<REFS1);//Avcc(+5V) as voltage reference
38
//ADMUX |= (1<<ADLAR); //Ergebnis linksbündig
39
ADMUX&=~(1<<ADLAR);//Ergebnis rechtsbündig
40
ADCSRA|=(1<<ADEN);//ADC enable
41
ADCSRA|=(1<<ADSC);//Start initial conversion
42
while(ADCSRA&(1<<ADSC)){;}// auf Abschluss der Konvertierung warten
returnsumADC/times;// das dauert länger wegen der Division
53
}
Was ich erlebt habe ist, dass der Optimizer mit -O2 und -O3 den Code
messung1=ADC_read_avg(ADC_pin_check,2);
nicht ausführt.
Das umgehe ich, indem ich temporär auf -O1 zurückgehe, wie bereits oben
beschrieben.
RichardHi schrieb:> Was ich erlebt habe ist, dass der Optimizer mit -O2 und -O3 den Code> messung1=ADC_read_avg(ADC_pin_check,2);> nicht ausführt.
Sieht alles soweit ok aus, aber ADC_read wird nicht gezeigt :/ Und ohne
den Code selbst kompilieren zu können kann ich da auch nicht wirklich
was zu sagen...
RichardHi schrieb:> return sumADC/times; // das dauert länger wegen der Division
... Es sei denn die Funktion wird geinlined, die Division durch 2 ist
schnell (bitshift).
Le X. schrieb im Beitrag #5166565:
> Stelle nur kurze, präzise Fragen die sich ebenso kurz und präzise> beantworten lassen.
Die kurze präzise Antwort ist "geht nicht". Das hilft ihm wenig. Daher
wurden alternative bewährte Lösungsansätze geboten.
Dr. Sommer schrieb:> Und ohne> den Code selbst kompilieren zu können kann ich da auch nicht wirklich> was zu sagen...
Und ohne die Schaltung, die an dem ADC-Pin hängt, vielleicht auch nicht.
RichardHi schrieb:> Und ohne die Schaltung, die an dem ADC-Pin hängt, vielleicht auch nicht.
Och, den Compiler anwerfen und den Assembler-Code anschauen würde gehen.
Da sollten ja die zwei Aufrufe zu sehen sein. Selbst wenn ich es flashen
würde, könnte ich ja das Rauschen messen...
Dr. Sommer schrieb:> Selbst wenn ich es flashen> würde, könnte ich ja das Rauschen messen...
Stimmt auch wieder.
Jörg W. schrieb:> Bei dieser Vorgehensweise erübrigt sich das ganze Ansinnen, das zu> diesem Thread geführt hat, eigentlich von vornherein.
Wer nicht mehr mitmachen möchte, darf sich ausklinken.
Und nicht vergessen: Die Spinner sind die Gewinner. War immer so.
==============================
Jetzt wieder zum Thread-Thema:
==============================
Dr. Sommer schrieb:
>> PS: Du kannst ja in der Build-Configuration so etwas wie>> -DCONF=\"Relase\" bzw. -DCONF=\"Debug\" übergeben, und dann im Programm>> auf dem LCD CONF ausgeben>
Das möchte ich jetzt mal ausprobieren. Sagte ich schon.
Frage dazu:
Verstehe ich es richtig? Wenn ich -DCONF=\"Relase\" in die Options
schreibe (dahin wo auch sowas wie -Wstrict-prototypes oder -Wall steht),
dann kann ich im C-Programm hinschreiben:
char lcd[32];
strncpy(lcd,CONF,32);
und in lcd steht dann "Relase"?
RichardHi schrieb:> Insbesondere habe ich einen Codeabschnitt gehabt, den der Optimizer> kaputt-optimiert hat.RichardHi schrieb:> Ich muss doch aber auch mal eine andere Variante flashen können, um> Tests auf der echten Hardware zu machen - nicht alles geht im Debugger.
Was verstehst */du/* unter (un)echter Hardware und unter Debugger?
RichardHi schrieb:> Frage dazu:> Verstehe ich es richtig? Wenn ich -DCONF=\"Relase\" in die Options> schreibe (dahin wo auch sowas wie -Wstrict-prototypes oder -Wall steht),> dann kann ich im C-Programm hinschreiben:> char lcd[32];> strncpy(lcd,CONF,32);> und in lcd steht dann "Relase"?
Ja ist korrekt. Das -DCONF=\"Release\" ist äquivalent zu
1
#define CONF "Release"
Somit wird aus der strncpy-Zeile einfach (simple Textersetzung durch den
Präprozessor)
Ralf G. schrieb:> RichardHi schrieb:>> Ich muss doch aber auch mal eine andere Variante flashen können, um>> Tests auf der echten Hardware zu machen - nicht alles geht im Debugger.>> Was verstehst */du/* unter (un)echter Hardware und unter Debugger?
Die Vermutung liegt nahe, dass er mit "echter Hardware" den Prozessor
meint (eben das, worauf man die Firmare flasht) und mit vermutlich eine
Simulation des Prozessors. Dr. Sommer hatte als "Lösung" allerdings
vorgeschlagen, die Debug-Version einfach gar nicht mehr auf den
Prozessor zu flashen.
Rolf M. schrieb:> Die Vermutung liegt nahe, dass er mit "echter Hardware" den Prozessor> meint (eben das, worauf man die Firmare flasht) und mit "Debugger" vermutlich
eine
> Simulation des Prozessors.
Fast richtig. Der Prozessor sitzt auf einem Prozessorboard, an das
weitere Hardware angeschlossen wird, die vom Prozessorboard gesteuert
wird. Die habe ich im Debugger nicht zur Verfügung.
Mit Debugger meine ich den internen Debugger in AVR Studio. Das ist eine
Simulation des Prozessors. Damit teste ich den Code zeilenweise, wenn er
nicht das tut was ich meinte oder wollte.
Falsch macht der Compiler ja nichts, wie wir gelernt haben, nur anders
als man vielleicht wollte. Manchmal macht man eben selbst was falsch.
RichardHi schrieb:> Mit Debugger meine ich den internen Debugger in AVR Studio.
Dacht' ich mir's. Das nennt man Simulator. Da liegt die Vermutung nahe,
dass der Code auch in höheren Optimierungsstufen schon richtig
ausgeführt wird, der Simulator aber die Codestellen 'nicht
wiederfindet', weil durch die Programmoptimierung Zwischenergebnisse
kurzzeitig in Registern gehalten werden oder sinnlose Berechnungen
einfach 'wegoptimiert' sind. Es scheint dann so, dass beim Steppen
durch den Quelltext Berechnungen übersprungen werden...
RichardHi schrieb:> Was ich erlebt habe ist, dass der Optimizer mit -O2 und -O3 den Code> messung1=ADC_read_avg(ADC_pin_check,2);> nicht ausführt.
Wie hast Du das diagnostiziert? Hast Du das Assemblerlisting angesehen
oder bist durchgesteppt? Oder bist Du nur aufgrund anderer Symptome
indirekt zu einer Vermutung gelangt ohne den eigentlichen erzeugten Code
zu sichten?
Bernd K. schrieb:> Wie hast Du das diagnostiziert?> Hast Du das Assemblerlisting angesehen> oder bist durchgesteppt?
Ob ich das Assemblerlisting angesehen habe, weiß ich nicht mehr. Ist
schon länger her, und ich habe das Problem ja gelöst.
Dass beim durchsteppen Codestellen nicht gezeigt werden, weiß ich.
Bernd K. schrieb:> Oder bist Du nur aufgrund anderer Symptome> indirekt zu einer Vermutung gelangt?
Und zwar bin ich mit dem Degubber drangegangen, weil der Coe nicht das
tat was ich wollte. Da hab ich dann bemerkt, dass die erste und zweite
Messung sich nicht unterscheiden. (Oder war es so, dass die zweite
Messung immer gleich war egal mit welchen Pins - das läuft nämlich in
einer Loop, das hatte ich vorhin weggelassen.)
Und auf dem Prozessorboard verhielt es sich ebenso.
Ich will an dies Thema jetzt auch nicht mehr dran, denn es funktioniert
so wie es ist. Dieser Thread geht ja um etwa ganz anderes.
Dr. Sommer schrieb:> Das -DCONF=\"Release\" ist äquivalent zu #define CONF "Release"
Und B I N G O
Ich habe jetzt mehrere Configurations angelegt mit identischen
Einstellungen außer -Ox und -DCONF=
War ein bisschen verzwickt, weil AVR Studio kein kopieren einer
Configuration kann. So habe ich das XML-File <projekt>.aps manipuliert
und Configurations kopiert und später in der IDE geändert.
Und ein simples lcd_print("\nConfig="); lcd_print(CONF); zum
Programmstart oder sowas ähnliches ist der Schlüssel zum Glück.
Danke, Dr. Sommer und allen anderen für die vielen Beiträge.