Forum: Mikrocontroller und Digitale Elektronik Muss Variable auch volatile sein, wenn sie NUR in ISR verwendet wird?


von Mario F. (superdude)


Lesenswert?

Hallo,
ich weis es gibt sehr viele Threads zu volatile, aber die kreisen alle 
um die Standardsituation "Variable wird im Hauptprogramm UND 
InterruptServiceRoutine (ISR) verwendet".

Ich würde gerne wissen, ob eine globale Variable, die ich NUR in der ISR 
verwende, auch volatile sein muss?

Also ist folgendes Beispiel auch ohne volatile safe?
1
#define LED0_TOG()    PORTA ^= (1<<PA0)
2
#define LED1_TOG()    PORTA ^= (1<<PA1)
3
4
volatile uint8_t ints_cnt = 0;
5
6
ISR(INT0)
7
{
8
  if (ints_cnt==100)
9
  {
10
    ints_cnt = 0;
11
    LED0_TOG();
12
  }
13
  else if {ints_cnt==0 || ints_cnt==50}
14
  {
15
    LED1_TOG();
16
  }
17
  ints_cnt++;
18
}

Meine vermutung wäre, dass es safe ist, da ints_cnt ja nicht anderweitig 
verändert werden kann, und der Compiler das "Variablen cachen" daher 
gerne aktivieren darf (das er hier wohl anwenden dürfte).

Danke für Antworten!

von (prx) A. K. (prx)


Lesenswert?

Da geht es auch ohne "volatile". Sicherer ist es dann freilich, wenn du 
die Variable innerhalb der ISR als "static" definierst, denn dann ist 
der Sachverhalt offensichtlich und niemand kommt später auf dumme 
Gedanken.

von Stefan E. (sternst)


Lesenswert?

Mario Fischer schrieb:
> Ich würde gerne wissen, ob globale eine Variable, die ich NUR in der ISR
> verwende, auch volatile sein muss?

Nein.

Aber wenn sie wirklich nur in dieser einen ISR verwendet wird, wäre es 
sinnvoll, sie static local zu machen, statt global.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mario Fischer schrieb:
> Ich würde gerne wissen, ob eine globale Variable, die ich NUR in der ISR
> verwende, auch volatile sein muss?

Nein, muss sie nicht.

> Also ist folgendes Beispiel auch ohne volatile safe?

Ja, aber wenn Du sie ausschließlich in der ISR benutzt, dann schreibe 
sie auch dort hinein!

Also:
1
ISR(INT0)
2
{
3
    static uint8_t ints_cnt = 0;        // static, damit sie "weiterlebt"
4
    ...

Damit ist dann klar, wo sie benutzt wird, nämlich ausschließlich in der 
ISR.

Gruß,

Frank

von Lutz (Gast)


Lesenswert?

Eigentlich sollte man immer berücksichtigen, warum es volatile gibt: 
Wenn für den Compiler nicht ersichtlich ist, daß sich eine Variable 
ändern kann. Eine ISR ist dabei zwar der Klassiker, aber nicht alleine.

von Karl H. (kbuchegg)


Lesenswert?

Mario Fischer schrieb:
> Hallo,
> ich weis es gibt sehr viele Threads zu volatile, aber die kreisen alle
> um die Standardsituation "Variable wird im Hauptprogramm UND
> InterruptServiceRoutine (ISR) verwendet".
>
> Ich würde gerne wissen, ob eine globale Variable, die ich NUR in der ISR
> verwende, auch volatile sein muss?

Wird Zeit das Thema mal in der FAQ anzusprechen :-)

Nein!
Das volatile sagt dem Compiler, dass sich eine Variable verändern kann, 
ohne dass er das mit seinen Datenflussanalysen rausfinden kann. volatile 
verlangt vom Compiler, dass jeder Zugriff auf die Variable so wie 
hingeschrieben durchgeführt werden muss.

Warum ist das wichtig?

Weil du in der Hauptschleife zb so was machen kannst

    while( Flag_welches_von_einer_ISR_verändert wird )
      ;

Die Datenflussanalyse des Compilers findet raus, dass sich in dieser 
Schleife die Variable überhaupt nicht verändern kann, weil es keinen 
Funktionsaufruf oder sonst irgendeine Zuweisung an diese Variable gibt. 
Für den Compiler ist daher diese while Schleife:
 entweder
* wird sie nie ausgeführt (wenn die Variable vor der Schleife
   auf 0 ist)
* oder es ist eine Endlosschleife (wenn die Variable vor der Schleife
   nicht 0 ist)

er kann daher dieses while so implementieren

   if( Flag_welches_von_einer_ISR_verändert wird )
     while( 1 )
       ;

und spart damit die Zugriffe auf die Variable ein.

Das ist aber nicht das was du willst. Denn du als Programmierer weißt, 
dass es sehr wohl eine Möglichkeit gibt, wie die Variable ihren Wert 
verändern kann. Nur für den Compiler ist das nicht ersichtlich. Also 
musst du ihm mit dem volatile helfen.

von Mario F. (superdude)


Lesenswert?

Danke für die Antworten!
Stimmt, da habt ihr recht, das Beispiel hätte besser ausgesehen, wenn 
ich ints_cnt als static in die ISR reingeschrieben hätte...

von chris (Gast)


Lesenswert?

>Aber wenn sie wirklich nur in dieser einen ISR verwendet wird, wäre es
>sinnvoll, sie static local zu machen, statt global.

Ähm, wieso static? Dann muss die variable ja auch gehalten werden, wenn 
die ISR nicht läuft.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

chris schrieb:
>>Aber wenn sie wirklich nur in dieser einen ISR verwendet wird, wäre es
>>sinnvoll, sie static local zu machen, statt global.
>
> Ähm, wieso static? Dann muss die variable ja auch gehalten werden, wenn
> die ISR nicht läuft.

Schau Dir die ISR oben an. Der Wert der Variablen muss "gehalten" 
werden, wenn die ISR nicht läuft. Genau das ist der Sinn einer globalen 
Variablen, deshalb hat der TO das ursprünglich auch so gemacht. Den 
gleichen Effekt erzielt man aber auch mit einer static-Variablen. Sie 
"überlebt".

von Oliver (Gast)


Lesenswert?

chris schrieb:
> Ähm, wieso static? Dann muss die variable ja auch gehalten werden, wenn
> die ISR nicht läuft.

Das ist bei einer solchen Zählvariable nunmal unabdingbar.

Oliver

von chris (Gast)


Lesenswert?

>Schau Dir die ISR oben an. Der Wert der Variablen muss "gehalten"
>werden, wenn die ISR nicht läuft. Genau das ist der Sinn einer globalen
>Variablen, deshalb hat der TO das ursprünglich auch so gemacht.

Tschuldigung, ein Versehen von mir. Ich dachte es geht um die allgemeine 
Frage, wie Variablen in der ISR zu definieren sind.

von C-Kritiker (Gast)


Lesenswert?

Lutz schrieb:
> Eigentlich sollte man immer berücksichtigen, warum es volatile gibt:
> Wenn für den Compiler nicht ersichtlich ist, daß sich eine Variable
> ändern kann.

Dafür muß man erstmal die Sichtweise des Compilers kennen. Eigentlich 
ist es doch eine Macke des Compilers, wenn er nicht mal den Klassiker 
erkennt und man, um diese Unzulänglichkeiten zu verdecken, extra ein 
Keyword wie "volatile" einführt.

von (prx) A. K. (prx)


Lesenswert?

C-Kritiker schrieb:

> Dafür muß man erstmal die Sichtweise des Compilers kennen. Eigentlich
> ist es doch eine Macke des Compilers, wenn er nicht mal den Klassiker
> erkennt und man, um diese Unzulänglichkeiten zu verdecken, extra ein
> Keyword wie "volatile" einführt.

Und woher soll ein Compiler wissen, ob eine Variable
- ein I/O-Register darstellt,
- im Adressraum mehrfach gemappt ist (mal cachable mal nicht)
- von einem Interrupt-Handler verändert wird,
- von einem anderen Prozess oder Thread genutzt wird,
- von einem anderen Prozessor oder per DMA genutzt wird?

Nein, das ist allenfalls eine Macke der Sprache, die für diese Konzepte 
keine individuelle Vereinbarung oder entsprechende Detaildeklarationen 
kennt, sondern pauschal "volatile" vorschreibt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

C-Kritiker schrieb:
> Eigentlich ist es doch eine Macke des Compilers, wenn er nicht mal
> den Klassiker erkennt
Woran soll denn der Compiler erkennen, ob z.B. zum entsprechenden 
Zeitpunkt ein Interrupt überhaupt enabled ist.

Früher wars compilerabhängig mal so, dass alle globalen Variablen 
automatisch volatil waren. Erst mit den fortgeschrittenen 
Optimierungsoptionen wurde die Sprachdefinition von C viel mehr auf 
"Schlupflöcher" abgeklopft. Die volatile Geschichte ist nur die 
einfachste Ausprägung, an der die Optimierungsstrategien am deutlichsten 
sichtbar sind.

Fazit: schalt einfach die Optimierung aus, dann macht der Compiler da 
nichts weg...

von Oliver (Gast)


Lesenswert?

C-Kritiker schrieb:
> Eigentlich
> ist es doch eine Macke des Compilers, wenn er nicht mal den Klassiker
> erkennt

C kennt das Konzept "Interrupt" nicht, daher muß ein C-Compiler das auch 
nicht erkennen können.

KLassiker in diesem Zusammenhang sind allerdings vor allem memory-mapped 
Zugriffe auf Register, dis sich alleine ändern (IO-Register, Zähler, 
ADC-Wandler, usw.). Von dem Problem bekommst du nur nichts mit, weil die 
volatile-Deklarationen dafür ihn den avrlibc-headern stehen.

Oliver

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.