Muss Variable auch volatile sein, wenn sie NUR in ISR verwendet wird?

OP #2354152
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!
Moderator Persönliche Seite #2354161
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
Gast #2354163
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.
#2354169
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.
Gast #2354227
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.
Moderator Persönliche Seite #2354232
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".
Gast #2354460
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.
Gast #2354482
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.
#2354486
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.
Moderator (Firma: Titel) Persönliche Seite #2354493
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...
Gast #2354522
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

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