Forum: Mikrocontroller und Digitale Elektronik Interrupt in Assemblerprogramierung


von Alex (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

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

von Jürgen (Gast)


Lesenswert?

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

von Alex (Gast)


Lesenswert?

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?

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von bitte löschen (Gast)


Lesenswert?

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

von oldmax (Gast)


Lesenswert?

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

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

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
Noch kein Account? Hier anmelden.