http://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff Ich lese in diesem Artikel dass man bei Interupts sehr vosichtig sein soll da atomare Datenzugriffe bei einem auftretenden Interupt nicht das gewünschte Ergebnis bringen können. Anderseits ist es doch die Aufgabe einer ISR möglichst am Prozesserstatus und an den Registern nichts zu verändern. Kann also eigentlich nicht sein. Wenn ich mir ein .lss File anschaue wird dort in der ISR auf Maschinenebene doch einiges an Registern gepusht und gepoppt, und zwar offensichtlich abhängig davon welche Optimierungsstufe eingeschaltet ist und (bei Optimierung) bei welchen Registern es sich überhaupt lohnt (wenn sie anderweitig zum Einsatz kommen). Genaueres weiss ich leider nicht da ich in Assembler nichts verstehe. Das würde bei kleinerem Code der wenig Register braucht auch auf eine schnellere ISR hinauslaufen. Einfach ausgedrückt: ein AVR, mit Interrupt betrieben, würde ja bei beliebigen einfachen Code c = a + b potentiell Fehler liefern. Anders herum müsste ich ja für jede C-Zeile die Interrupt-geschützt ausgeführt werden soll mit einem cli() / sei() einhüllen. Ein Ding der Unmöglichkeit. Kann also eigentlich nicht sein, oder doch? Vielleicht kann sich ein Wissender (oder auch mehr) dazu äussern?
Wenn du sämtliche Variablen des Hauptprogramms in der ISR anzusprechen gedenkst, dann gibts viel Arbeit. Aber warum hast du das vor?
isidor schrieb: > Einfach ausgedrückt: ein AVR, mit Interrupt betrieben, würde ja bei > beliebigen einfachen Code c = a + b potentiell Fehler liefern. nein, nur wenn a oder b > 8bit sind um in der ISR geändert werden.
Oder wenn c > 8bit ist und in der ISR mindestens gelesen wird.
An alle: Der Autor signalisiert ja ein seiner Code-Beispielzeile dass es sich nicht um den (nicht-)Schutz von Variablen handelt sondern eben um Registerinhalte.
A. K. schrieb: > Wenn du sämtliche Variablen des Hauptprogramms in der ISR anzusprechen > gedenkst, dann gibts viel Arbeit. Aber warum hast du das vor? Davon war nicht die Rede. Siehe Variable vs Register.
isidor schrieb: > Ich lese in diesem Artikel dass man bei Interupts sehr vosichtig sein > soll da atomare Datenzugriffe bei einem auftretenden Interupt nicht > das gewünschte Ergebnis bringen können. Ich nicht, kannst Du die Passage mal zitieren? Nur, wenn man sich nicht sicher ist, sollte man den Zugriff auf Interruptvariablen im Main atomar kapseln.
isidor schrieb: > Der Autor signalisiert ja ein seiner Code-Beispielzeile dass es > sich nicht um den (nicht-)Schutz von Variablen handelt sondern > eben um Registerinhalte. C kennt keine Register. Man es gibt auch keine Grund sich um Register zu kümmern, wenn man C programmiert.
isidor schrieb: > Davon war nicht die Rede. Du hattest Sorgen, jede Zeile deines Programs schützen zu müssen. Nochmal: weshalb? Teilt jede Zeile deines Programms Variablen mit der ISR? > Siehe Variable vs Register. Der Begriff "Variable" kommt bei dir überhaupt nicht vor. Ich vermute mal, dass du etwas missverstanden hast. Wie schon skizziert wurde geht es nur um Variablen und I/O-Register, die in Hauptprogramm und ISR angesprochen werden. Die ISR wird kein Prozessorregister verändern. Daten, die nicht geteilt werden, sind sicher.
:
Bearbeitet durch User
Peter II schrieb: > isidor schrieb: >> Einfach ausgedrückt: ein AVR, mit Interrupt betrieben, würde ja bei >> beliebigen einfachen Code c = a + b potentiell Fehler liefern. > > nein, nur wenn a oder b > 8bit sind um in der ISR geändert werden. Auch dann wenn sie in der ISR gelesen werden und in einer niedrigeren ISR-Ebene verändert werden. isidor schrieb: > Ich lese in diesem Artikel dass man bei Interupts sehr vosichtig sein > soll da atomare Datenzugriffe bei einem auftretenden Interupt nicht > das gewünschte Ergebnis bringen können. Du meinst wohl nicht-atomar? Bzw. Nicht-atomare Operationen? > Anderseits ist es doch die Aufgabe einer ISR möglichst am > Prozesserstatus und an den Registern nichts zu verändern. Streiche das "möglichst". Die Aufgabe eine ISR definiert du. Es ist Aufgabe des Compilers (oder von dir im Falle einer (Inline)-Assember-ISR) den Prozessor-Status und nicht-globale Register effektiv nicht zu ändern, d.h. zu sichern und wieder herzustellen. Globale Register darf der Compiler nicht restaurieren, denn sonst wären sie nicht global. In der Standard-Konfiguration bzw. ABI von avr-gcc gibt es übrigens keinen globalen Register. > Wenn ich mir ein .lss File anschaue wird dort in der ISR auf > Maschinenebene doch einiges an Registern gepusht und gepoppt, und > zwar offensichtlich abhängig davon welche Optimierungsstufe > eingeschaltet ist und (bei Optimierung) bei welchen Registern es > sich überhaupt lohnt (wenn sie anderweitig zum Einsatz kommen). Evtl. speichert avr-gcc mehr als nötig, was aber ein Problem der Effizienz ist und nicht der Korrektheit. > Einfach ausgedrückt: ein AVR, mit Interrupt betrieben, würde ja bei > beliebigen einfachen Code c = a + b potentiell Fehler liefern. Es kommt auf die Verwendung und die Speicherklasse von a, b und c an. Generell gilt folgende Regel: Falls 1) Auf mindestens eine ISR-Ebene das Datum geschrieben wird und 2) Das Datum auf einer anderen Ebene gelesen wird als geschrieben dann muss die niedrigere ISR-Ebene ihre Zugriffe atomar machen. Dies gilt auch für mehr als eine ISR-Ebene (dann für alle Paare an ISR-Ebenen) oder auch ohne Interrupts in Multi-Core Controllern. Dem Hauptprogramm ist in diesem Sinne auch eine ISR-Ebene zugeordnet, nämlich die niedrigste. In Multi-Core Umgebung spielt die Interrupte-Ebene keine Rolle, es sei denn, es handelt sich um Core-lokale Daten. Auf einem 8-Bit µC sind 8-Bit Lese- und Schreiboperationen i.d.R atomar, es gibt jedoch auch Ausnahmen wie ein 8-Bit Bitfeld welches eine 8-Bit-Grenze überschreitet. Arithmetische Operationen auf den Daten sind i.d.R nicht atomar, d.h. auch wenn die Operanden von +, -, *, /, &, |, ^, ==, etc. atomar gelesen und geschrieben werden können, ist die Gesamtoperation i.d.R. nicht-atomar. Beispiel zur Umsetzung von atomaren Speicher-Operationen sind die bei manchen AVR Xmega existierenden Befehle LAC, LAS, LAT mit denen sich 8-bittige, atomare AND, OR und XOR implementieren lassen.
Peter Dannegger schrieb: > Ich nicht, kannst Du die Passage mal zitieren? Hier steht es doch: -------------------Start Zitat------------------------------------ Beispiel: port |= 0x03; übersetzt sich auf AVR-Prozessoren in IN r16,port ORI r16,0x03 OUT port,r16 Wenn nun zwischen IN und OUT ein Interrupt auftritt, der beispielsweise Bit 7 verändert, dann geht mit dem OUT-Befehl diese Änderung verloren, da der OUT-Befehl den alten Zustand vor dem Interrupt wiederherstellt. Gefährlich ist das insbesondere deshalb, weil der Fall nur selten auftritt und dieses Verhalten sehr schlecht reproduzierbar ist. -------------------Ende Zitat------------------------------------ Nimmt man dies Aussage wörtlich dann findet sich in praktisch jeder C-Zeile die Chance dass die Operation bei Interrupt nicht korrekt ausgeführt wird. Und zwar nicht dadurch dass eine Variable verändert wird sondern dass durch "geschrottete" Registerinhalte die Operation fehlerhaft wird.
isidor schrieb: > port |= 0x03; > > übersetzt sich auf AVR-Prozessoren in > > IN r16,port > ORI r16,0x03 > OUT port,r16 zum glück kann man das ja auch anders schreiben, was in den meisten Fälle auch geht.
1 | port |= 0x02; |
2 | port |= 0x01; |
das ist dann sogar schneller.
isidor schrieb: > Einfach ausgedrückt: ein AVR, mit Interrupt betrieben, würde ja bei > beliebigen einfachen Code c = a + b potentiell Fehler liefern. Nur wenn a, b oder c sowohl in der ISR, als auch außerhalb davon benutzt wird und der Zugriff darauf außerhalb der ISR nicht atomar erfolgt. Zitat aus dem von dir verlinkten Artikel: ********************************** Alle Variablen, Steuerregister und I/O-Ports, die sowohl im Hauptprogramm als auch in Interrupts verwendet werden, sind mit viel Sorgfalt zu behandeln. ********************************** > Anders herum müsste ich ja für jede C-Zeile die Interrupt-geschützt > ausgeführt werden soll mit einem cli() / sei() einhüllen. Ja. > Ein Ding der Unmöglichkeit. Es gibt meist nur wenige Zeilen, die tatsächlich Interrupt-geschützt sein müssen. isidor schrieb: > -------------------Start Zitat------------------------------------ > Beispiel: > > port |= 0x03; > > übersetzt sich auf AVR-Prozessoren in > > IN r16,port > ORI r16,0x03 > OUT port,r16 > > Wenn nun zwischen IN und OUT ein Interrupt auftritt, der beispielsweise > Bit 7 verändert, dann geht mit dem OUT-Befehl diese Änderung verloren, > da der OUT-Befehl den alten Zustand vor dem Interrupt wiederherstellt. Es handelt sich hier also um ein Register, das sowhohl in der ISR, als auch außerhalb verwendet wird. > Nimmt man dies Aussage wörtlich dann findet sich in praktisch jeder > C-Zeile die Chance dass die Operation bei Interrupt nicht korrekt > ausgeführt wird. Nein. Nochmal: Nur bei Zugriff auf die I/O-Register und Variablen, die sowohl in der ISR, als auch außerhalb verwendet werden. > Und zwar nicht dadurch dass eine Variable verändert wird sondern dass > durch "geschrottete" Registerinhalte die Operation fehlerhaft wird. Das Register ist letztendlich auch nichts anderes, als eine Variable.
>> das ist dann sogar schneller. > >Themaverfehlung. Setzen. Sechs. Nein, du hast nur nicht verstanden wieso;)
isidor schrieb: > Und zwar nicht dadurch dass eine Variable verändert > wird sondern dass durch "geschrottete" Registerinhalte die Operation > fehlerhaft wird. >> Wenn nun zwischen IN und OUT ein Interrupt auftritt, der beispielsweise >> Bit 7 verändert, dann geht mit dem OUT-Befehl diese Änderung verloren, >> da der OUT-Befehl den alten Zustand vor dem Interrupt wiederherstellt. Es geht um die Veränderung von Bit 7 des dort "port" genannten I/O-Registers. Nicht eines Prozessorregisters.
Rolf Magnus schrieb: > Nein. Nochmal: Nur bei Zugriff auf die I/O-Register und Variablen, die > sowohl in der ISR, als auch außerhalb verwendet werden. ja Danke! Das ist der Punkt bzw die Auflösung. Darauf kommt es an. Da ich solche Fehler nie gemacht habe ist mir dieser feine Unterschied nicht aufgefallen. Also stimmt ihr mit mir überein das der GCC in ISRs alle in einem Programm benutzen Register sichert und bei Verlassen wieder restauriert (so "wie es sich gehört")?
isidor schrieb: > Also stimmt ihr mit mir überein das der GCC in ISRs alle in einem > Programm benutzen Register sichert und bei Verlassen wieder > restauriert (so "wie es sich gehört")? Alle Prozessorregister. Deine Verwirrung kommt möglicherweise davon, dass der Artikel auch I/O- und Steuer-Register erwähnt.
isidor schrieb: > Also stimmt ihr mit mir überein das der GCC in ISRs alle in einem > Programm benutzen Register sichert und bei Verlassen wieder > restauriert (so "wie es sich gehört")? Ja. Du mußt hier eben sauber unterscheiden zwischen den Prozessorregistern der ALU und den I/O-Register. Die ersteren existieren auf C-Ebene nicht, und der Compiler kümmert sich automatisch darum. Die I/O-Register dagegen sind Ressourcen, die letztendlich wie globale Variablen zu handhaben sind.
Rolf Magnus schrieb: > Ja. Du mußt hier eben sauber unterscheiden zwischen den > Prozessorregistern der ALU und den I/O-Register. Die ersteren existieren > auf C-Ebene nicht, So habe ich das schon gemeint, nur die passende, allumfassende Formulierung dafür auf die Schnelle nicht gefunden. Natürlich sind die Prozessor-Register gemeint ....
isidor schrieb: > Also stimmt ihr mit mir überein das der GCC in ISRs alle in einem > Programm benutzen Register sichert und bei Verlassen wieder > restauriert (so "wie es sich gehört")? Das hab ich oben bereits geschrieben. Hilft aber nix wenn du es nicht liest.
Ich verstehe die ganze Diskussion nicht. Es gehört doch zu den Grundlagen der ISR Programmierung das man als Programmierer berücksichtigen muss das Zugriffe auf Variablen (was letzten Endes Speicherzellen sind) die sowohl in der ISR als auch im Hauptprogramm manipuliert werden besonders behandelt werden müssen. SFR's sind wie hier ja bereits angesprochen nichts anderes als Variablen mit speziellem HW Bezug.
isidor schrieb: > Peter II schrieb: >> das ist dann sogar schneller. > > Themaverfehlung. Setzen. Sechs. wenn Du mal etwas älter bist und etwas mehr Ahnung hast kannst du dir solche Ausdrücke erlauben. Dann macht man es aber nicht mehr weil man a) weiß dass Peter recht hat und b) man es nicht mehr nötig hat (haben sollte) Sprüche zu klopfen
:
Bearbeitet durch User
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.