HPET: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
timer N registers |
finished (I hope) |
||
Line 55: | Line 55: | ||
==HPET operating modes== |
==HPET operating modes== |
||
HPET offers |
HPET offers two operating modes: one-shot (also called "non-periodic" by the specification) and periodic mode. |
||
===One-shot mode=== |
===One-shot mode=== |
||
Line 295: | Line 295: | ||
Bits 63:0 (or 31:0, if the timer operates in 32 bit mode) are used to compare with main counter to check if an interrupt should be generated. |
Bits 63:0 (or 31:0, if the timer operates in 32 bit mode) are used to compare with main counter to check if an interrupt should be generated. |
||
==Initialization== |
|||
The following is the procedure you need to perform to initialize main counter and comparators in order to receive interrupts. |
|||
General initialization: |
|||
1. Find HPET base address in 'HPET' ACPI table. |
|||
2. Calculate HPET frequency (f = 10^15 / period). |
|||
3. Save minimal tick (either from ACPI table or configuration register). |
|||
4. Initialize comparators. |
|||
5. Set ENABLE_CNF bit. |
|||
Timer N initialization: |
|||
1. Determine if timer N is periodic capable, save that information to avoid re-reading it every time. |
|||
2. Determine allowed interrupt routing for current timer and allocate an interrupt for it. |
|||
I am enabling the timers only when I actually use them, so there's no "real" initialization of comparators here. |
|||
Keep in mind that allowed interrupt routing '''may be insane'''. Namely, you probably want to use some of ISA interrupts - or, at very least, be able to use them at one point unambiguously. Last time I checked VirtualBox allowed mappings for HPET, it allowed every timer to be routed to ''any'' of 32 I/O APIC inputs present on the system. Knowing how buggy hardware can be, I wouldn't be too surprised if there exists a PC with HPET claiming that input #31 is allowed, when there are only 24 I/O APIC inputs. Be aware of this when choosing interrupt routing for timers. |
|||
==Using timers== |
|||
===One-shot mode=== |
|||
To enable one-shot mode: |
|||
<source lang="cpp"> |
|||
// "time" is time in femptoseconds from now to interrupt |
|||
if (time < COUNTER_CLK_PERIOD) |
|||
{ |
|||
time = adjust_time(time); |
|||
} |
|||
write_register_64(timer_configuration(n), (ioapic_input << 9) | (1 << 2)); |
|||
write_register_64(timer_comparator(n), read_register(main_counter) + time); |
|||
</source> |
|||
I hope the above code is obvious. If it's not, please analyze the meaning of specific fields in registers used above. |
|||
===Periodic mode=== |
|||
To enable periodic mode: |
|||
<source lang="cpp"> |
|||
// "time" is time in femptoseconds from now to interrupt |
|||
if (time < COUNTER_CLK_PERIOD) |
|||
{ |
|||
time = adjust_time(time); |
|||
} |
|||
write_register_64(timer_configuration(n), (ioapic_input << 9) | (1 << 2) | (1 << 3) | (1 << 6)); |
|||
write_register_64(timer_comparator(n), read_register(main_counter) + time); |
|||
write_register_64(timer_comparator(n), time); |
|||
</source> |
|||
This snippet requires some more comments. |
|||
Bit 2 is the same as above, Interrupt Enable. Bit 3 is also quite straightforward - 1 means periodic timer. But we've also set bit 6. Why? |
|||
Let's take a look at quote from the HPET specification: |
|||
<blockquote>Timer n Value Set: [...] Software uses this read/write bit only for timers that have been set to periodic mode. By writing this bit to a 1, the software is then allowed to directly set a periodic timer’s accumulator.</blockquote> |
|||
<blockquote>Software does NOT have to write this bit back to 0 (it automatically clears). Software should not write a 1 to this bit position if the timer is set to non-periodic mode.</blockquote> |
|||
This means that next write to timer N comparator register will have the usual meaning, while ''second'' next write will write directly to the accumulator. I believe that the wording could've been much better. |
|||
==See also== |
==See also== |