www.mikrocontroller.net

Forum: Compiler & IDEs Problem mit Switch-Statement und Optimierung


Autor: Eike S. (corny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin zusammen,

irgendwie habe ich ein ziemlich seltsames Problem bei einem Programm für 
einen ATMega16, an dem ich gerade bastele.

Ich habe auf PINA0 und PINA1 jeweils einen Schalter, der mir den Eingang 
nach Masse zieht, sowie externe Pull-Ups. Die Pins sind als Eingänge 
geschaltet.

Ich verwende folgende Struktur (aufs Notwendige reduziert), um die 
Eingänge auszuwerten:
// Am Anfang von main
volatile unsigned char prog;

//...
// (im Main-Loop)
prog = PINA & 0x03;
switch (prog)
{
  case 3:
    break;
  case 2:
    break;
  case 1:
    break;
  case 0:
    break;
}

Gehe ich jetzt über den JTAG-Debugger drauf, hat die Variable prog immer 
den richtigen Wert, abhängig von den externen Schalterstellungen. Bis 
dahin kommt also alles wie es soll, Hardware und Software sind also an 
sich korrekt.
Allerdings wird das switch-Statement nicht ausgeführt, solange ich eine 
Optimierungsstufe ungleich 0 ausgewählt habe. Einen passenden Zweig gibt 
es, mehr als vier Möglichkeiten habe ich bei zwei Bit ja nicht. Bei -O0 
läuft alles, bei allen anderen Optimierungsstufen nicht. Wenn ich im 
Debugger als aktuelle Anweisung das switch-Statement habe, und per 
Einzelschritt weiterspringe, komme ich wieder auf das switch-Statement, 
als hätte ich keinen passenden Zweig.
Syntaktisch korrekt muß aber alles sein, sonst würde es mit -O0 ja nicht 
funktionieren.

Kennt jemand dieses in meinen laienhaften Augen seltsame Verhalten des 
Compilers? Habe ich ein Brett vor'm Kopf? Hilfe... Ich habe zwar genug 
Platz, mit unoptimiertem Code zu arbeiten, aber ich wüßte doch gerne, 
warum der so tut wie er tut.

Zur Ausstattung auf meinem Entwicklungs-PC: Jeweils die aktuellsten 
Fassungen von AVR-Studio und WinAVR, die Platine mit dem µC ist über 
einen JTAGICE mkII von Atmel angebunden.

Wenn mir jemand helfen kann, soll ihn mein Dank ewiglich verfolgen. ;-)

Autor: Michael B. (planlessmichi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin zwar kein Assemblertyp, aber vielleicht hilft Dir in diesem - 
für mich auch seltsamen Fall - einfach mal ein Vergleich der 
lss-Dateien!?
Erstelle doch einfach mal mit 2 Optimierungsstufen (0 und beliebig) die 
hex-Datei und vergleiche dann die jeweiligen Stellen in den lss-Dateien.
Vielleicht findest Du mit denen was raus?
Viel Glück :-)

Autor: Murkser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Füge doch einmal eine "default"-Klausel ein und schau nach, welchen Wert 
"prog" annimmt. Ansonsten müßtest Du schon mehr von Deinem Code zeigen, 
evtl. könntest Du Dir generierten Assembler-Code anschauen, der bei 
-O1..3 herauskommt.

   Murkser

Autor: Eike S. (corny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob ich default mit drin habe oder nicht, macht keinen Unterschied, auf 
die Idee war ich auch schon gekommen.

Viel mehr Code gibt es nicht zu zeigen, ich habe eigentlich nur das 
Mainloop-Konstrukt weggelassen und die Inhalte der einzelnen 
Case-Blöcke. Zwischen der Zuweisung und dem Switch steht nichts, davor 
nur ein do { und nach dem Switch-Block ein } while(1);. Die Inhalte der 
einzelnen Case-Zweige sind ja dafür erstmal nicht relevant.

Die Assemblergeschichten nutzen mir leider recht wenig, wenn ich ehrlich 
bin, verstehe ich da nur Bahnhof. :(

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du denn in deinem Original etwas im switch stehen?
Wenn ja: was?

So wie es oben gezeigt wird, kann es natürlich komplett
wegoptimiert werden.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eike S. schrieb:
> Die Inhalte der
> einzelnen Case-Zweige sind ja dafür erstmal nicht relevant.

Es sei denn, der Compiler hält den Inhalt für überflüssig.

Autor: Eike S. (corny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Innerhalb der einzelnen Case-Blöcke weise ich verschiedene Variablen zu, 
die an anderer Stelle (ISR vom Timer) ausgewertet werden. Außerdem setze 
ich ein paar Ausgänge in direkter Abhängigkeit von den Eingängen. Selbst 
wenn also die Variablen (wieso auch immer) wegoptimiert würden, 
spätestens das Setzen der Ausgänge sollte ja eigentlich nicht 
wegoptimiert werden können.

Nachtrag: Compilerwarnungen sind eingeschaltet, und Warnungen wegen 
ungenutzter Variablen bekommen ich keine.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eike S. schrieb:
> Innerhalb der einzelnen Case-Blöcke weise ich verschiedene Variablen zu,
> die an anderer Stelle (ISR vom Timer) ausgewertet werden. Außerdem setze
> ich ein paar Ausgänge in direkter Abhängigkeit von den Eingängen. Selbst
> wenn also die Variablen (wieso auch immer) wegoptimiert würden,
> spätestens das Setzen der Ausgänge sollte ja eigentlich nicht
> wegoptimiert werden können.

Werden die Ausgänge denn wirklich anders gesetzt als ohne Optimierung, 
oder ist dein Problem einfach nur, dass du mit dem Debugger den Code 
nicht vernünftig singlesteppen kannst? Falls nur letzteres: das kommt 
mit Optimierung schonmal vor, da muss man mit leben ;-)

Andreas

Autor: bob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

wenn Du im main nur Zuweisungen zu Variablen durchführst die "nur" in 
der ISR genutzt/verändert werden, dann solltest du die mit volatile 
definieren, da sonst der Optimierer hier voll zuschlägt und alles 
wegschmeisst was nicht innerhalb des gleichen Scopes verwendet wird, da 
er sich denkt, dass das Ergebnis ja keiner braucht.

Das passiert in die Gegenrichtung genauso. Eine Variable die in der ISR, 
nur gesetzt/verändert aber sonst dort an keiner weiteren Stelle 
verwendet wird, wird gnadenlos ignoriert. Und im Debugger funktionierts, 
das ist das Tolle daran.

Beispiel:
volatile uint16_t counter;

damit passiert kein Unsinn wenn counter in der ISR verändert, aber nur 
im main abgefragt wird.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eike S. schrieb:
> Wenn ich im
> Debugger als aktuelle Anweisung das switch-Statement habe, und per
> Einzelschritt weiterspringe, komme ich wieder auf das switch-Statement,
> als hätte ich keinen passenden Zweig.

Was genau funktioniert denn nicht? Werden denn die Ausgänge richtig 
gesetzt, wenn du das Programm durchlaufen lässt?

Das der Debugger bei eingeschalteter Optimierung ziemlich planlos durch 
das Programm hüpft, ist normal. Das optimierte Programm hat vermutlich 
nicht mehr viel mit dem Sourcecode zu tun, da sieht man dann komische 
Sachen.

Oliver

Autor: Eike S. (corny)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal vielen Dank an alle, die selbst zu nachtschlafender Zeit hier 
geantwortet haben! Doch im Einzelnen:

Andreas Ferber schrieb:
> Werden die Ausgänge denn wirklich anders gesetzt als ohne Optimierung,
> oder ist dein Problem einfach nur, dass du mit dem Debugger den Code
> nicht vernünftig singlesteppen kannst? Falls nur letzteres: das kommt
> mit Optimierung schonmal vor, da muss man mit leben ;-)

Nee, die Ausgänge werden auch nicht gesetzt. Ohne das Debugger-Wissen, 
daß die Eingänge korrekt gelesen werden, hätte ich zuerst auf einen 
Fehler der Eingangsbeschaltung/-Konfiguration getippt.  Bei 
eingeschaltetem Optimizer passiert nach außen hin sichtbar nichts. Es 
ist also nicht nur das Problem, nicht singlesteppen zu können.

bob schrieb:
> wenn Du im main nur Zuweisungen zu Variablen durchführst die "nur" in
> der ISR genutzt/verändert werden, dann solltest du die mit volatile
> definieren, da sonst der Optimierer hier voll zuschlägt und alles
> wegschmeisst was nicht innerhalb des gleichen Scopes verwendet wird, da
> er sich denkt, dass das Ergebnis ja keiner braucht.

Danke, so weit war ich auch schon - nur spätestens beim Hardwarezugriff, 
beim Schreiben eines I/O-Registers, da darf doch nichts wegoptimiert 
werden. Der geschriebene Wert ist zwar eine Konstante, aber diese ist 
abhängig von jeweils durchlaufenen Case-Zweig.


Oliver schrieb:
> Was genau funktioniert denn nicht? Werden denn die Ausgänge richtig
> gesetzt, wenn du das Programm durchlaufen lässt?

Nein.

> Das der Debugger bei eingeschalteter Optimierung ziemlich planlos durch
> das Programm hüpft, ist normal. Das optimierte Programm hat vermutlich
> nicht mehr viel mit dem Sourcecode zu tun, da sieht man dann komische
> Sachen.

Das Problem hatte ich schon öfter, das würde mich nicht wundern. Wie ich 
schon auf einen anderen Post antwortete, es passiert rein gar nichts, 
wenn die Optimierung an ist.

Autor: Michael B. (planlessmichi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste doch mal Deine lss-Files (einmal ohne, einmal mit Optimierung). 
Auch wenn Du/wir nicht viel damit anfangen kannst/können - evtl. sieht 
ja ein anderer den Grund

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.