PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Optimierungslevel & Funktionalität ?!



Zarathustra
10.05.2007, 16:00
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. 8-[
Ich will ein PWM Signal auf 2 Ports ausgeben durch:



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


wobei motortick von einem Timer hochgezählt wird und mot1,2 die Intensität des Signals verändert.
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

Superhirn
10.05.2007, 16:16
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

izaseba
10.05.2007, 18:35
while (PORTB | (1<<PB5)) {
; //Achtung: ein ; ist hier
}
angeschrieben werden.

Klar optimiert er das weg (PORTB | (1<<PB5)) ist immer wahr...

@Markus,
hast Du motortick als volatile deklariert ?

Gruß Sebastian

Zarathustra
10.05.2007, 18:47
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 :-s
Erstaunlich..
Eine kurze Erklärung was genau das volatile dort anstellt?

thx & Gruß,
Markus

Superhirn
10.05.2007, 19:04
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.

izaseba
10.05.2007, 19:09
Eine kurze Erklärung was genau das volatile dort anstellt?
Gerne, volatile bezeichnet die Variable als flüchtig, d.h. bei jedem Zugriff soll sie bitteschön aus dem Speicher gelesen oder geschrieben werden.
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):wink:

Ich hoffe, daß es verständlich genug war :-)

Gruß Sebastian

izaseba
10.05.2007, 19:20
ja da hab ich mich vertan mit den & und |. sry.

Solltest Du die UND Verknüpfung gemeint haben, bestehe ich darauf, daß ein


while (PORTB & (1<<PB5)); etc wegoptimiert. sie müssen

nicht wegoptimiert wird, hier was gcc bei -Os daraus macht:


while (PORTB&(1<<PB5));
fa: c5 99 sbic 0x18, 5 ; 24
fc: fe cf rjmp .-4 ; 0xfa <main+0x1c>

Ich hoffe, daß Du soviel Assembler verstehen wirst.

Gruß Sebastian

Superhirn
10.05.2007, 20:10
ok ich verstehe es in asm so halbwegs.

danke ich dachte immer das ist so.

aber:

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

ist von mikrocontroller.net kopiert damit man wies wie die for nicht wegoptimiert wird :P

Zarathustra
10.05.2007, 20:14
Gute Erklärungen,
ich habe es verstanden und werde mich gleich daran begeben all meine "Interruptvariablen" als volatile zu erklären \:D/

Danke nochmal,
einen schönen Abend noch,
Markus

ragnar
10.05.2007, 20:18
while (PORTB | (1<<PB5)); etc wegoptimiert. sie müssen
while (PORTB | (1<<PB5)) {
; //Achtung: ein ; ist hier
}
angeschrieben werden.


@Superhirn:
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.

izaseba
10.05.2007, 20:29
Ja, Du mußt aber zugeben, das wir jetzt zwei paar Schuhe haben, zuerst haben wir auf einen Zustand gewartet

while (PORTB & (1<<PB5));
Hier hat der Compiler keinen Grund was wegzuoptimieren, egal wie Du das schreibst, mit Klammern, ohne Klammer, ja nachdem wie faul der Programmierer ist :wink:
Ich meine ohne Klammern ist das ganze besser lesbar.
Die leeren for Schleifen hingegen ergeben keinen Sinn, und da ist es auch richtig, daß sie rausfliegen, und es ist auch richtig, daß sie bleiben, wenn Du die Variable volatile machst, oder halt ein nop zwischen packst :-)
Das ist aber kein guter Still, wie lange dauert denn so eine Schleife ?
Kann man ja schlecht sagen, für sowas gibt es eine extra Bibliothek mit den berühmten delay Schleifen, die sicher elleganter gelöst sind, als die for Schleifen.
So jetzt reicht es, dem Markus haben wir geholfen, und ich wollte hier nicht unnötig OT werden
Gruß Sebastian

EDIT:
@ragner,
stimmt, das ergibt eher eine Endlosschleife

Superhirn
10.05.2007, 20:42
@ragnar:
ich bin da drauf gekommen da ich dachte er hat nur einen teil von seinm code geposted. und es war ja auch so.

das ich was falsches dachte wusste ich nicht. ich hab das schon seit monaten so im hinterkopf. 8-[ :-k