Hallo Zarathustra!
Gib uns doch mal deinen ganzen code.
mein optimeren werden schleifen wie
while (PORTB | (1<<PB5)); etc wegoptimiert. sie müssen
while (PORTB | (1<<PB5)) {
; //Achtung: ein ; ist hier
}
angeschrieben werden.
lg
Thomas
Hallo Gemeinde!
Seit einer Stunde wieder an meinem ATmega8 Motortreiber sitzend stelle ich gerade erstaunt fest, dass das "Optimization level" des AVR Studios die Funktionsweise meines Codes beeinflusst.
Ich will ein PWM Signal auf 2 Ports ausgeben durch:
wobei motortick von einem Timer hochgezählt wird und mot1,2 die Intensität des Signals verändert.Code:if(motortick < mot1) MOTOR1_PORT |= (1<<MOTOR1_PIN); else MOTOR1_PORT &= ~(1<<MOTOR1_PIN); if(motortick < mot2) MOTOR2_PORT |= (1<<MOTOR2_PIN); else MOTOR2_PORT &= ~(1<<MOTOR2_PIN);
Kompiliere ich mit Optimierungsstufe s, 1, 2 oder 3, sind die Ausgänge immer auf high, mit 0 hingegen funktioniert es richtig prima (allerdings ist die HEX 4 mal so groß).
Eigentlich dürfte doch eine Optimierung die Funktion des Skripts nicht verändern, oder?
Gibt es vielleicht etwas zu berücksichtigen wenn man mit 's' programmiert?
Gruß,
Markus
Hallo Zarathustra!
Gib uns doch mal deinen ganzen code.
mein optimeren werden schleifen wie
while (PORTB | (1<<PB5)); etc wegoptimiert. sie müssen
while (PORTB | (1<<PB5)) {
; //Achtung: ein ; ist hier
}
angeschrieben werden.
lg
Thomas
Klar optimiert er das weg (PORTB | (1<<PB5)) ist immer wahr...while (PORTB | (1<<PB5)) {
; //Achtung: ein ; ist hier
}
angeschrieben werden.
@Markus,
hast Du motortick als volatile deklariert ?
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
Hallo Superhirn,
Das gepostete war eigentlich schon fast der gesamte Code und das hochzählen durch den Timer2 Interrupt funktioniert problemlos auch unter "s".
Zu deinem Code: ich würde izaseba zustimmen und besser PORTB & (1<<PB5) schreiben, weil 1 oder 0 immer eins ist.
@izaseba,
ich habe auf deinen Hinweis hin mal ganz unverbindlich ein volatile hingeschrieben (volatile unsigned int compfreq, motortick, mot1, mot2) und siehe da: es funktioniert
Erstaunlich..
Eine kurze Erklärung was genau das volatile dort anstellt?
thx & Gruß,
Markus
ja da hab ich mich vertan mit den & und |. sry.
ohne volatile wird von der variable eine kopie im register angelegt damit sie schneller ist. und diese kopie kann jedoch nicht durch einem interrupt etc verändetr werden.
das volatile verhindert das kopien angelegt werden.
Gerne, volatile bezeichnet die Variable als flüchtig, d.h. bei jedem Zugriff soll sie bitteschön aus dem Speicher gelesen oder geschrieben werden.Eine kurze Erklärung was genau das volatile dort anstellt?
Das hindert den Compiler daran sie in einem Register zu halten, weil der Inhalt an einer anderen Stelle (bei Dir der Timerinterrupt) geändert werden könnte, ohne das der Prozessor es merkt.
Variablen, die für die Komunikation zwischen Interrupts und Hauptprogramm zuständig sind, sind daher als volatile zu deklarieren, es sei den man macht die Optimierung weg (-O0) was ja nicht gerade Sinn macht(wie Du leider feststellen musstest)
Ich hoffe, daß es verständlich genug war
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
Solltest Du die UND Verknüpfung gemeint haben, bestehe ich darauf, daß einja da hab ich mich vertan mit den & und |. sry.
nicht wegoptimiert wird, hier was GCC bei -Os daraus macht:Code:while (PORTB & (1<<PB5)); etc wegoptimiert. sie müssen
Ich hoffe, daß Du soviel Assembler verstehen wirst.Code:while (PORTB&(1<<PB5)); fa: c5 99 sbic 0x18, 5 ; 24 fc: fe cf rjmp .-4 ; 0xfa <main+0x1c>
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
ok ich verstehe es in asm so halbwegs.
danke ich dachte immer das ist so.
aber:
ist von mikrocontroller.net kopiert damit man wies wie die for nicht wegoptimiert wird :PCode:... uint16_t i; /* leere Schleife - wird bei eingeschalteter Compiler-Optimierung wegoptimiert */ for (i = 0; i < 1000; i++) ; ... /* Schleife erzwingen (keine Optimierung): "NOP-Methode" */ for (i = 0; i < 1000; i++) asm volatile("NOP"); ... /* alternative Methode (keine Optimierung): */ volatile uint16_t j; for (j = 0; j < 1000; j++) ;
Gute Erklärungen,
ich habe es verstanden und werde mich gleich daran begeben all meine "Interruptvariablen" als volatile zu erklären \/
Danke nochmal,
einen schönen Abend noch,
Markus
@Superhirn:while (PORTB | (1<<PB5)); etc wegoptimiert. sie müssen
while (PORTB | (1<<PB5)) {
; //Achtung: ein ; ist hier
}
angeschrieben werden.
IMHO sind obige Zeilen C absolut identisch und werden nicht
unterschiedlich optimiert. Sprich: der erzeugte Code ist absolut
identisch. Dem compiler ist es egal ob der Block hinter dem
while explizit oder implizit leer ist.
Und wie bist du eigentlich auf dieses Beispiel gekommen, daß
überhaupt nichts mit der Originalfrage zu tun hat.
@Izaseba:
Nachdem boolsche Ausdrücke von links nach rechts ausgewertet
werden glaube ich das ein "while (var | 1)" niemals wegoptimiert wird
(auch wenn das Ergebnis immer bekannt ist).
@Zarathustra:
Solange du nur motortick in deinem Interrupt verändernst (und nicht
mot1 oder mot2) reicht es auch nur motortick als volatile zu deklarieren.
Lesezeichen