Forum: Mikrocontroller und Digitale Elektronik volatile Frage


von Jens (Gast)


Lesenswert?

Wenn mit einer Variable in einem Interrupt gearbeitet wird, sprich die 
Variable inkrementiert wird, muss diese dann auch volatile sein oder 
nur, wenn wirklich die Variable auch irgendwo anders im main verwendet 
wird?

Ich denke, dass erstere macht keinen Sinn, die Variable im Interrupt 
alleine als volatile zu setzen.

von Adam P. (adamap)


Lesenswert?

Wenn du die Variable auch außerhalb nutzt.

von Jens (Gast)


Lesenswert?

danke

von Jens (Gast)


Lesenswert?

Sorry, nochmals konkret

b ist die Variable, die im Interrupt inkrementiert wird.

im main passiert Folgendes:

a = b;


Sie wird zwar nicht verändert aber gelesen. Muss b immer noch nicht 
volatile sein?

von Jonas (Gast)


Lesenswert?

Dann ist b ja irgendwo im Main deklariert und muss meiner Meinung nach 
volatile sein.

von Jonas (Gast)


Lesenswert?

Jonas schrieb:
> Dann ist b ja irgendwo im Main deklariert und muss meiner Meinung
> nach
> volatile sein.

Global deklariert wollte ich sagen.

von Dirk B. (dirkb2)


Lesenswert?

b sollte dann global sein.
Dann ist b einmal deklariert. Als volatile, da sie ja woanders geändert 
wird.

von M.A. S. (mse2)


Lesenswert?

Jonas schrieb:
> Dann ist b ja irgendwo im Main deklariert und muss meiner Meinung nach
> volatile sein.

Muss es.
Andernfalls ginge der Compiler davon aus, dass die Variable nicht 
verändert werden kann und würde evtl. die beabsichtigte Funktionalität 
wegoptimieren.

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


Lesenswert?

Jens schrieb:
> Sie wird zwar nicht verändert aber gelesen. Muss b immer noch nicht
> volatile sein?
Besser, du deklarierst b als volatile, denn sonst könnte es sein, dass 
im main() die Variable nur 1x eingelesen und dann mit der lokalen Kopie 
weitergearbeitet wird.

Du sagst dem Compiler mit volatile, dass die Variable sich ausserhalb 
der Routine ändern kann (wie z.B. ein Hardwarezähler oder ein 
Statusflag). Und genau das passiert mit deiner Variablen ja auch.

: Bearbeitet durch Moderator
von Jens (Gast)


Lesenswert?

ok vielen Dank

eine andere Frage noch:

volatile uint16_t a, b, c;

gilt volatile nun nur für a oder für alle Variablen?

von Falk B. (falk)


Lesenswert?

Jens schrieb:
> ok vielen Dank
>
> eine andere Frage noch:
>
> volatile uint16_t a, b, c;
>
> gilt volatile nun nur für a oder für alle Variablen?

Für alle.

von foobar (Gast)


Lesenswert?

> volatile uint16_t a, b, c;

Warning: bei AVR sind Zugriffe auf uint16 nicht atomar, ein volatile 
alleine reicht nicht.

Siehe auch 
https://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff

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


Lesenswert?

foobar schrieb:
> Warning: bei AVR sind Zugriffe auf uint16 nicht atomar
Bei einem STM32 dagegen schon...   ;-)
Man kann das i.A. auf alle Architekturen ausdehnen, in denen die 
Prozessorwortbreite (oder ggfs. auch nur die Busbreite) nicht zur Breite 
der Variablen passt.

Und ich hatte letzthin auch den Fall, da meinte sogar auf einem 
32-Bit-System mit 32 Bit Bus der Compiler, es wäre schlauer, die 4 
nötigen Bytes des Integers nacheinander einzeln einzulesen. Und sich 
dabei vom Interrupt unterbrechen zu lassen...   :-O

: Bearbeitet durch Moderator
von Einer K. (Gast)


Lesenswert?

Lothar M. schrieb:
> es wäre schlauer, die 4
> nötigen Bytes des Integers nacheinander einzeln einzulesen.

Naja....
Bei einem Misalignment kann das schon sein, aber sonst eher unüblich.

von Jens (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Lothar M. schrieb:
>> es wäre schlauer, die 4
>> nötigen Bytes des Integers nacheinander einzeln einzulesen.
>
> Naja....
> Bei einem Misalignment kann das schon sein, aber sonst eher unüblich.

-Wie meinst du das mit Misalignment? Kannst du ein Beispiel geben?
Vielen Dank

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> da meinte sogar auf einem
> 32-Bit-System mit 32 Bit Bus der Compiler, es wäre schlauer, die 4
> nötigen Bytes des Integers nacheinander einzeln einzulesen.

Lass mich raten: Der Integer war in einem struct, welcher mit "packed" 
markiert war, und du hast -mno-unaligned-access angegeben :-)

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


Lesenswert?

Niklas G. schrieb:
> Lass mich raten: Der Integer war in einem struct, welcher mit "packed"
> markiert war, und du hast -mno-unaligned-access angegeben :-)
Nein, es war komplizierter und hing auch noch vom Optimierungsgrad ab. 
Bei der Debug-Version trat der Fehler "zum Glück" nicht auf  :-/
OK, es war eigentlich ein Compilerfehler vereinfacht nur in dem Sinn, 
dass er auf ein nicht-cachefähiges Statuswort wie auf eine 
RAM-Speicherzelle zugriff. Und dann natürlich 4 Zugriffe statt nur 1 auf 
das Statusregister machte.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Bei der Debug-Version trat der Fehler "zum Glück" nicht auf  :-/

Ja, diese Fehler machen am meisten Spaß!

Lothar M. schrieb:
> Und dann natürlich 4 Zugriffe statt nur 1 auf
> das Statusregister machte.

Aber wieso? Klingt komisch, eigentlich sollten Compiler so etwas nur tun 
um unaligned Speicherzugriffe zu vermeiden.

von Einer K. (Gast)


Lesenswert?

Jens schrieb:
> -Wie meinst du das mit Misalignment? Kannst du ein Beispiel geben?
Lesetipp: https://de.wikipedia.org/wiki/Speicherausrichtung

von Doof (Gast)


Lesenswert?

1. Der Sinn von volatile ist es, den Compiler darüber zu informieren, 
dass sich der Inhalt einer Speicherstelle ändern kann, ohne dass es für 
den Compiler aus dem Programmablauf ersichtlich ist. Ansonsten darf der 
Compiler Deinen Code nach Belieben so optimieren, solange der für ihn 
ersichtliche Programmablauf gewahrt bleibt.
Mit volatile sagst Du dem Compiler: "Pass auf, das Ding kann sich 
jederzeit ohne Dein Zutun verändern."

2. Atomarer Zugriff bedeutet, dass der Inhalt einer Variable während des 
Zugriffs nicht verändert wird. Das ist dann relevant, wenn ein Zugriff 
mehr als einen Maschinenbefehl benötigt und sich der Inhalt der Variable 
zwischen den Maschinenbefehlen ändern kann (z.B. weil es ein 
HW-Rergister ist oder weil ein Interrupt dazwischen kommt).
Atomarer Zugriff wird erreicht, indem bestimmt Zugriffsprotokolle 
vorhanden sein müssen, die eingehalten werden.
Z.B. HW-Register in einer bestimmten Reihenfolge lesen, oder z.B. 
Variablen aus Interrupt-Service-Routinen nur unter Interruptsperre lesen 
etc.

von Dergute W. (derguteweka)


Lesenswert?

Arduino Fanboy D. schrieb:
> Jens schrieb:
>> -Wie meinst du das mit Misalignment? Kannst du ein Beispiel geben?
> Lesetipp: https://de.wikipedia.org/wiki/Speicherausrichtung

tl;dr
1
bla = *((int32_t*)0x87654321);

Gruss
WK

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.