ATMEGA8: Variable in ISR ändern und in Schleife lesen

OP #798972
Lesenswert?

Hi,
das will einfach nicht so ganz funktionieren. Alles was ich tue ist eine 
Variable in einer Schleife abfragen:
1
while((inp=(PINB&0b111)) == 0b111 && menu_countdown);
(Es geht hierbei um menu_countdown)

und währenddessen sollte die folgende ISR diese Variable in 
Sekundenabständen dekrementieren:
1
SIGNAL(SIG_OVERFLOW2) {
2
  clk_subseconds = (clk_subseconds+1)%SUBSECONDS;
3
  if(!clk_subseconds) {
4
    clk_seconds++;
5
    if(menu_countdown > 0) menu_countdown--; //Menu countdown timer (for automatic return)
6
  }
7
  
8
  if(clk_seconds >= 86400) clk_seconds = 0; //reset after 24h
9
  if((clk_seconds % 10800)==0) clk_seconds += 1; //standardadjustment: +1 sec per 3 hours
10
  
11
  if(clk_shown) { //if we want to see the time
12
    clk_refresh(0);
13
  }
14

15
}

menu_countdown ist vom Typ uint8_t. Hier sollte es also keine Probleme 
geben, dass der Interrupt "waehrend des Lesens" eintritt... Was aber 
sonst ist hier los?

Danke, phil
OP #798984
Lesenswert?

Andreas Kaiser wrote:
> Erstens fehlt wahrscheinlich volatile. Zweitens eigentlich auch dein
> Problem.

Oh verdammt ^^. Das wichtigste Vergessen. Naja das Problem ist 
jedenfalls, dass es nicht aus der Schleife rausspringt. Also 
menu_countdown irgendwie nicht 0 zu werden scheint, obwohl die ISR ganz 
sicher aufgerufen wird (da bin ich mir wirklich sicher)
(Firma: DC3AX) #801561
Lesenswert?

Hi Falk, hi Philipp!

Also ich finde jetzt keinen direkten Hinweis auf volatile im PWM Link.
Daher mal vereinfacht:
Der Compiler weist irgendwann die CPU an den Inhalt der Variablen in ein 
Register zu laden und dann zu vergleichen. Gibt man kein volatile an, 
dann erlaubt man dem Compiler den Code so zu optimieren, dass er die 
Variablen im Register behält anstatt sie immer neu zu lesen. Das ist 
kürzer und schneller.

Da die Interrupt Routine sehr klein ist, ist die Wahrscheinlichkeit sehr 
hoch, dass der Compiler sie vollständig in Registern abhandelt, denn er 
ändert seine Strategie nicht Code zu optimieren. Er weiß nix von einer 
Spezialbehandlung für Interrupts.

Durch die volatile Anweisung weißt Du den Compiler an, diese Optimierung 
zu unterlassen und zwingst ihn, die Variable immer aus dem RAM zu lesen 
und dorthin zurück zu schreiben.

Das Gegenstück ist übrigens 'register', was den Compiler zwingt eine 
Variable zwingend in einem Register zu führen. Das kann in Interrupt 
Routinen von Vorteil sein um schnelleren Code oder RAM-sparenden Code zu 
schreiben.

Gruß, Ulrich
#801610
Lesenswert?

Ulrich P. wrote:
>
> Da die Interrupt Routine sehr klein ist, ist die Wahrscheinlichkeit sehr
> hoch, dass der Compiler sie vollständig in Registern abhandelt, denn er
> ändert seine Strategie nicht Code zu optimieren. Er weiß nix von einer
> Spezialbehandlung für Interrupts.

Das Problem ist nicht die Interrupt Routine.
Am Ende einer Funktion müssen sowieso alle in Register gehaltenen
Variablen ins RAM zurückübertragen werden.

Das Problem ist vielmehr die abfragende Schleife. Wenn der Compiler
sich hier dafür entscheidet, die Variable ständig im RAM zu behalten,
dann kriegt die abfragende Schleife eine Änderung des Variablen-
Wertes überhaupt nicht mit.

Das kann dann auch soweit gehen, dass die Datenfluss-Analyse
ergibt, dass diese konkrete Schleife überhaupt nie betreten
oder verlassen werden kann und wahlweise die Schleife
komplett entfernt oder gegen eine Endlosschleife ohne irgend
welche Abfragen ersetzt.

> Das Gegenstück ist übrigens 'register', was den Compiler zwingt eine
> Variable zwingend in einem Register zu führen.

'register' zwingt den Compiler zu überhaupt nichts.
'register' ist für den Compiler maximal ein Vorschlag, was man
denn machen könnte. Bei den meisten Compilern ist es eher so,
dass man froh sein kann, wenn der Compiler ein 'register' ganz
einfach ignoriert und lieber seiner Datenflussanalyse vertraut.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren