mikrocontroller.net

Forum: Compiler & IDEs Optimierung stört in while-Schleifen Anwendung


Autor: Ingo Stahl (ingo-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habe eine WinAVR Anwendung in der serielle Eingangsdaten per ISR in 
einen Ringbuffer geschrieben werden. In der Auslesefunktion überwache 
ich, das ich den Pointer auf die Eingangsposition nicht überhole. Mit 
der -Os Optimierung wird aber leider die Übernahme der momentanen 
Eingangsposition dummerweise vom Compiler optimiert vor die 
Warteschleife gesetzt.

Codebeibspiel das nicht funktioniert:

-----
char* psaveInputpos;

  // diese Schleife soll das Überholen der Eingangsposition verhindern
  do{
    cli();
    psaveInputpos = prInputpos;
    sei();
  }while(psaveInputpos == prOutputpos);

  //hier gehts dann weiter mit dem Abholen der neuen Daten
----
im Assembler Listing kann man sehen, das die Anweisung
  psaveInputpos = prInputpos;
vor die while Schleife gesetzt wird und damit funktioniert die Abfrage 
natürlich nicht mehr.
Gelöst habe ich das Problem indem ich den Positionsvergleich in eine 
getrennte Funktion ausgelagert habe, die ich allerdings dann noch als 
noinline deklarieren musste, sonst war es das selbe in grün.

Gibt es für solche Fälle Compiler Direktiven, die die Position einer 
Anweisung gezielt für eine Funktion oder innerhalb einer Funktion 
sicherstellen?

Gruß Ingo

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, gibt es: die vom Interrupt-Handler modifizierte Variable als 
volatile deklarieren.

Autor: Ingo Stahl (ingo-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi prx,

die sind natürlich volatile, selbst die Funktions interne zusätzlich als 
volatile zu definieren bringst nicht. Der Compiler setzt sie trotzdem 
vor die while Schleife :-((

Gruß Ingo

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vertrauen ist gut, Kontrolle ist besser. Ich sehe nirgends ein volatile.

Vorsorglicher Tipp: in
  volatile char *p;
zeigt ein non-volatile Pointer auf volatile char, in
  char *volatile p;
ist der Pointer selbst volatile.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ingo Stahl schrieb:
> Gibt es für solche Fälle Compiler Direktiven, die die Position einer
> Anweisung gezielt für eine Funktion oder innerhalb einer Funktion
> sicherstellen?

Nö. Der Compiler darf und wird die Reihenfolge der Anweisungen so 
umstellen, wie es es für sinnvoll hält. Das macht er das so, daß sich 
dabei am Ergebnis nichts ändert (wenn er keine Bug hat) .


Ingo Stahl schrieb:
> Der Compiler setzt sie trotzdem
> vor die while Schleife :-((

Bist du dir sicher? Optimierter Code ist schwer zu lesen. Die als 
Kommentar eingefügten C-Sourcecodezeilen kannst du als Anhaltspunkt 
dabei getrost vergessen.

Zeig mal ein compilierbares Codebeispiel, an dem sich das Verhalten 
reproduzieren lässt.

Oliver

Autor: Ingo Stahl (ingo-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
@prx:
so sind sie global definiert:
volatile char* prInputpos;
volatile char* prOutputpos;

die Anweisung
psaveInputpos = prInputpos;
gibt ein natürlich ein Warning, den Cast
psaveInputpos = (char*)prInputpos;
hatte ich vergessen mit anzuführen.
Wobei ich ja auch die Variante
volatile char* psaveInputpos;
erfolglos ausprobiert hatte.

@Oliver:
ich baue morgen mal wieder die alte Variante ein und zeige das 
Codebeispiel.
Sicher bin ich mir schon, ich bin beim Debugging (Dragon) auf die 
Assembler Ansicht gegangen. Ohne Optimierung sieht man, das der Compiler 
die Anwweisung nicht verschiebt.

Gruß Ingo

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ingo Stahl schrieb:

> so sind sie global definiert:
> volatile char* prInputpos;
> volatile char* prOutputpos;

Na also, dachte ich mir es doch. Die Pointer sind hier eben nicht 
volatile, auch wenn's für ungeübte Augen zunächst so aussieht, und daher 
gibst du dem Compiler die ungewollte Freiheit der Optimierung.

Damit deklarierst du, dass die chars, auf die die Pointer zeigen, 
volatile sind. Nicht die Pointer. Bei deinem Vergleich geht es aber um 
die Pointer, nicht die chars. Wenn du das grade ziehst bist du nebenbei 
auch ganz ohne cast die Warnung los. Also:
  char *volatile prInputpos;
  char *volatile prOutputpos;

Autor: Ingo Stahl (ingo-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

jetzt wollte ich es doch noch wissen und hab das Problem in einem 
Testprojekt nachvollzogen.

@prx:
Super Tipp, das wars!
Im Assembler Listing ist es einwandfrei sichtbar.
Irgentwie werde ich mit der für mich etwas kryptischen "C" Syntacs" 
trotz einiger Jahre VC++ nicht 100%tig so warm, das mir das auf Anblick 
auffällt.

@Oliver:
ich denke, das sich das Codebeispiel damit erledigt hat.

Gruß Ingo

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ingo Stahl schrieb:
> @Oliver:
> ich denke, das sich das Codebeispiel damit erledigt hat.

;-)

Oliver

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Ingo Stahl schrieb:
>> @Oliver:
>> ich denke, das sich das Codebeispiel damit erledigt hat.

hmmm, nicht wirklich. Zwar wird die störende Optimierung nicht mehr 
gemacht, aber es sieht stark danach aus, daß da noch ne Race-Condition 
zuschlagen kann wegen nicht-atomarem Code im Zeiger-Test.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn prOutputpos in der ISR nicht verändert wird (was zu vermuten ist), 
dann nicht.

Oliver

Autor: Ingo Stahl (ingo-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Wenn prOutputpos in der ISR nicht verändert wird (was zu vermuten ist),
> dann nicht.
>
> Oliver

genau, da fummelt keine ISR dran rum :-)

Gruß Ingo

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.