bin mir aktuell nicht sicher ob die Zuweisung des Rechenergebnis an wert in loop atomar erfolgen muss?
Es könnte ja sein das während der Zuweisung ein Interrupt auftritt und nur ein Byte statt zwei in wert "übergeben" wurde. Ich war bisher der Meinung das atomarer Zugriff nur notwendig ist wenn wert in einer ISR verändert wird
Ist atomar immer notwendig sobald sobald schreibend oder lesend in einer ISR eine variable benutzt wird oder nur schreibend? Für volatile ja. Für atomar ist die Frage?
Doc_Arduino:
wert "übergeben" wurde. Ich war bisher der Meinung das atomarer Zugriff nur notwendig ist wenn wert in einer ISR verändert wird
Richtig. Innerhalb der ISR sind Interrupts (im Normalfall) gesperrt, so dass der Wert innerhalb der ISR problemlos gelesen werden kann. Wenn die ISR ihn nicht ändert, kann er im loop auch normal belegt werden.
Korrektur: Es kann die Änderung im loopü unterbrochen werden und damit nur 1 Byte gesetzt sein.
Richtig ist: das volatile ist trotzden notwendig.
ich meinte das etwas anders. Quasi der umgedrehte Fall.
Wenn in loop die Zuweisung des Rechenergebnisses an wert stattfindet und wert aus mehreren Bytes besteht, kann dann die ISR diese Zuweisung unterbrechen und sich einen verstümmelten wert holen? Weil die Zuweisung vielleicht? noch nicht abgeschlossen war. Oder wird eine Zuweisung niemals unterbrochen, auch von einer ISR nicht?
@ Microbahner. Mit der Aussage bin ich nicht einverstanden, weil komplett falsch,
Die ISR ändert den Wert von wert ja nicht. Also hat sie auf die Zuweisung keinen Einfluss.
Jetzt wo Du nochmal darauf hinweist: Es könnte aber passieren, dass sie nur einen Teil der Änderung mitbekommt, weil sie zwischendrin liest. Also doch atomar. Ich korrigiere damit meine 1. Aussage.
Doc_Arduino:
Wenn in loop die Zuweisung des Rechenergebnisses an wert stattfindet und wert aus mehreren Bytes besteht, kann dann die ISR diese Zuweisung unterbrechen und sich einen verstümmelten wert holen?
Genau das kann die ISR. Und deshalb muss man das atomar machen - sprich den Interrupt während der Zuweisung unterbinden. Also wenn Du im 'normalen' Programmablauf einen Wert ( mit Size>1Byte ) änderst, den die ISR liest.
Und 'volatile' ist ein Hinweis an den Compiler, dass sich ein Wert auch ausserhalb seines 'sichtbaren Bereiches' ändern kann. Das betrifft dann den Optimieralgorithmus und ist wichtig für alle Werte, die die ISR ändert, und die im normalen Sketch verwendet werden.
genau die Frage ist, kann ein Interrupt eine Mehrbytezuweisung die außerhalb von ihm stattfindet unterbrechen oder nicht? Das wäre die Kurzform meines Anliegens. Ich hatte nochmal hier nachgelesen, wurde aber nicht schlau daraus wie das in meinem Fall ist. https://www.mikrocontroller.net/articles/Interrupt#Interruptfeste_Programmierung
Praktisch kann ja ein Interrupt immer dazwischen funken sobald irgendein Befehl mehr als ein Takt dauert.
Gut, mach ich das atomar. Danke für die schnellen Antworten.
Ich fasse zusammen. volatile und atomar immer, egal ob im Interrupt lesend oder schreibend verwendet.
Kann man sich auch leichter merken ohne nochwas unterscheiden zu dürfen.
@ Microbahner.
Deine erste Antwort ist da leider missverständlich. Ich weiß nicht ob sie allgemeingültig sein sollte oder auf meine Frage direkt zugeschnitten. Wenn allgemeingültig dann wäre sie falsch.
Wenn eine Variable in einer ISR geändert wird (also schreibend), dann muss sie außerhalb der ISR auf jeden Fall atomar behandelt werden. Du sprachst nur vom lesen. Solche Fehler findet man verdammt schwer.
Wenn das in der ISR nur gelesen wird, ist volatile vollkommen überflüssig - es behindert nur den Optimieralgorithmus. Volatile heißt nur, dass sich der Compiler den Wert bei mehrfacher Verwendung immer aus dem RAM holen muss, und ihn nicht in Registern zwischenspeichern kann. Wenn die ISR den Wert nur liest, kann der Compiler den Wert zwischenspeichern, das stört die ISR nicht.
Tommy56:
Du liest einen mehrbytigen Wert im loop und musst das trotzdem atomar tun
Da hast Du allerdings recht, wobei das volatile auch bei 1-bytigen Werten wichtig ist. In meiner Aussage oben fehlte in der Tat also noch eine Zeile.
Volatile: Wenn die Variable in beiden vorkommt.
Atomar: wenn die Variable grösser 1 byte ist , in der ISR geschrieben wird und ausserhalb gelesen wird.
Allerdings bei einem 8266 oder ESP32 erfogt da der Lesezugriff auch byteweise je Takt. Wenn nein dann wäre ja Atomar nicht notig ?
Doc_Arduino:
@ Microbahner.
Deine erste Antwort ist da leider missverständlich. Ich weiß nicht ob sie allgemeingültig sein sollte oder auf meine Frage direkt zugeschnitten. Wenn allgemeingültig dann wäre sie falsch.
Zumindest unvollständig, und damit allgemein gesehen falsch. Also nochmal:
Atomar: Du verwendest einen (mehrbytigen) Wert, der auch in der ISR verwendet wird.
Werte die die ISR nur liest, kann man auch außerhalb der ISR nichtatomar lesen.
Volatile: Du liest einen Wert, der in der ISR geändert wird ( egal ob ein- oder mehrbytig ).
MicroBahner:
Dann würden meine MobaTools vorn und hinten nicht funktionieren.
Vielleicht solltet ihr nochmal drüber nachdenken
Ich habe da reichlich drüber nachgedacht!
Variablen, Strukturen, müssen als volatile deklariert werden, wenn auf sie von mehr als einem "Programmstrang" zugegriffen wird.
z.B. Hauptprogramm und ISR
Oder auch bei 2 Kern µC, wie dem ESP32 oder K210.
Egal, wer liest oder schreibt
"Atomic", muss sein, wenn der Zugriff auf die Daten mehr als 1 Asm Statment benötigt, also unterbrochen werden könnte.
Egal, wer liest oder schreibt, alle diese Zugriffe müssen verriegelt werden.
Da in AVR ISR die Interrupts sowieso erstmal gesperrt sind, meist nur im Hauptprogramm.
Anders siehts wieder bei Multicore aus.
atomar ist geklärt.
Ich war bis heute leider immer nur bei Veränderung in einer ISR (oder außerhalb des Programmflusses) davon ausgegangen, eben dann atomar verwenden zu müssen. Ab jetzt auch bei Lesezugriffen in einer ISR (oder außerhalb des Programmflusses).
Wenn in der ISR nur gelesen wird - der Wert wird eh neu aus dem Speicher ausgelesen - da zuvor nicht bekannt ist, was in den Registern steht, müssen eh sämtliche Variablen neu geholt werden.
Da sehe ich nur Nachteile, hier volatile zu benutzen (wobei ich Das bis Jetzt wohl gemacht hätte) - der eigentliche Sketch 'kennt' ja Seinen Variablenwert und kann Diesen auch 'so lange, wie's halt dauert' in Registern halten - die ISR ändert Da ja Nichts dran.
Sobald die ISR was schreibt, muß der Wert im Sketch selber immer neu gelesen werden - kann sich ja IMMER geändert haben.
Da der Wert der Variable nicht in den Registern gehalten werden KANN, braucht eine volatile Variable deutlich länger (nur, wen nSie nicht eh neu gelesen wird, da Sie schon 'ewig' nicht mehr in Gebrauch war - 32 Register mit je einem Byte reichen auch nicht für Alles - auch haben einige der Register besondere Funktionalitäten - zumindest bei den AVR.
Wenn in der ISR nur gelesen wird - der Wert wird eh neu aus dem Speicher ausgelesen - da zuvor nicht bekannt ist, was in den Registern steht, müssen eh sämtliche Variablen neu geholt werden.
Da sehe ich nur Nachteile, hier volatile zu benutzen.....
Wenn das Hauptprogramm optimierend kompiliert wird, muss die Variable volatile sein, damit das Hauptprogramm sie "wirklich" in den Speicher schreibt.
Sonst steht alter Müll im Speicher, welcher dann von der ISR gelesen wird.
Doc_Arduino:
genau die Frage ist, kann ein Interrupt eine Mehrbytezuweisung die außerhalb von ihm stattfindet unterbrechen oder nicht? Das wäre die Kurzform meines Anliegens. Ich hatte nochmal hier nachgelesen, wurde aber nicht schlau daraus wie das in meinem Fall ist. Interrupt – Mikrocontroller.net
Praktisch kann ja ein Interrupt immer dazwischen funken sobald irgendein Befehl mehr als ein Takt dauert.
Gut, mach ich das atomar. Danke für die schnellen Antworten.
Ein Befehl wird üblicherweise nicht unterbrochen durch einen Interrupt. Der wird erst nach Ende des einen Befehls abgearbeitet.
Ein Befehl ist aber der ASM-Befehl des C. Wenn Du also z.B. auf einem AVR mit einen der 16Bit-Befehle einen 16Bit-Wert aus dem Ram holst, bleibt der ungestört. Wenn Du aber mit Byte-Befehlen die Teilwerte holst und zusammenbastelst, kannst er nach jeder ASM-Anweisung gestört werden.
Atomar sperrt letztlich nur die Interrupts bis zum Ende des Blocks.
Du kannst auch selbst das Statusregister zwischenspeichern, die Interrupts sperren , Deinen Kram machen und das Statusregister zurückschreiben. Das geht so aber nur bei AVR, das Problem ist, ein CLU() vor und SEI() nach dem Block alleine kann den gesetzten IRQ-Zustand ändern. Wenn der vorher gesperrte war, wäre er danach erlaubt... Deshlab die atomic-Geschichte, die kümmert sich um die Spezialitäten der jeweiligen Architektur.