volatile Variablen

OP #4150072
Lesenswert?

Guten Abend,

habe ich mal eine Verständnisfrage:

Wenn eine Variable im Interrupt geändert wird, deklariere ich sie 
volatile.

Wie ist es, wenn eine Variable im Interrupt nur gelesen wird, muss sie 
dann auch volatile sein? Eigentlich nicht, oder?

Danke schon mal.
-Markus
Gast #4150114
Lesenswert?

Ach, das 'volatile' dient NUR dazu, daß der Compiler die von dir 
geschriebenen Zugriffe auf diese so gekennzeichnete Variable nicht 
wegoptimiert, weil er z.B. den Wert von einem früheren Zugriff her noch 
in einem Register hat.

Das ist alles.

Manchmal braucht man sowas auch zum nur schreiben. Es gibt 
Peripherie-Cores, die erst dann weitermachen, wenn man z.B. ihr 
Statusregister ausgelesen hat. Wenn man jedoch sowas ausliest und in 
eine Variable packt, die man garnicht weiter benutzt, dann neigen manche 
Compiler dazu, die ganze Ausleserei wegzuoptimieren. Dagegen hlft dann 
auch das volatile bei der Dummy-Variablen.

W.S.
Gast #4150187
Lesenswert?

>Es ist also schon so, dass bei nur lesendem Zugriff auf das volatile
>verzichtet werden kann.

Nö, bei lesendem Zugriff weiss der Compiler ja nicht
das die Variable in einem Interrupt verändert werden kann.
Wenn das so ist benötigt er das volatile zwingend.
#4150202
Lesenswert?

Markus E. schrieb:
> Es ist also schon so, dass bei nur lesendem Zugriff auf das volatile
> verzichtet werden kann. Ich verwende hier übrigens den AVR-GCC für einen
> ATmega-Controller.

Nein. Es ist genau wie W.S. schrieb:

"das 'volatile' dient NUR dazu, daß der Compiler die von dir
geschriebenen Zugriffe auf diese so gekennzeichnete Variable nicht
wegoptimiert, weil er z.B. den Wert von einem früheren Zugriff her noch
in einem Register hat."

Ob lesend oder schreibend ist dafür völlig egal.

Wenn du z.B. eine Stelle im Code hast wie diese:

while( bFlagWurdeGesetztInterrupt );

Dann optimiert der Compiler wahrscheinlich den lesenden Zugriff auf die 
Variable und liest ihren Wert nicht jedes mal erneut aus dem Speicher 
aus.

Durch die deklaration als "volatile" sagst du dem Compiler, dass er 
nicht optimieren soll und er wird Code erzeugen, der jedes mal erneut 
den Speicher der Variable einlesen und testen wird.

Und natürlich optimiert der Compiler auch nur, wenn die Optimierungen 
überhaupt aktiv sind. (Also z.B. nicht wenn im Atmel-Studio die 
"Debug"-Version aktiv ist.)


Mein Tipp: Wenn du unsicher bist, verwende einfach auf jeden Fall 
"volatile" in der Deklaration. Das kostet ein wenig mehr Speicher und 
Performance, aber ersparrt dir Probleme die du nur ganz schwer als 
"fehlendes volatile" erkennst.

Gruß
Basti
OP #4150257
Lesenswert?

Aus Unsicherheit habe ich schon alle Variablen, die irgendwie in der ISR 
genutzt werden volatile deklariert.

Zum Verständnis habe ich diese Frage hier gestellt.

Wie ist es im umgekehrten Fall, wenn eine Variable in der ISR gelesen 
wird, die nur im Hauptprogramm geändert wird:

ISR(){
while( bFlagWurdeInMainGesetzt );
}

Dann ist für bFlagWurdeInMainGesetzt eigentlich kein volatile nötig, 
oder?

@Gast: Sorry, war mir nicht klar.
Werde für meine nächste Frage eine andere Kategorie wählen.
#4150264
Lesenswert?

Markus E. schrieb:
> ISR(){
> while( bFlagWurdeInMainGesetzt );
> }

So macht das natürlich überhaupt keinen Sinn. Da hast du eine tolle 
Endlosschleife gebaut weil deine main Funktion nie wieder dran kommt und 
das Flag ändern könnte. Wenn du in der ISR eine Variable aber nur einmal 
ließt kann man meiner Meinung nach das volatile weglassen, da mir keine 
Möglichkeit einfällt wie der Compiler den Wert irgendwo sichern könnte. 
Also sowas wie:
1
ISR()
2
{
3
  if(someFlag)
4
    doX();
5
  else
6
    doY();
7
}
Gast #4150267
Lesenswert?

Markus E. schrieb:
> Dann ist für bFlagWurdeInMainGesetzt eigentlich kein volatile nötig,
> oder?

doch, weil sei eventuell im Hauptprogramm gar nicht in dem Ram 
geschrieben wird sondern im Register bleibt.


das volatile ist auch nicht für den code in der ISR sondern für den code 
im Hauptprogramm. Der code in der ISR wird durch das volatile sogar 
schlechter.
Persönliche Seite #4150398
Lesenswert?

Markus E. schrieb:
> wenn eine Variable in der ISR gelesen wird, die nur im
> Hauptprogramm geändert wird:
>
> ISR(){
> while( bFlagWurdeInMainGesetzt );
> }
>
> Dann ist für bFlagWurdeInMainGesetzt eigentlich kein volatile nötig,
> oder?

Doch.

Beispiel:
1
extern unsigned char x;
2

3
void f (void)
4
{
5
    while (1)
6
        x++;
7
}

Das übersetzt avr-gcc korrekt zu
1
f:
2
.L2:
3
  rjmp .L2
Wenn also in einer ISR auf x geprüft wird, wird sich der Wert nie 
ändern.
Persönliche Seite #4150416
Lesenswert?

Sebastian V. O. schrieb:
> Peter II schrieb:
>> doch, weil sei eventuell im Hauptprogramm gar nicht in dem Ram
>> geschrieben wird sondern im Register bleibt.
>
> Gut das könnte natürlich sein. Außer bei konstruierten Beispielen
> aber vermutlich eher unwahrscheinlich, dass eine Variable nie aus
> dem Register in den RAM zurück geschrieben wird.

Selbst wenn sie zurückgeschrieben wird, bedeutet das nicht, dass das 
volatile überflüssig ist.

Beispiel:
1
#include <util/delay.h>
2

3
extern unsigned char count;
4

5
void wait_and_count (void)
6
{
7
    do
8
        _delay_loop_1 (100);
9
    while (++count);
10
}

Wenn nun eine ISR count liest, wird sie nie einen anderen Wert als 0 
erhalten, denn avr-gcc übersetzt das Beispiel zu:
1
wait_and_count:
2
  lds r24,count
3
.L2:
4
  ldi r25, 100
5
1:
6
  dec r25
7
  brne 1b
8
  subi r24, -1
9
  brne .L2
10
  sts count,__zero_reg__
11
  ret
#4150531
Lesenswert?

W.S. schrieb:
> Manchmal braucht man sowas auch zum nur schreiben. Es gibt
> Peripherie-Cores, die erst dann weitermachen, wenn man z.B. ihr
> Statusregister ausgelesen hat. Wenn man jedoch sowas ausliest und in
> eine Variable packt, die man garnicht weiter benutzt, dann neigen manche
> Compiler dazu, die ganze Ausleserei wegzuoptimieren. Dagegen hlft dann
> auch das volatile bei der Dummy-Variablen.

Das volatile muß zwingend zum Register. Bei der Dummy-Variablen hilft es 
nicht unbedingt. Eigentlich braucht man die nicht mal, wenn das Register 
volatile ist. Wenn du die Dummy-Variable volatile machst, sorgt das nur 
dafür, daß diese auf jeden Fall geschrieben wird, aber nicht zwingend, 
daß das Register auch an der Stelle gelesen wird. Wurde das Register 
vorher in der Funktion schon mal gelesen oder geschrieben, kann der 
Compiler auch den alten Wert nochmal hernehmen und in die Dummy-Variable 
schreiben, ohne das Register nochmal zu lesen.

Peter II schrieb:
> das volatile ist auch nicht für den code in der ISR sondern für den code
> im Hauptprogramm. Der code in der ISR wird durch das volatile sogar
> schlechter.

Das volatile ist für beides.

Sebastian V. O. schrieb:
> Peter II schrieb:
>> doch, weil sei eventuell im Hauptprogramm gar nicht in dem Ram
>> geschrieben wird sondern im Register bleibt.
>
> Gut das könnte natürlich sein. Außer bei konstruierten Beispielen aber
> vermutlich eher unwahrscheinlich, dass eine Variable nie aus dem
> Register in den RAM zurück geschrieben wird.

Kann aber je nach Code passieren.

Ralf D. schrieb:
> Für atomare Zugriffe gibts in C kein Schlüsselwort

Doch: http://en.cppreference.com/w/c/atomic

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