Hallo, ich habe ein Verständnisproblem. Laut der Beschreibung in http://www.mikrocontroller.net/articles/Interrupt. Interrupt soll beim Atomarer Datenzugriff ausgeschaltet werden.Z.B.: Wenn 16-Bit Zahl dekrementiert wird? Oder hier " 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. " Gilt es auch für Assemblerprogrammierung oder nur für C? In Assembler kann man bei wenn Interrupt auftitt, den SREG-Register in SRAM sichern. Oder verstehe ich etwas falsch?
Alex schrieb: > Gilt es auch für Assemblerprogrammierung oder nur für C? für beide > In Assembler kann man bei wenn Interrupt auftitt, den SREG-Register in > SRAM sichern. Oder verstehe ich etwas falsch? das macht C auch nicht anders. Aber das Probelm liegt woanders: IN r16,port ISR ORI r16,0x03 ISR OUT port,r16 stellt dir mal vor in den Zeilen ISR tritt ein interupt ein und setzt von dem Port ein bit. Dann wird diesen bit beim out nicht wieder hergestellt.
Hi
> Gilt es auch für Assemblerprogrammierung oder nur für C?
Auch für Assembler.
In Assembler
kann man bei wenn Interrupt auftitt, den SREG-Register in SRAM sichern.
Oder verstehe ich etwas falsch?
Im RAM oder einem dafür reservierten Register.
Die fragen haben aber nichts miteinander zu tun.
MfG Spess
Welches Bit7? Das von r16 oder das vom Port? Falls Port, musst du vor IN r16,port ein cli setzen. Falls r16 musst du in der ISR mit push r16 sichern unt vor reti wieder pop r16 zurückholen
Ein Beispiel: 16-Bit-Zähler verwendet und von 0x00FF auf 0x0100 hochzählt,dann tritt der Interrupt auf. Dieser Zähler wird nicht in der Interrupt-Unterprogramm verwendet. Angenommen es wird nur in Hauptprogramm angewendet. Nach ISR_Verlassen kommr es auch zum Fehler? Oder es wird richtig übergehen?
Peter II schrieb: > Alex schrieb: > Aber das Probelm liegt woanders: > > IN r16,port > ISR > ORI r16,0x03 > ISR > OUT port,r16 > > stellt dir mal vor in den Zeilen ISR tritt ein interupt ein und setzt > von dem Port ein bit. Dann wird diesen bit beim out nicht wieder > hergestellt. Sinniger wäre eventuell das hier:
1 | sbi PORTx,0 |
2 | sbi PORTx,1 |
Zwar werden dann die IO-Leitungen nicht exakt gleichzeitig auf High gesetzt, aber es gibt keine Probleme mit fehlender Atomarität.
Alex schrieb: > Nach ISR_Verlassen kommr es auch zum Fehler? > Oder es wird richtig übergehen? nein da gibt es keine Probleme. Nur wenn eine Resource gleichzeitg in der ISR und dem Rest verwendet wird.
Alex schrieb: > Ein Beispiel: 16-Bit-Zähler verwendet und von 0x00FF auf 0x0100 > hochzählt,dann tritt der Interrupt auf. Wann? Nach dem Addieren oder dabei? > Dieser Zähler wird nicht in der > Interrupt-Unterprogramm verwendet. Angenommen es wird nur in > Hauptprogramm angewendet. Was es? Das Zähler? > Nach ISR_Verlassen kommr es auch zum Fehler? Das hängt von der ISR ab. Siehe unten. > Oder es wird richtig übergehen? An wen? Hier findet keine Übergabe statt. Versuche Dich mal klar auszudrücken. Das ganze hat nichts mit dem Code in Deinem Eingansposting zu tun. Wenn Du mit Übertrag rechnest, und das musst Du bei einem 16 bit Zähler, verlässt Du Dich auf das C-Bit in SREG. Deswegen und weil auch andere Befehle (z.B. bedingte Sprünge) sich auf den korrekten Wert der Bits in SREG verlassen müssen, muss eine ISR das SREG-Register einlesen und zwischenspeichern, um es am Ende restaurieren zu können.
1 | Hochzaehlen: |
2 | subi r16,-1 ; Unteres Byte hochzählen, bei Überlauf C-Flag setzen. |
3 | ; <=ISR-Aufruf |
4 | sbci r17,0 ; Evtl. Übertrag in C-Flag auf oberes Byte übernehmen. |
5 | ret |
6 | |
7 | ISR: |
8 | push r16 |
9 | in r16, SREG |
10 | ... |
11 | ; Befehle, die das C-Flag in SREG ändern |
12 | ... |
13 | out SREG, r16 |
14 | pop r16 |
15 | reti |
Hi Eigentlich gilt: alle in der ISR benutzeten Tegister müssen vorher auf den Stack gelegt werden. Da ist zuerst das Statusregister "SREG". Das wird höchstwahrscheinlich verändert, daher ist es wie bereits geschrieben, auch zwischenzuspeichern. Werden nun noch andere im Programm verwendete Register in der ISR benutzt, z. B. R16, R17 etc. dann sind auch diese auf den Sack abzulegen und später in umgekehrter Reihenfolge wieder herzustellen. Push a Push B Push C .... POP C POP B POP A Dazu braucht es keine Abschaltung der Interrupts. Lediglich beim Schreiben auf den EEProm ist soweit ich's in Erinnerung habe, der Interrupt abzuschalten, weil das "Brennen" etwas länger dauert und nicht unterbrochen werden darf. Gruß oldmax
oldmax schrieb: > Eigentlich gilt: alle in der ISR benutzeten Tegister müssen vorher auf > den Stack gelegt werden. Ja, C-Compiler machen das meisten so. Trotzdem kostet es viel Rechenzeit, was grad bei einer Interrupt-Routine wehtun kann. Wenn man schon in Assembler programmiert, kann man ohne Weiteres zwei oder drei Register von den 32 vorhandenen auswählen und diese NUR in der ISR benutzen. Das SREG sollte man tunlichst sichern, das ist richtig, aber auch dieses braucht man nicht auf den Stack zu legen, man sichert es einfach in ein sonst nicht verwendetes Register. Nicht selten werden ISR dadurch doppelt oder dreimal so schnell durchlaufen, als wenn man alles auf den Stack sichern würde. Jedes PUSH kostet 2 Zyklen, jedes POP ebenfalls.
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.