(由于之前的blog已经关闭了,所以将此文章迁移至这里,并非转载)
HPET
This page is not meant as a full description of HPET, only as a lightweight introduction. If you need any information not covered by this article, consult the HPET specification.
这篇文章并没有完全的去说明HPET,只是简单地概述了一下。如果你需要的内容这里没有讲述到,请参考HPET的说明文档。
Preface
HPET, or High Precision Event Timer, is a piece of hardware designed by Intel and Microsoft to replace older PIT and RTC. It consists of (usually 64-bit) main counter (which counts up), as well as from 3 to 32 32 or 64 bit wide comparators. HPET is programmed using memory mapped IO, and the base address of HPET can be found using ACPI.
HPET(High Precision Event Timer,高精度时钟),是Intel和微软为了替换之前PIT或RTC(都可以当定时器用的一个东西)所设计的一个硬件。它由一个主的计数器和比较器组成,计数器一般是64位的,比较器至少有3个最多32个(这个我没考察过,只是翻译),通常比较器是32位或64位的。HPET通过内存映射IO来操作,内存的基地址可以从ACPI中找到。
Detecting HPET using ACPI
The HPET specification defines an ACPI 2.0 table that is to be used to detect presence, address and capabilities of HPET present in the system. If this table doesn’t exist, you should assume there is no HPET and you should fall back to PIT.
HPET规范中规定了会定义一个ACPI 2.0表(在ACPI中),可以通过这个表来检测硬件中是否存在HPET,并且可以获取到基地址以及HPET功能上的一些信息。如果这个表没有,那只能用PIT了。
struct address_structure
{
uint8_t address_space_id; // 0 - system memory, 1 - system I/O
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t reserved;
uint64_t address;
} __attribute__((packed));
struct description_table_header
{
char signature[4]; // 'HPET' in case of HPET table
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oemid[6];
uint64_t oem_tableid;
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __attribute__((packed));
struct hpet : public description_table_header
{
uint8_t hardware_rev_id;
uint8_t comparator_count:5;
uint8_t counter_size:1;
uint8_t reserved:1;
uint8_t legacy_replacement:1;
pci_vendor_t pci_vendor_id;
address_structure address;
uint8_t hpet_number;
uint16_t minimum_tick;
uint8_t page_protection;
} __attribute__((packed));
HPET – timer vs comparators
There is just one up counting main counter in the timer, but interrupt generation is handled by comparators. There’re from 3 to 32 comparators, and the exact amount is indicated by comparator_count
field in the above hpet
structure. Keep in mind you have to initialize both the main counter and all of the comparators. Also, the routing as well as allowed routing of comparator interrupts is independent, so you have to detect and set it up for each of them individually. More information on this procedure is provided further in the text.
HPET中只有一个通过定时器自加的计数器,通过不同的比较器来产生中断。(可以理解为只有一个基准Timer,并且自加计数器的值,然后通过比较器来比较是否触发中断。)HPET中大约有3-32个比较器,具体的值时候hpet
结构体中的comparator_count
字段来设置。必须要同时初始化主计数器和所有的比较器。每个比较器所触发的中断都是可以独立配置的,所以一般情况下都需要为每个比较器单独的设置中断。在下文中将会继续说明这部分内容。