Informationen Programmierbarer Interrupt Controller (PIC)
Der PIC 8259A ist ein Chip (oder besser Teil eines Chips), der wie der Prozessor selbst auf dem Motherboard eines jeden PCs zu finden ist. Seine Aufgabe besteht in der Koordination der Unterbrechungsanforderungen der verschiedenen Geräte.
Dazu besitzt der PIC 8 Eingänge IR0
bis IR7
,
an die jeweils der Interruptausgang eines Gerätes angeschlossen werden
kann. Beispiele für diese Geräte sind der Timer, die Tastatur,
die seriellen Schnittstellen (Maus) und der Festplattencontroller.
Die Nummer des IR Pins gibt gleichzeitig die Priorität der Unterbrechung
an. Das Gerät, das an IR0
angeschlossen ist, wird mit
höchster Priorität behandelt, das an IR7
mit der
niedrigsten.
Der PIC hat mehrere Ausgänge, durch die er mit der CPU verbunden ist.
Unter anderem ist der Pin INT
des PICs direkt an den Pin
INTR
der CPU angeschlossen, ebenso sind die bei PIC und CPU
gleichermaßen mit INTA
bezeichneten Pins gekoppelt. Die Pins
D0
bis D7
des PICs sind mit den acht niederwertigsten
Leiterbahnen des Datenbusses verbunden.
Wenn der PIC feststellt, dass auf mindestens einem seiner Eingänge
IR0
bis IR7
eine Interruptanforderung anliegt und
dem PIC nicht mitgeteilt wurde, dass er die entsprechende Anforderung
ignorieren soll, so gibt er die Interruptanforderung über seinen Ausgang
INTR
an die CPU weiter. Diese wird die Anforderung mit Hilfe der
INTA
Leitung quittieren und durch ein zweites Signal auf
INTA
nach der Nummer des Interrupts fragen.
Der PIC antwortet daraufhin, indem er die Nummer des Interrupts (gleich
der Nummer der Eingangsleitung + einem Offset) auf den Datenbus legt.
Die CPU ist nun in der Lage, die Anfangsadresse der Unterbrechungsbehandlungsroutine
zu finden und die Unterbrechungsbehandlung zu starten.
Damit der PIC sich merken kann, von welchen Geräten er Interruptanforderungen
erhalten hat, welche er ignorieren soll und welche gerade von der CPU behandelt
werden, besitzt er drei interne Register, die jeweils 8 Bit
breit
sind:
- Interrupt-Request Register (IRR)
- Hier speichert der PIC, auf welchen der IR Leitungen eine Interruptanforderung signalisiert wurden. Dadurch braucht das betreffende Gerät nur eine kurze Änderung des Pegels auf der Leitung auszulösen.
- Interrupt-Service Register (ISR)
- Liegen die Interruptanforderungen mehrerer Geräte gleichzeitig an,
so wird der PIC zunächst nur die wichtigste weiterleiten. Dazu wird
die Unterbrechungsanforderung der CPU über die Leitung
INT
angezeigt. Sobald diese daraufhin mit zweiINTA
Signalen reagiert hat, wird nicht nur die Nummer des Interrupts auf den DatenleitungenD0-D7
ausgegeben, sondern auch das entsprechende Bit imISR
gesetzt. Gleichzeitig wird das Bit imIRR
gelöscht. Da das Bit im ISR gesetzt bleibt, bis es von der Unterbrechungsbehandlungsroutine mit Hilfe eines speziellen Befehls explizit gelöscht wird, kann der PIC beim Eintreffen einer weiteren Unterbrechung leicht erkennen, ob diese noch wichtiger als die gerade bearbeitete ist. In diesem Fall wird er dies der CPU durch ein erneutes Signal auf derINT
Leitung mitteilen. - Interrupt-Mask Register (IMR)
- Mit Hilfe dieses Registers ist es möglich, Interrupts selektiv zu unterdrücken. Ein gesetztes Bit im IMR sorgt dafür, dass der PIC Interrupts des entsprechenden Gerätes ignoriert.
Um mehr als 8 Interruptquellen unterscheiden zu können, enthalten
moderne PCs (das heißt alle ab dem XT) zwei PICs, die
hintereinander geschaltet sind. Der INT
Ausgang des Slave-PICs
hat also keine direkte Verbindung zu dem INTR
Eingang der CPU,
sondern wird an einen der IR Einänge (IR2) des Master PICs
angeschlossen. Außerdem stehen Master und Slave über drei weitere
Leitungen in Verbindungen, über die der Master dem Slave mitteilen kann,
wann dieser die Nummer des von ihm signalisierten Interrupts auf den Datenbus
legen soll.
Software
Ignorieren eines Interrupts
CPU-seitig kann dafür gesorgt werden, dass das laufende Programm nicht
durch Interrupts unterbrochen wird. Dazu wird mit der Assembleranweisung
cli
das Interrupt-Bit im EFLAGS-Register gelöscht.
Der Prozessor wird auf Signale seiner INTR
Leitung nun nicht mehr
reagieren. Da der PIC einen Interrupt frühestens dann weitergibt, wenn die
CPU auf den vorhergehenden Interrupt reagiert hat, wird der PIC keine Interrupts
weiterleiten, solange die CPU Interrupts ignoriert.
Dieser Vorgang kann mit dem Befehl sti
wieder rückgängig
gemacht werden.
Interrupts können auch selektiv unterdrückt werden. Dazu muss
der PIC programmiert werden. Das geht wie üblich mit in
und out
Befehlen.
Software zur Interruptbehandlung
Wenn ein Interrupt ankommt, der sowohl seitens des PICs als auch seitens der CPU zugelassen wurde, verzweigt der Prozessor automatisch zur Interruptbehandlungsroutine.
Deren Adresse wird einer Interruptdeskriptortabelle (IDT
)
entnommen, wobei die von dem PIC auf den Datenbus gelegte Nummer des Interrupts
als Index dient. Beim 8086 Prozessor war die Lage der Interruptdeskriptortabelle
noch fest von der Hardware vorgegeben, ab dem 80386 wird ihr Anfang und ihre
Größe durch das IDT-Register beschrieben.
Die Interruptdeskriptortabelle kann maximal 256 Interruptgate-Deskriptoren enthalten, von denen es drei verschiedene Typen gibt:
- Task-Gate
- Der Taskgate-Deskriptor zeigt auf einen Task, einen hardwaremäßig unterstützten Prozeß. Wenn der entsprechende Interrupt eintritt, führt der Prozessor automatisch einen Taskwechsel zu dem angegebenen Interrupt-Task durch.
- Interrupt-Gate
- Der Interruptgate-Deskriptor zeigt auf eine Prozedur, die als Interruptbehandlungsroutine ohne vorherigen Taskwechsel aufgerufen wird.
- Trap-Gate
- Der Trapgate-Deskriptor zeigt auf eine Prozedur, die als Trapbehandlungsroutine ohne vorherigen Taskwechsel aufgerufen wird.
Bevor der Prozessor infolge eines Interrupts oder Traps die angegebene
Behandlungsroutine aufruft, legt er den aktuellen Inhalt des
EFLAGS
-Registers auf den Stack ab. Dies ermöglicht es ihm,
nun das Interrupt-Enable-Flag im EFLAGS
-Register zu löschen
und auf diese Weise die geschachtelte Behandlung weiterer Interrupts zu
verhindern. Wie bei einem normalen Funktionsaufruf wird dann noch die
Rücksprungadresse (Inhalt von Code-Segment und Instruction Pointer)
auf dem Stack gesichert, bevor die Behandlungsroutine begonnen wird.
Bei manchen Exceptions legt der Prozessor zusätzlich einen Fehlercode
auf dem Stack ab.
Wurde die Unterbrechung durch einen Interrupt ausgelöst, besteht eine
Aufgabe der Interruptbehandlungsroutine darin, dem PIC mitzuteilen, dass
der Interrupt behandelt wurde. Anderenfalls wird der PIC nämlich keine
weiteren Interrupts desselben Gerätes weiterleiten.
Das Senden dieses Interrupt-Acknowledge-Signals erfolgt wieder mit einem
(bzw. bei einer Kaskadierung der PICs mit zwei) out
Befehl(en) an den Port des PICs.
Mit dem iret
Befehl wird die Unterbrechungsbehandlung
abgeschlossen. Der Prozessor holt die Rücksprungadresse vom Stack,
stellt den Inhalt des EFLAGS
-Registers wieder her und kehrt
zu der unterbrochenen Methode zurück.
Dadurch, dass auch die EFLAGS
wieder hergestellt werden,
werden spätestens jetzt die Interrupts CPU-seitig wieder zugelassen.
Zugriff auf die PICs über Ports
Jedem der beiden PICs in einem PC sind zwei Ports im I/O-Adressraum zugeordnet, die wie folgt belegt sind:
Port (IRQ0-7/IRQ8-15) | Lesedaten | Schreibdaten |
0x20 / 0xa0 | IRR, ISR, Int.Vektor | ICW1, OCW2, OCW3 |
0x21 / 0xa1 | IMR | ICW2, ICW3, ICW4, OCW1 |
Die Bezeichnungen ICW
und OCW
stehend dabei
für Initialization Control Word und Operation Control Word.
Für die Lösung der Aufgabe sind nur die Operationsbefehlsworte
OCW1
und OCW2
relevant:
OCW1
ist schlicht ein Platzhalter für die Maske der gesperrten Interrupts. Diese Maske wird direkt in das Interrupt Mask Register (IMR,0x21/0xa1
) übertragen; ein gesetztes Bit X sorgt dafür, dass der entsprechende Interrupt X gesperrt wird.OCW2
wird verwendet um dem PIC einenEOI
-Befehl zu senden, damit dieser erfährt, dass der Interrupt bearbeitet wird und das gesetzte Bit im ISR löscht. Bei oo-StuBS verwenden wir den "unspezifischen EOI-Befehl":OCW2 == 0x20
wird nach der Bearbeitung eines Interrupts in die Kontrollregister0x20 / 0xa0
geschrieben.
Die Initialisierungsbefehlsworte ICW1-ICW4
dienen der Initialisierung
des Chips. Dies erfolgt bei oo-StuBS innerhalb des Startup-Codes
(siehe startup.asm
), so dass ihr euch darum ausnahmsweise
mal nicht selber kümmern müsst.
Literatur
- Hans-Peter Messmer, "PC-Hardwarebuch", Addison-Wesley, 1995
- Intel, "8259A - Programmable Interrupt Controller"
- Andreas Roth, "Das Computer-Peripherie Kochbuch", IWT Verlag, 1990
- Klaus-Dieter Thies, "80386 - Die innovativen 80286/80386 Architekturen", tewi Verlag, 1988