mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik compiler optimierung zuviel :/


Autor: Waldgichtel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend zusammen,

da mir zur Anzeige von Informationen nur eine einzelnde RGB-LED zur 
Verfügung steht habe ich mir mittels einem Timer eine kleine Funktion 
geschrieben die unterschiedliche Blink-sequenzen ausgeben kann. Mein 
Problem ist nun dass bei abgeschalteter Compiler-Optimierung alles 
einwandfrei funktioniert, ist allerdings -Os eingeschaltet kommt es zu 
Problemen.

Im Anhang der Beispielcode.

Ohne optimierung:
die erste led Sequenz wird nach dem Start angezeigt. Nach drücken auf 
den Taster wird die zweite Sequenz geladen. ... alles wie es sein soll.

Mit Optimierung (-Os):
Nach dem Start sind alle LED-Ausgänge auf low. Nach Drücken des Tasters 
wird die zweite LED-Sequenz angezeigt. ... das erste init_led_seq 
scheint ignoriert zu werden.

Habe auch schon versucht die globalen Variablen direkt zu setzten, ohne 
eine extra Funktion (init_led_seq()) zu verwenden. Hatte leider den 
gleichen Effekt.

Habe auch schon die Warteschleife bis der Taster gedrückt wird mit ein 
paar Zeilen gefüllt, auf den Verdacht hin, dass da etwas wegoptimiert 
wird ... auch kein Erfolg.

Was mach ich falsch?

Vielen Dank schonmal, und schönen Abend noch.

Toni

Autor: --> (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste doch mal das generierte Assemblerfile

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht ist der unoptimierte Code so langsam, dass die 
Tasterentprellung von Haus mitgeliefert wird.

Autor: Experte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist doch sonnenklar:

Du hast Race-Conditions. Und davon eine ganze Menge.

Auch wenn in jedem AVR-Tutorial erzählt wird, dass "volatile" alle 
Probleme löst, ist es eben nicht so. "volatile" zu benutzen ist relativ 
dämlich, da ineffizient. Korrekt macht man so etwas mit 
Memory-Barrieren. Aber das ist ein anderes Thema, darum soll es hier 
nicht gehen.

Dein Problem sind die volatile-16-Bit-Variablen (led_out_seq, 
led_aku_seq). Die können nun mal nicht atomar auf einem 8-Bit Prozessor 
abgebildet werden. Wieder ein Beispiel wie bescheuert die 
"volatile"-Technik ist.

Dazu noch Datenabhängkeiten zwischen Variablen. Auch hier versagt 
volatile grandios.

Nun gut, einfach Lösung:
void init_led_seq(PGM_P led_seq, UCHAR delay){
  cli();
  led_aku_seq = led_seq; 
  led_delay = delay; 
  led_out_seq = led_seq; 
  sei();
}

Autor: Waldgichtel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang nochmal zur Sicherheit led_test.c die ich compliert habe. 
Einmal optimiert und einmal ohne optimierung.

Wegen der Tastenentprellung:
eigentlich sollte es ja egal sein wie oft die Taste nachprellt, da nach 
dem ersten Kontakt sowieso in die Endlosschleife gesprungen wird. 
Anstatt des Tasterdrucks habe ichs aber auch mit delays versucht.

Bei soetwas:

init_led_seq(led_1_min, 100);
_delay_ms(10000);
init_led_seq(led_5_min, 150);
_delay_ms(10000);
init_led_seq(led_10_sec, 100);

passiert 2*100000ms gar nix (Ausgänge bleiben auf low) und erst 
led_10_sec ganz am Ende wird ausgegeben. Bei ausgeschalteter Optimierung 
funktionierts aber auch hier wie erwartet ... 100000ms led_1min, 100000 
led_5_min, nachfolgend led_10_sec_

Toni

Autor: Waldgichtel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@ Experte

... zu spät deine Antwort gesehen. Habs nun auch so versucht wie du 
geschrieben hast.

Sowohl mit volatile als auch ohne vor den entsprechenden Variablen. 
Beides mal wieder ... ohne optimierungs klappts, mit nicht :/.

Wenns eine andere, schönere Möglichkeit gibt, mein Geblinke umzusetzten 
werf ich das ganze auch weg ;-) Nur fehlts mir da an den Ideen :/.

Toni

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deklarier die beiden Pointer mal als
PGM_P volatile led_out_seq = 0 ;
PGM_P volatile led_aku_seq = 0 ;

Warum das nötig ist? Deutlicher wird es bei normalen Pointern ohne die 
Makros:
volatile char *foo;

Damit wird ein Zeiger auf ein "volatile char" deklariert, d.h. das 
Ziel des Pointers ist volatile, der Zeiger selbst aber nicht. Um den 
Pointer selbst volatile zu machen ist folgendes nötig:
char * volatile foo;

Auf das PGM_P-Makro übertragen sieht das dann wie oben aus.

Da der Zeiger selbst in deinem Code nicht volatile ist, optimiert der 
Compiler dann den ersten Schreibzugriff weg, da in main() vor dem 
zweiten Schreibzugriff nicht mehr auf die Variablen zugegriffen wird.

Andreas

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Ferber schrieb:
> Deklarier die beiden Pointer mal als

Nachtrag: das cli()/sei() in init_led_seq() ist natürlich trotzdem noch 
nötig, um die Zugriffe atomar zu machen.

Andreas

Autor: Pothead (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Experte schrieb:
> Die können nun mal nicht atomar auf einem 8-Bit Prozessor
> abgebildet werden. Wieder ein Beispiel wie bescheuert die
> "volatile"-Technik ist.

Toll! Das ist ja auch gar nicht die Aufgabe von volatile. Thema 
verfehlt, sechs, setzen.

http://www.nongnu.org/avr-libc/user-manual/group__...

Autor: Waldgichtel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super vielen Dank :) jetzt funktionierts endlich :) Der Tipp von 
Andreas hat jetzt zum Ziel geführt :) freude :). Besten Dank.

Toni

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.