Bereits Tabelle 4.1 (Abschnitt 4.2. VCPI) stellte die Standard Interruptvektortabelle dar. Dabei ist aus Tabelle 4.1 ersichtlich, daß die Hardware-Interrupts 0..7 die Interrupts 8..15 auslösen. Diese Interrupts sind jedoch bereits von Intel als Protected Mode Exceptions reserviert worden. Würde man ohne eine Änderung an dieser Einstellung, Interrupts erlauben, so würden beispielsweise 18,2 mal in der Sekunde Double-Fault Exceptions ausgelöst werden (Hardware-Interrupt 0 löst standardmäßig Interrupt 8 aus). Ebenfalls unter Punkt 4.2 wurde erläutert, wie eine Umprogrammierung der Interrupts erfolgen kann. Die Interrupts 00..1Fh sind von Intel reserviert. Damit stehen die Interrupts 20h..2Fh zur Verfügung und werden im Beispielprogramm für die Hardware-Interrupts 00..0Fh verwendet. Vgl. mit folgendem Programmcode-Ausschnitt:
; Neuinit der Interrupt-Controller, sowie neu Setzen des ; Interrupt Mappings mov al,00010001b ; kaskadierte Interrupt-Controller out 020h,al ; und Flankentriggerung an beider Controller out 0a0h,al ; neuer IRQ-Vektor für den ersten Controller einstellen mov al,20h ; neuer Wert => IRQ0..7 -> INT20h..27h out 021h,al ; neuer IRQ-Vektor für den zweiten Controller einstellen mov al,28h ; neuer Wert => IRQ8..15 -> INT28h..2Fh out 0a1h,al ; Kaskadierung beider Controller einstellen mov al,00000100b ; Kaskadierung über IRQ2 out 021h,al mov al,00000010b ; Kaskadierung über IRQ2 out 0a1h,al ; PIC auf Intel-Umgebung und manuelle Int.- Beendigung einstellen mov al,00000001b out 021h,al out 0a1h,al
Damit wird erreicht, daß Hardware-Interrupt 0 nicht mehr Interrupt 8, sondern Interrupt 20h aufruft.
Beispielprogramm pm_07_01.asm demonstriert die notwendigen Schritte, um einen Task-Handler für den Hardware-Interrupt 0 zu installieren. Der neue Handler wird dabei als Task ausgeführt (eigenes CODE- und TS-Segment), wird 18.2 mal in der Sekunde aktiviert und führt die folgenden Funktionen aus:
|
Die Frequenz, mit der der Hardware-Interrupt 0 aufgerufen wird, läßt sich über den PIT (Programmable Interval Timer) genau einstellen. Zähler 0 des PIT steuert dabei den Timer-Interrupt des PC und aktiviert ihn 18.2 mal in der Sekunde. Um den Eindruck einer wirklich parallelen Verarbeitung der Tasks zu erreichen, ist diese Zeitspanne zu groß. Der PIT kann aber leicht so umprogrammiert werden, daß die Aktivierung des Timer Interrupts öfter geschieht.
Dazu steht an Port 43h ein Control-Register zur Verfügung, dem entsprechende PIC-Kommandos übergeben werden können, so z.B. den Arbeitsmodus und das Zählformat. Tabelle 6.1 zeigt die Bedeutung der einzelnen Bits.
Bit | Bedeutung |
---|---|
7-6 | Auswahl des Zählers: |
00 - Zähler 0 (Timer-Interrupt) | |
01 - Zähler 1 (DRAM-Refresh) | |
10 - Zähler 2 (Frequenz für Lautsprecher) | |
11 - Rücklese - Modus | |
5-4 | Art des Kommandos |
00 - Latch Register lesen | |
01 - Lesen / Schreiben des Zähler Low Bytes | |
10 - Lesen / Schreiben des Zähler High Bytes | |
11 - Lesen / Schreiben von zuerst Low- und dann High- Byte des Zählers | |
3-1 | Arbeitsmodus |
000 - Modus 0, Interrupterzeugung | |
001 - Modus 1, Programmierbarer Monoflop | |
010 - Modus 2, Taktgenerator | |
011 - Modus 3, Rechteckswelle-Signalgenerator | |
100 - Modus 4, Triggerung des Ausgangs durch Software | |
101 - Modus 5, Triggerung des Ausgangs durch Hardware | |
0 | Wahl des Zähler-Formats |
0 - 16-Bit binär (Standard) | |
1 - BCD-Format |
Zähler 1 ist für den DRAM-Refresh zuständig und sollte nicht verändert werden. Zähler 2 steuert die Frequenz des internen Lautsprechers. Zähler 0 generiert den Timer-Interrupt. Als Kommando ist "Lesen/Schreiben von zuerst Low-, dann High-Byte" zu benutzen (Kommandocode: 11b), um den Zähler von einem definierten Anfangswert aus zu starten. Da der Task-Handler regelmäßig aktiviert werden soll, wird Modus 3 (Rechteckswellen-Signalgenerator) ausgewählt. Als Zählerformat wird der Standard (16-Bit Zähler -- binär) verwendet. Aus diesen Gründen ergibt sich der Wert 00110110b (36h), der an Portadresse 43h gesendet werden muß.
Als nächstes erwartet der PIC den neuen Wert für den Zähler an der Portadresse 40h in der Reihenfolge Low-Byte und danach High-Byte. Die Frequenz, d.h. die Angabe, wie oft ein Interrupt pro Sekunde generiert wird, muß dabei über die folgende Formel umgerechnet werden:
Zähler := 1193180 / Frequenz
Dabei wird zunächst das Low-Byte des ermittelten Zählerwertes an den PIC übertragen und anschließend das High-Byte. Die Zahl 1193180 entspricht der Frequenz, mit der der PIC aktiviert wird (1193180 Schwingungen pro Sekunde). Bei der Wahl der Aktivierungsfrequenz muß beachtet werden, daß sie nicht zu hoch gewählt wird, da das Umschalten der Tasks auch Zeit beansprucht.
Die Initialisierung des PIC auf die Frequenz 100 HZ (Zähler:= 1193180 / 100 = 11932d = 2E9Bh) kann z.B. über den folgenden Programmausschnitt realisiert werden:
; PIC für Zähler 0 auf 100 HZ initialisieren cli mov al,36h out 43h,al mov al,9Bh out 40h,al mov al,2Eh out 40h,al sti
Um den Ursprungszustand des PIC wieder herzustellen (z.B. bei der Rückehr ins DOS), kann der folgende Programmausschnitt verwendet werden:
; PIC, Zähler 0 wieder in Standardeinstellung cli mov al,36h out 43h,al mov al,0 out 40h,al out 40h,al sti
Beispielprogramm pm_07_02.asm erweitert die Möglichkeiten von Programm pm_07_01.asm um die Umprogrammierung des PIC. Außerdem wird die oben beschriebene Task-Umschaltung anhand von zwei Beispieltasks durchgeführt, die nichts weiter machen, als jeweils ein Zeichen auf dem Bildschirm zu verändern. |