NMI

Aus C64-Wiki
Zur Navigation springenZur Suche springen

Der NMI (engl.: Non Maskable Interrupt, zu deutsch: nicht maskierbarer Interrupt) ist wie der IRQ eine Interruptleitung der CPU. Im Gegensatz zum IRQ wird ein NMI nur bei einem Wechsel der Leitung auf "low"-Pegel ausgelöst und lässt sich softwaremäßig durch den Assembler-Befehl SEI nicht unterbinden (also nicht maskieren).

Auslösung[Bearbeiten | Quelltext 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).
  • Durch eine fallende Flanke auf Leitung FLAG2 des Userports, sofern der CIA2 entsprechend konfiguriert ist.
  • Extern über den Expansionsport Pin D.

Das Signal an der NMI-Leitung wird ab dem 2. Takt bis zum letzten Takt einer Instruktion erkannt.

Eine zeitgleich mit einer IRQ-Anforderung anliegende NMI-Anforderung hat Vorrang.[1]

Eine während der ersten 4 Takte der Abarbeitung eines BRK-Befehls eingehende NMI-Anforderung hat den Nebeneffekt, dass das BRK statt zum IRQ-Vektor zum NMI-Vektor verzweigt (inkl. gesetztem Break-Flag).[2]

Ablauf[Bearbeiten | Quelltext 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.
  4. 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.
  5. Es wird zum NMI-Vektor in $0318/$0319 gesprungen (bei $FE44; zeigt normalerweise auf $FE47). Dieser Vektor kann auch von BASIC aus manipuliert werden.
  6. Falls der NMI durch die CIA2 ausgelöst wurde (Check bei $FE4C), wird zu den RS232-Routinen verzweigt ($FE72).
  7. 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).
  8. 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).
  9. 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 | Quelltext 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 | Quelltext 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 | Quelltext bearbeiten]

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

Weblinks[Bearbeiten | Quelltext bearbeiten]

Referenzen