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.
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?
Dann ist b ja irgendwo im Main deklariert und muss meiner Meinung nach volatile sein.
Jonas schrieb: > Dann ist b ja irgendwo im Main deklariert und muss meiner Meinung > nach > volatile sein. Global deklariert wollte ich sagen.
b sollte dann global sein. Dann ist b einmal deklariert. Als volatile, da sie ja woanders geändert wird.
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.
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
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?
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.
> 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
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
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.
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
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 :-)
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.
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.
Jens schrieb: > -Wie meinst du das mit Misalignment? Kannst du ein Beispiel geben? Lesetipp: https://de.wikipedia.org/wiki/Speicherausrichtung
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.