坏级尹 发表于 2025-8-5 20:27:48

ARM 通用中断控制器GIC(Generic Interrupt Controller)

Zynq7000系列学习笔记
本文介绍分发器(Distributor)和CPU接口 (CPU Interface)的功能与协作,并提供C语言案例辅助理解。
总结来说,分发器设置中断使能和中断优先级,并将该中断信号发送给CPU,CPU设置可接受的最低优先级,进行中断处理和完成中断通知。
一、分发器和CPU接口的功能

 分发器Distributor
CPU 接口 (CPU Interface)
基地址
0xF8F01000
0xF8F00100
功能
全局中断管理
CPU 核心的中断交互
管理对象
所有中断源 (SPI, PPI, SGI)
连接到单个 CPU 核心的中断
具体使用
中断使能/禁用、优先级配置、路由到 CPU
中断确认、优先级屏蔽、中断完成通知
可见性
全局唯一(CPU共享)
每个CPU私有
二、工作原理与交互流程 (中断生命周期)

[*]中断触发(外设 → 分发器)


[*]外设中断源(如 GPIO / UART / Timer)触发中断信号。
[*]分发器接收:



[*]中断信号到达分发器(0xF8F01000)
[*]分发器检查该中断是否 已使能(GICD_ISENABLERn)
[*]分发器读取该中断的 优先级(GICD_IPRIORITYRn)
[*]分发器根据配置决定是否 转发 给目标 CPU


[*]中断分发(分发器 → CPU 接口)


[*]路由决策:



[*]分发器检查目标 CPU 接口的状态(是否使能接收中断)
[*]比较 中断优先级 与目标 CPU 当前的 运行优先级(通过 CPU 接口的 GICC_PMR 获取)
[*]若中断优先级 > CPU 当前优先级,分发器将其挂起到目标 CPU 的待处理队列。



[*]信号通知:



[*]分发器通过硬件信号线通知目标 CPU 的 CPU 接口:有高优先级中断等待处理。


[*]CPU 响应 (CPU 接口 → CPU 核心)


[*]中断通知:



[*]CPU 接口 (0xF8F00100)收到分发器通知。
[*]CPU 接口向 CPU 核心 发送 IRQ/FIQ 中断请求。



[*]CPU 核心响应:



[*]CPU 核心暂停当前程序,跳转到 中断向量表 入口。
[*]执行中断服务程序 (ISR) 的 入口代码。


[*]中断处理 (ISR 与 CPU 接口交互)


[*]中断确认:



[*]ISR 通过 CPU 接口的 Interrupt Acknowledge Register(GICC_IAR)读取 中断号(INTID)
[*]读取 GICC_IAR 的行为告知 GIC:“CPU 已开始处理此中断”
[*]GIC 自动将该中断状态从 Pending 改为 Active



[*]服务中断:



[*]ISR 根据 INTID 执行具体的中断服务逻辑(如读取 UART 数据)



[*]中断完成:



[*]ISR 结束时,向 CPU 接口的 End of Interrupt Register(GICC_EOIR)写入之前读到的 INTID。
[*]写入 GICC_EOIR 告知 GIC:“此中断处理已完成”
[*]GIC 将该中断状态从 Active 改为 Inactive,并允许分发器再次发送此中断(若再次触发)


[*]中断优先级与抢占


[*]分发器 根据全局中断优先级决定哪些中断可发送给 CPU。
[*]CPU 接口 的 GICC_PMR 设置 CPU 可接受的最低优先级(低于此值的中断被屏蔽)
[*]若高优先级中断到达,且当前中断优先级较低,CPU 接口可触发 中断抢占(暂停当前 ISR,转去处理更高优先级中断)。
三、软件编程详细案例

[*]分发器初始化代码详解

[*] 全局使能分发器

*(volatile uint32_t *)(GIC_DIST_BASE + 0x000) = 0x1; // GICD_CTLR

[*]作用:启用整个中断分发系统,是整个 GIC 系统的总开关
[*]寄存器:GICD_CTLR(Distributor Control Register)
[*]地址计算:基地址0xF8F01000+偏移量0x000
[*]位设置:



[*]Bit 0 = 1:使能中断转发到 CPU 接口
[*]Bit 1 = 0:禁用安全扩展


[*]配置中断优先级

*(volatile uint32_t *)(GIC_DIST_BASE + 0x400 + (84 * 4/4)) = 0xA0;
// GICD_IPRIORITYR

[*]作用:设置中断号84的优先级(优先级范围0~255,0最高)
[*]寄存器:GICD_IPRIORITYRn(Interrupt Priority Registers)
[*]地址计算:



[*]优先级寄存器组基偏移:0x400
[*]中断号 84 的偏移:84 * 1(因为每个中断占 1 字节)
[*]实际地址:0xF8F01000 + 0x400 + 84 = 0xF8F01454
[*]Zynq-7000 中:0-31是私有中断(PPI)和软件中断(SGI);32-95是共享外设中断(SPI)


[*]路由到 CPU0

*(volatile uint32_t *)(GIC_DIST_BASE + 0x800 + (84 * 4/4)) = 0x01;
// GICD_ITARGETSR

[*]作用:指定中断84发送到 CPU0
[*]寄存器:GICD_ITARGETSRn(Interrupt Processor Targets Registers)
[*]地址计算:0xF8F01000 + 0x800 + 84 = 0xF8F01854
[*]位掩码:0x01表示 CPU0



[*]Bit 0 = 1:路由到 CPU0
[*]Bit 1 = 0:不路由到 CPU1



[*]注:在双核系统中,必须明确指定中断发送到哪个核心。
[*]注:PPI/SGI 不能配置路由,只有 SPI(32+)可配置

[*]使能中断号 84

*(volatile uint32_t *)(GIC_DIST_BASE + 0x100 + (84 / 32)*4) |= (1
页: [1]
查看完整版本: ARM 通用中断控制器GIC(Generic Interrupt Controller)