IRQ

Aus C64-Wiki
Wechseln zu: Navigation, Suche

Der IRQ (Interrupt ReQuest oder maskierbarer Interrupt) ist wie der NMI eine Interruptleitung der CPU, die "low"-aktiv ist. Im Gegensatz zum NMI kann sich ein Programm durch Setzen des Interrupt-Flags mit dem Assembler-Befehl SEI gegen eine IRQ-Anforderung schützen (maskieren) und zu einem späteren Zeitpunkt eine Unterbrechung wieder mit dem Assembler-Befehl CLI zulassen.

Der Programmteil, der einen IRQ abarbeitet, wird Interrupt Service Routine (ISR) genannt.

Auslösung[Bearbeiten]

Folgende Möglichkeiten bestehen, um einen Low-Pegel (0) auf der IRQ-Leitung zu erzeugen.

Das Signal an der IRQ-Leitung wird ab dem 2. Takt bis zum letzten Takt einer Instruktion erkannt.
Unter gewissen Situationen können IRQ-Anforderungen auch verworfen werden, wenn nämlich gleichzeitig ein NMI ansteht.[1]

Das Löschen des I-Flags führt üblicherweise dazu, dass eine etwaige bereits wieder anstehende Anforderung zu berücksichtigen ist. Das passiert aber bei den das I-Flag manipulierenden Instruktionen zu unterschiedlichen Zeitpunkten:[2]

  • RTI: unmittelbar nach dem RTI kann bereits zu einer IRQ-Routine verzweigt werden, weil schon während dessen der Status der IRQ-Leitung berücksichtigt wird.
  • CLI, PLP, SEI: Hier wird erst in der folgenden Instruktion der Status der IRQ-Leitung überprüft und damit die folgende Instruktion noch abgearbeitet bevor sich der IRQ auswirkt.

Ablauf[Bearbeiten]

  1. Es wird zunächst der laufende Befehl zu Ende abgearbeitet.
  2. Der Programmzähler (PC) des unterbrochenen Programms wird auf den Stapel abgelegt.
  3. Das Statusregister wird auf den Stapel gelegt und anschließend das Interrupt-Flag gesetzt, was eine neuerliche Unterbrechung der ISR selbst verhindert.
  4. Der Hardware-Vektor $FFFE/$FFFF wird angesprungen (zeigt beim normalen C64-KERNAL auf Adresse $FF48).
  5. Die Interrupt-Service-Routine ab $FF48 wird abgearbeitet.
  6. mit dem Befehl RTI folgt der Rücksprung ins unterbrochene Programm.

ISR des KERNAL[Bearbeiten]

  • im Gegensatz zur NMI-Routine werden die Register gesichert:
 $FF48 PHA          ; Akku sichern
 $FF49 TXA 
 $FF4A PHA          ; X-Register sichern
 $FF4B TYA
 $FF4C PHA          ; Y-Register sichern
$FF4D TSX          ; Stapelzeiger ins X-Register
$FF4E LDA $0104, X ; Break-Flag vom Stapel holen
$FF51 AND #$10     ; und testen
$FF53 BEQ $FF58    ; nicht gesetzt
$FF55 JMP ($0316)  ; Break-Routine $FE66
  • Sprung in die IRQ-Routine:
$FF58 JMP ($0314)  ; IRQ-Routine $EA31
  • Standard IRQ-Routine:
$EA31 ...
$EA34 ...
...
...
$EA81 PLA
$EA82 TAY          ; Y-Register wiederherstellen
$EA83 PLA
$EA84 TAX          ; X-Register wiederherstellen
$EA85 PLA          ; Akkumulator wiederherstellen
  • mit dem Befehl RTI folgt der Rücksprung ins Hauptprogramm:
$EA86 RTI          ; Rücksprung ins Hauptprogramm

Eigene ISR[Bearbeiten]

Bei der originalen ISR wird bei Adresse $FF58 der Befehl JMP ($0314) ausgeführt. Hier besteht nun die Möglichkeit, diesen Vektor (LSB = $0314 ; MSB = $0315) "umzubiegen", um in eine eigene ISR springen zu können (siehe Beispielprogramm). Alternativ muss bei ausgeblendetem ROM direkt die Adresse der eigenen Interrupt-Service-Routine an den Vektor $FFFE/$FFFF geschrieben werden.

Hardware Vektoren[Bearbeiten]

Vektor-Name Hardware Vektor Adresse
NMI $FFFA / $FFFB $FE43
Reset $FFFC / $FFFD $FCE2
IRQ $FFFE / $FFFF $FF48


Weblinks[Bearbeiten]


Referenzen

  1. nesdev.com-Wiki: CPU interrupts: Detailed interrupt behavior Sprache:englisch
  2. nesdev.com: CPU Interrupts: Delayed IRQ responses ... Sprache:englisch