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
:
Verschoben durch Moderator
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.
Danke mal für die Anwort. 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.
>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.
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
Im Debug ist doch O1 standardmäßig eingeschaltet! Und es hinder dich doch niemand auf Os oder O2 zu gehen!
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.
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 | }
|
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.
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.
Immer und immer und immer wieder: volatile hat nix mit atomar zu tun! Für atomare Zugriffe gibts in C kein Schlüsselwort - da hilfts auch nichts, den Sourcecode mit x-fach redundantem volatile zuzupflastern.
:
Bearbeitet durch User
Ralf D. schrieb: > volatile hat nix mit atomar zu tun! schön und gut, aber wo kam denn in den thread atomar vor?
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.
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 |
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
Beim Lesen des threads kam mir diese Geschichte in den Sinn: http://www.ariva.de/forum/Ephraim-Kishon-Juedisches-Poker-250692
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.