NMI

Aus C64-Wiki
Wechseln zu: Navigation, Suche

Der NMI (engl.: Non Maskable Interrrupt, zu deutsch: nicht maskierbarer Interrupt) ist wie der IRQ eine Interruptleitung der CPU, die durch den Wechsel auf "low"-Pegel aktiv wird. Im Gegensatz zum IRQ kann der NMI softwaremäßig durch den Assembler-Befehl SEI nicht unterbunden (also nicht maskiert) werden.

Auslösung[Bearbeiten]

Folgende Möglichkeiten bestehen, um einen Übergang auf den Low-Pegel (0) auf der NMI-Leitung zu erzeugen:

  • Über Tastatur durch Drücken von Restore  (0-Pegel wird durch Monoflop erzeugt).
  • Durch entsprechende Programmierung des Interrupt-Kontrollregisters der CIA-Bausteine (Timer CIA2).
  • Extern über den Expansionsport Pin D.
  • Extern über den Userport Pin 3.

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. Die CPU MOS 6510 folgt dem Vektor in $FFFA/$FFFB (normalerweise $FE43, die NMI-Routine des KERNALs). Steckmodule im Ultimax-Modus können diesen Vektor überschreiben.
  4. Es wird zum NMI-Vektor in $0318/$0319 gesprungen (bei $FE44; zeigt normalerweise auf $FE47). Dieser Vektor kann auch von BASIC aus manipuliert werden.
  5. Falls der NMI durch die CIA2 ausgelöst wurde (Check bei $FE4C), wird zu den RS232-Routinen verzweigt ($FE72).
  6. Falls eine Modulkennung im RAM oder Steckmodul-ROM bei $8000 gefunden wird (Aufruf bei $FE56), wird der Vektor an der Stelle $8002/$8003 für die weitere Ausführung herangezogen ($FE5B).
  7. Wurde keine Modulkennung gefunden und ist die RUN/STOP -Taste gedrückt (Prüfung bei $FE61), wird ein BASIC-Warmstart ausgeführt: Es wird zu dem Programmcode verzweigt, der durch den im BASIC-ROM befindlichen Vektor $A002/$A003 referenziert wird ($FE6F).
  8. Ansonsten werden RS232-Routinen ausgeführt und schließlich mit dem Befehl RTI ins unterbrochene Programm zurückgesprungen ($FEC1).

Eigene Interrupt-Service-Routine (ISR) für den NMI[Bearbeiten]

Bei der originalen ISR wird bei Adresse $FE44 im KERNAL der Befehl JMP ($0318) ausgeführt. Hier besteht nun die Möglichkeit, diesen Vektor (LSB = $0318 ; MSB = $0319) "umzubiegen", um eine eigene ISR nutzen zu können. Im ISR-Code muss darauf geachtet werden, dass die CPU-Register unverändert bleiben oder entsprechend zwischenzeitlich gesichert werden. Nichtmaskierbare Interrupts sind zu diesem Zeitpunkt gesperrt (maskiert). Nachdem das Statusregister automatisch am Ende wieder hergestellt wird, erfolgt auch implizit das Aufheben der Interruptmaskierung (sofern dies vor der Unterbrechung der Fall war).

NMI unterdrücken[Bearbeiten]

Trotz des Namens kann der NMI im C64 unterdrückt werden. Hierzu muss man nur dafür sorgen, dass die NMI-Leitung dauerhaft auf Low (0) bleibt, denn der NMI wird als sogenannter edge-sensitve interrupt nur beim Übergang der Leitung von High (1) auf Low (0) ausgelöst und nicht durch den Low-Pegel an sich. Erstellt man also eine eigene NMI-Service-Routine, die nur aus einem RTI besteht (z.B. vorhanden an Adresse $FEC1) und somit den CIA2 nicht zurücksetzt, dann kann man den NMI per CIA2 einmal auslösen und die Leitung bleibt danach auf Low. Die RESTORE-Taste und auch die von Freezern verwendete NMI-Leitung am Expansionsport bleiben dann völlig wirkungslos.

Hardware Vektoren[Bearbeiten]

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

Weblinks[Bearbeiten]