OOStuBS/MPStuBS
|
Die APIC-Architektur beinhaltet auf jedem der CPU-lokalen APICs einen hochauflösenden Timer, der zum Generieren von Interrupts genutzt werden kann.
Da seine Frequenz nicht in der Spezifikation festgelegt ist, muss sie zunächst durch Kalibration mit einer anderen Zeitquelle deren Frequenz bekannt ist, beispielsweise dem Programmable Interrupt Timer (PIT), bestimmt werden. In der Vorgabe zu OOStuBS ist dieser Code bereits enthalten, er nutzt dazu jedoch eine generische Methode zur Timerkonfiguration, die noch zu implementieren ist.
Vier 32bit-Register (memory-mapped) sind für die Programmierung des APIC-Timers verantwortlich:
Addresse | Registername |
---|---|
0xfee00320 | LVT Timer Register (aka Timer Control Register) |
0xfee00380 | Initial Count Register (ICR) |
0xfee00390 | Current Count Register (CCR) |
0xfee003e0 | Divide Configuration Register |
Die beiden Count-Register (ICR und CCR) dienen dazu, den Startwert des Timers zu setzen beziehungsweise den aktuellen Wert auszulesen. Zusätzlich kann mit einem ICR-Wert von 0 der Timer vor einer Umprogrammierung komplett gestoppt werden. Ein anschließendes Schreiben des ICR mit einem Wert ungleich 0 startet den Timer.
Das Verhalten des Timers kann über das Kontrollregister und den Divisor beeinflusst werden. Der Aufbau des Kontrollregisters ist:
Bit(s) | Wert | Bedeutung |
---|---|---|
31-18 | (reserviert) | |
17 | Betriebsmodus | |
0 | one-shot (stoppt bei 0) | |
1 | periodic (startet wieder mit ICR-Wert) | |
16 | Interruptmaske | |
0 | Interrupts werden zugestellt | |
1 | Interrupts sind deaktiviert | |
15-13 | (reserviert) | |
12 | Interrupt-Status (read-only) | |
0 | idle | |
1 | Interrupt pending | |
11-8 | (reserviert) | |
7-0 | Vektornummer des auszulösenden Interrupts |
Die Zuordnung des Divisors auf entsprechende Registerwerte ist dem Intel-Manual zu entnehmen, aber auch bereits durch die Hilfsfunktion LAPIC::timer_div() als Teil der Vorgabe implementiert.