GIC-625是Arm CoreLink系列中的通用中断控制器(Generic Interrupt Controller),基于GICv3/v4架构设计。作为现代多核SoC的中枢神经系统,它负责高效管理处理器与外围设备间的中断信号。与早期版本相比,GIC-625在实时性、安全监控和可扩展性方面有显著提升。
GIC-625支持三种基本中断类型:
其创新性体现在事件监控单元(PMU)的集成,通过五个32位硬件计数器实时追踪中断事件。例如0x51(SPI_ENABLED)事件记录新SPI中断的触发情况,0x80(ACC)事件则监控时钟周期计数。
GIC-625采用双安全域模型:
c复制// 安全状态判定示例代码
if (GICD_SAC.GICPNS == 0) {
// 安全访问模式
access_secure_registers();
} else {
// 非安全访问模式
access_nonsecure_registers();
}
关键寄存器如GICP_EVTYPERn(事件类型寄存器)在安全状态下可配置访问权限,防止非特权代码篡改中断行为。这种设计符合Arm TrustZone安全扩展要求。
PMU寄存器组位于GICP_前缀的地址空间,包含五个可编程计数器:
| 寄存器名称 | 位宽 | 功能描述 |
|---|---|---|
| GICP_EVCNTRn | 32位 | 事件计数器当前值 |
| GICP_EVTYPERn | 32位 | 事件类型配置(如0x51对应SPI启用) |
| GICP_FRn | 32位 | 事件过滤器配置 |
| GICP_CNTENSET0 | 32位 | 计数器使能设置 |
典型配置流程:
bash复制# 将计数器0归零
mmio_write32(GICP_BASE + 0x100, 0x00000000)
bash复制# 配置计数器0监控SPI启用事件(0x51)
mmio_write32(GICP_BASE + 0x200, 0x00000051)
bash复制# 设置精确匹配INTID 100的SPI
mmio_write32(GICP_BASE + 0x300, 0xC0000064)
GIC-625采用四级优先级机制:
关键提示:实时中断(RLT_SPI)需单独配置目标过滤寄存器GICP_FR3,即使使用计数器4也需通过FR3过滤
以监控USB控制器的中断(SPI 100)为例:
c复制// 设置GICP_CR.E=1启用所有计数器
writel(GICP_BASE + 0xF00, 0x00000001);
c复制struct gicp_filter {
uint32_t type : 2; // 0b01表示INTID过滤
uint32_t encoding: 1; // 精确匹配
uint32_t reserved:13;
uint32_t id :16; // 目标INTID
};
// 配置精确匹配INTID 100
struct gicp_filter filter = {
.type = 1,
.encoding = 1,
.id = 100
};
writel(GICP_BASE + 0x300, *(uint32_t*)&filter);
c复制uint32_t count = readl(GICP_BASE + 0x100);
printf("SPI100触发次数: %u\n", count);
通过GICD_CPENDSGIRn实现动态中断分配:
mermaid复制graph TD
A[中断触发] --> B{GICD_IRouter策略}
B -->|固定分配| C[指定CPU核心]
B -->|轮询调度| D[下一个可用核心]
B -->|负载感知| E[最低负载核心]
实际配置代码:
c复制// 设置SPI100路由到任意可用核心
writel(GICD_BASE + 0x6100, 0x80000000);
// 启用IRM位实现多核共享
uint32_t val = readl(GICD_BASE + 0x104);
writel(GICD_BASE + 0x104, val | 0x1);
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 中断未触发 | GICD_CTLR未启用 | 设置GICD_CTLR.EnableGrp1 |
| 计数器不递增 | 全局使能未打开 | 检查GICP_CR.E位 |
| SPI目标核心不响应 | 亲和性路由配置错误 | 验证GICD_IROUTERn设置 |
| 安全状态访问冲突 | GICD_SAC权限不足 | 切换安全状态或配置访问权限 |
实测数据表明,合理配置可使中断延迟降低40%以上:
code复制优化前: 平均延迟1.2μs
优化后: 平均延迟0.7μs
c复制// 安全状态检查示例
if (is_secure_mode()) {
// 可访问GICP_EVTYPERn等安全寄存器
} else {
// 仅能访问非安全寄存器
assert(register_offset >= NS_SAFE_REGION);
}
在开发基于GIC-625的实时系统时,建议采用以下防御性编程模式:
c复制void handle_interrupt(uint32_t intid) {
// 验证INTID范围
if (intid > MAX_SPI_ID) {
log_security_event(INVALID_INTID);
return;
}
// 检查安全上下文
if (is_secure_interrupt(intid) && !is_secure_mode()) {
escalate_to_secure_world();
}
// 正常处理流程
...
}