mikrocontroller.net

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


Autor: Philipp F. (nerdture)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
das will einfach nicht so ganz funktionieren. Alles was ich tue ist eine 
Variable in einer Schleife abfragen:
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:
SIGNAL(SIG_OVERFLOW2) {
  clk_subseconds = (clk_subseconds+1)%SUBSECONDS;
  if(!clk_subseconds) {
    clk_seconds++;
    if(menu_countdown > 0) menu_countdown--; //Menu countdown timer (for automatic return)
  }
  
  if(clk_seconds >= 86400) clk_seconds = 0; //reset after 24h
  if((clk_seconds % 10800)==0) clk_seconds += 1; //standardadjustment: +1 sec per 3 hours
  
  if(clk_shown) { //if we want to see the time
    clk_refresh(0);
  }

}

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interrupt, wahrscheinlich fehlt ein volatile

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstens fehlt wahrscheinlich volatile. Zweitens eigentlich auch dein 
Problem.

Autor: Philipp F. (nerdture)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Philipp F. (nerdture)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lies den Artikel!

Autor: Philipp F. (nerdture)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Falk Brunner (falk)
Datum:

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

MFG
Falk

Autor: Ulrich P. (uprinz)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

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.