文章目录
- GIC Pending 和 Clear Pending
- GICD_ISPENDR<n>
- GICD_ICPENDR<n>
- 参数<n>编号解释
- 使用举例
- 设置中断ID 100为挂起状态
- 清除中断ID 100的挂起状态
- 代码实现
- 小结
GIC Pending 和 Clear Pending
在ARMv8体系结构中,GICD_ISPENDR<n>
和 GICD_ICPENDR<n>
是GIC(通用中断控制器)中的两组重要寄存器,它们分别用于设置和清除中断的挂起状态。这些寄存器允许软件控制中断的挂起状态,从而在高级中断管理中起到关键作用。
GICD_ISPENDR
- 寄存器名称:Interrupt Set-Pending Registers
- 目的:用于将特定的中断标记为挂起状态。
- 描述:
GICD_ISPENDR<n>
寄存器允许软件将中断标记为挂起。当向这些寄存器的特定位写入1
时,相应的中断会被设置为挂起状态,这意味着中断已经准备好被GIC处理。写入0
对该位没有影响。
GICD_ICPENDR
- 寄存器名称:Interrupt Clear-Pending Registers
- 目的:用于清除特定中断的挂起状态。
- 描述:
GICD_ICPENDR<n>
寄存器允许软件清除中断的挂起状态。当向这些寄存器的特定位写入1
时,相应的中断挂起状态会被清除,这意味着中断不再准备好被处理。写入0
对该位没有影响。
参数编号解释
参数 <n>
表示寄存器的索引,根据系统支持的中断数量而变化。例如,如果 GIC 支持最多 1020 个中断,则 GICD_ISPENDR
和 GICD_ICPENDR
寄存器会有多个(例如从 GICD_ISPENDR0
到 GICD_ISPENDR31
),因为每个寄存器可以控制 32 个中断的挂起状态。
使用举例
假设我们要将中断ID 100标记为挂起,并随后清除其挂起状态:
设置中断ID 100为挂起状态
- 确定正确的寄存器和位位置:
- 中断ID 100 位于
GICD_ISPENDR3
(因为100 / 32 = 3
),位于该寄存器的第100 % 32 = 4
位。
- 中断ID 100 位于
- 设置挂起:
GICD_ISPENDR3 |= (1 << 4);
清除中断ID 100的挂起状态
- 同样,位于
GICD_ICPENDR3
寄存器,位位置为第 4 位。 - 清除挂起:
GICD_ICPENDR3 |= (1 << 4);
代码实现
void gic_irq_set_pending(int irq)
{
uint32_t addr;
if (!is_spi_irq(irq)) {
log_err("irq%d is not a spi irq\n", irq);
return;
}
/* Calculate enable register offset and bit position */
uint32_t reg_offset = irq / 32;
uint32_t reg_shift = irq % 32;
addr = ISPENDR_ADDRESS(GIC_DISTRIBUTOR_BASE, reg_offset);
write32(addr, (1 << reg_shift));
}
void gic_irq_clear_pending(int irq)
{
uint32_t addr;
if (!is_spi_irq(irq)) {
log_err("irq%d is not a spi irq\n", irq);
return;
}
uint32_t reg_offset = irq / 32;
uint32_t reg_shift = irq % 32;
addr = ICPENDR_ADDRESS(GIC_DISTRIBUTOR_BASE, reg_offset);
write32(addr, (1 << reg_shift));
}
小结
- 操作这些寄存器通常需要有特权级别的代码执行,因此通常在操作系统的内核或中断管理器中进行。
- 写入这些寄存器时要特别注意,错误的操作可能导致中断错误挂起或无法正确处理。
- 如需为特定应用编程,确保理解你的系统的具体GIC版本和实现细节。