Forum: Mikrocontroller und Digitale Elektronik ATMEGA8: Variable in ISR ändern und in Schleife lesen


von Philipp F. (nerdture)


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

von Falk B. (falk)


Lesenswert?

Interrupt, wahrscheinlich fehlt ein volatile

von Andreas K. (a-k)


Lesenswert?

Erstens fehlt wahrscheinlich volatile. Zweitens eigentlich auch dein 
Problem.

von Philipp F. (nerdture)


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)

von Philipp F. (nerdture)


Lesenswert?

Ja danke, wie geil. Mit volatile vor der Variablen gehts!
Versteh ich zwar nicht so ganz aber danke!

von Falk B. (falk)


Lesenswert?

Lies den Artikel!

von Philipp F. (nerdture)


Lesenswert?

Ja habs gesehn, da steht drin man solls verwenden, aber ich versteh noch 
nicht ganz warum es mit geht und ohne nicht. Warum soll der Compiler das 
wegoptimieren?

von Falk B. (falk)


Lesenswert?

OK, steht dort nicht. Entschuldigung. Es steht, wenn gleich sehr kurz, 
im Artikel Soft-PWM, vor der letzten Überschrift "Zusammenfassung".

MFG
Falk

von Ulrich P. (uprinz)


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

von Karl H. (kbuchegg)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.