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


von Eike S. (corny)


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:
1
// Am Anfang von main
2
volatile unsigned char prog;
3
4
//...
5
// (im Main-Loop)
6
prog = PINA & 0x03;
7
switch (prog)
8
{
9
  case 3:
10
    break;
11
  case 2:
12
    break;
13
  case 1:
14
    break;
15
  case 0:
16
    break;
17
}

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. ;-)

von Michael B. (planlessmichi)


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 :-)

von Murkser (Gast)


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

von Eike S. (corny)


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. :(

von Klaus W. (mfgkw)


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.

von Klaus W. (mfgkw)


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.

von Eike S. (corny)


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.

von Andreas F. (aferber)


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

von bob (Gast)


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:
1
volatile uint16_t counter;

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

von Oliver (Gast)


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

von Eike S. (corny)


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.

von Michael B. (planlessmichi)


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

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
Noch kein Account? Hier anmelden.