2. x86平台硬件基础:中断控制器与定时器
在VxWorks BSP时钟定时器驱动开发中,x86平台的中断控制器和定时器硬件是核心基础。本章深入剖析8259A/APIC中断控制器、PIT/8254可编程间隔定时器以及高精度事件定时器(HPET)的架构、工作原理与编程模型,为后续驱动实现奠定坚实的硬件认知。
2.1 x86中断控制器:从8259A到APIC
中断控制器负责收集外设中断请求,经优先级裁决后向CPU发送中断信号。x86平台先后经历了8259A和APIC两个阶段。
2.1.1 8259A可编程中断控制器
8259A是传统x86系统的中断控制器,支持8个中断输入引脚IR0-IR7,可通过级联扩展至最多64个中断源。每个中断源可独立设置触发方式(边沿/电平)和中断向量号。
| 特性 | 8259A | 备注 |
|---|---|---|
| 最大中断源 | 8(单片)/ 64(级联) | 主片IR2接从片INT |
| 中断向量范围 | 0x00-0xFF | 通过ICW2设置基址 |
| 优先级模式 | 固定/循环优先级 | 全嵌套/特殊全嵌套 |
| 触发方式 | 边沿触发/电平触发 | 通过ICW1设置 |
| 编程接口 | ICW1-ICW4 + OCW1-OCW3 | 初始化命令字/操作命令字 |
8259A初始化流程(ICW序列):
- 写ICW1(端口0x20/0xA0):触发方式、级联标志、ICW4需要
- 写ICW2(端口0x21/0xA1):中断向量基址(高5位)
- 写ICW3(端口0x21/0xA1):主片/从片级联标识
- 写ICW4(端口0x21/0xA1):8086模式、自动EOI、特殊全嵌套
VxWorks BSP要点:在传统UP系统(单处理器)中,BSP初始化阶段需完成8259A的ICW序列配置,并设置OCW1中断屏蔽字。中断服务例程(ISR)结束时必须发送EOI命令(OCW2=0x20)到主片和从片端口。
2.1.2 APIC(高级可编程中断控制器)
APIC是现代x86多核系统的标准中断架构,包含LAPIC(本地APIC)和I/O APIC两部分。LAPIC集成在CPU内部,每个核心拥有独立的LAPIC;I/O APIC作为系统芯片组组件,负责收集外设中断并分发到目标LAPIC。
| 组件 | 位置 | 功能 | 寄存器基址 |
|---|---|---|---|
| LAPIC | CPU内部 | 接收本地中断(定时器/热敏/错误)、处理IPI、中断仲裁 | 0xFEE00000(MSR 1Bh配置) |
| I/O APIC | 芯片组 | 收集外设中断、重定向到指定LAPIC | 0xFEC00000(典型值) |
| MSI/MSI-X | PCIe设备 | 设备直接写LAPIC中断寄存器,无需I/O APIC | PCI配置空间 |
BSP开发关键差异:8259A与APIC在中断向量分配、EOI机制、优先级模型上完全不同。VxWorks BSP必须通过ACPI MADT表或MP表检测系统使用的中断模型,并选择对应的初始化路径。在SMP(对称多处理)系统中,必须使用APIC模式。
2.2 可编程间隔定时器(PIT/8254)
PIT是x86平台最经典的定时器硬件,提供3个独立的16位计数器通道,广泛应用于系统时钟、扬声器音调生成和事件计数。
2.2.1 8254内部结构与通道
| 通道 | I/O端口 | 典型用途 | GATE引脚 | CLK输入 |
|---|---|---|---|---|
| 计数器0 | 0x40 | 系统时钟中断(IRQ0) | 常高(+5V) | 1.1931816 MHz |
| 计数器1 | 0x41 | DRAM刷新请求 | 常高 | 1.1931816 MHz |
| 计数器2 | 0x42 | PC扬声器音调 | PPI端口0x61 bit0 | 1.1931816 MHz |
| 控制字寄存器 | 0x43 | 工作模式/读写格式选择 | — | — |
2.2.2 工作模式与编程模型
8254支持6种工作模式,其中模式2(速率发生器)和模式3(方波发生器)最常用于定时器驱动。
| 模式 | 名称 | 输出波形 | 典型应用 |
|---|---|---|---|
| 0 | 中断终止计数 | 计数到0时OUT变高 | 单次延时 |
| 1 | 可编程单稳 | 触发后输出低电平脉冲 | 脉冲生成 |
| 2 | 速率发生器 | 每个计数周期输出一个CLK宽度的低脉冲 | 系统时钟中断 |
| 3 | 方波发生器 | 50%占空比方波 | 扬声器音调 |
| 4 | 软件触发选通 | 计数到0时输出低脉冲 | 软件同步 |
| 5 | 硬件触发选通 | 硬件触发后计数到0输出低脉冲 | 硬件同步 |
VxWorks BSP中PIT初始化示例(模式2,计数器0):
/* 设置计数器0为模式2(速率发生器),先读写低字节再高字节,二进制计数 */
#define PIT_CTRL_PORT 0x43
#define PIT_CNTR0_PORT 0x40
#define PIT_CLK_FREQ 1193181 /* 1.1931816 MHz */
#define PIT_CTRL_WORD 0x34 /* 00 11 010 0 */
/* SC=00(计数器0) */
/* RW=11(先低后高) */
/* M=010(模式2) */
/* BCD=0(16位二进制) */
/* 设置定时周期为1ms (1000Hz) */
unsigned short reload_value = PIT_CLK_FREQ / 1000;
sysOutByte(PIT_CTRL_PORT, PIT_CTRL_WORD);
sysOutByte(PIT_CNTR0_PORT, reload_value & 0xFF); /* 低字节 */
sysOutByte(PIT_CNTR0_PORT, (reload_value >> 8) & 0xFF); /* 高字节 */
2.3 高精度事件定时器(HPET)
HPET是Intel/AMD联合制定的高精度定时器标准,旨在替代PIT和RTC定时器,提供更高精度和更多独立比较器通道。HPET在ACPI 3.0规范中定义,现代x86平台普遍支持。
2.3.1 HPET寄存器模型
| 偏移地址 | 寄存器名称 | 宽度 | 描述 |
|---|---|---|---|
| 0x000 | GCAP_ID | 64位 | 能力与ID寄存器(含计数器位数、定时器数量、时钟周期) |
| 0x010 | GEN_CONF | 64位 | 全局配置寄存器(使能位、遗留路由使能) |
| 0x020 | GINTR_STA | 64位 | 全局中断状态寄存器 |
| 0x0F0 | MAIN_CNT | 64位 | 主计数器(递增计数,不可写,复位归零) |
| 0x100 + n*0x20 | Tn_CONF | 64位 | 定时器n配置寄存器(中断类型、触发方式、使能) |
| 0x108 + n*0x20 | Tn_COMP | 64位 | 定时器n比较器寄存器(触发中断的计数值) |
| 0x110 + n*0x20 | Tn_FSB | 64位 | 定时器n FSB中断路由寄存器(MSI模式) |
2.3.2 HPET与PIT对比
| 特性 | PIT (8254) | HPET |
|---|---|---|
| 计数器宽度 | 16位 | 32位或64位 |
| 时钟频率 | 1.1931816 MHz | ≥10 MHz(典型14.31818 MHz) |
| 最小分辨率 | ~838 ns | ~70 ns(14.31818 MHz时) |
| 独立比较器 | 3个通道(共享时钟) | 至少3个(通常8个以上) |
| 中断路由 | 固定IRQ0 | 可编程路由到任意LAPIC/IOAPIC引脚 |
| MSI支持 | 不支持 | 支持(FSB中断模式) |
| 周期模式 | 自动重装 | 支持周期模式和单次模式 |
VxWorks BSP选择策略:在支持HPET的平台上,优先使用HPET作为系统时钟源。HPET的更高精度和更灵活的中断路由能力,能够提供更稳定的系统时钟和更低的调度延迟。BSP通过ACPI HPET表获取HPET基址和时钟周期,初始化主计数器和至少一个比较器通道。