GIC是ARM提供给Cortex-A/R内核的中断控制器,类似于Cortex-M内核(STM32)中的NVIC。GIC:GenericInterruptController,通用中断控制器。NVIC:NestedVectoredInterruptController,嵌套中断向量控制器。GIC目前有4个版本:V1~V4,V1是最老的版本,已经废弃。V2~V4目前正在大量使用。GICV2用于ARMv7-A架构,如Cortex-A7、Cortex-A9、Cortex-A15等。V3、V4用于ARMv8-A/R架构,即64位芯片。我们使用的是IP内核,即gic400、gic500、gic600。支持相应的架构。gic400,支持GIC-v2架构。gic500,支持GIC-v3架构。gic600,支持GIC-v3和GIC-v4架构。GIC-v2GICV2最多支持8个内核。ARM会根据不同的GIC版本开发不同的IP核,半导体厂商可以直接采购对应的IP核。例如ARM为GICV2开发了gic400中断控制器IP核。当GIC接收到外部中断信号时,会向ARM内核上报,但ARM内核只提供四种信号给GIC上报中断:VFIQ、VIRQ、FIQ和IRQ:VFIQ:VirtualfastIRQ。VIRQ:虚拟中断请求。FIQ:快速中断请求。IRQ::中断请求。VFIQ和VIRQ是针对虚拟化的,我们不讨论虚拟化中断,剩下的就是FIQ和IRQ了。一般我们只用IRQ,所以相当于GIC最后上报一个IRQ信号给ARM核。下图来自ARM官方手册,是GIC-v2的框图:左边是中断源,中间是GIC控制器,最右边是向处理器发送中断信息的中断控制器核。我们必须关注中间的GIC部分。GIC把很多中断源分为三类:①、SPI(SharedPeripheralInterrupt),共享外设中断,中断来自外设,由所有Cores共享中断。比如按键中断、串口中断等,这些中断都是所有Core都可以处理的,不限制具体的Core。②、PPI(PrivatePeripheralInterrupt),私有外设中断,终端来自外设,由特定的内核处理。GIC支持多核,每个核都有自己独特的中断。③.SGI(Software-generatedInterrupt),软中断,由软件触发的中断,通过向寄存器GICD_SGIR写入数据触发,系统将使用SGI中断来完成多核之间的通信。中断源有很多。为了区分这些不同的中断源,必须给它们分配一个唯一的ID。这些ID是中断ID。GIC-v2中每个CPU最多支持1020个中断ID,中断ID号为ID0~ID1019。这1020个ID包括PPI、SPI和SGI。1020个ID分配如下:ID0~ID15:这16个ID分配给SGI。每个CPU核心都有自己的16个。ID16~ID31:这16个ID分配给PPI。每个CPU核心都有自己的16个。ID32~ID1019:这988个ID分配给SPI,GPIO中断,串口中断等外部中断,具体ID对应哪个中断,由半导体厂商决定根据实际情况来定义。GIC-v2架构分为两个逻辑块:Distributor和CPUInterface,即分发器端和CPU接口端。Distributor(分发端):中间的框架,这个逻辑块负责处理每个中断事件的分发,即中断事件应该发送到哪个CPUInterface。分发器收集所有的中断源,可以控制每个中断的优先级。它始终将具有最高优先级的中断事件发送到CPU接口。经销商端主要要做的工作如下:①.全局中断使能控制。②.控制每个中断的启用或禁用。③.设置每个中断的优先级。④.为每个中断设置目标处理器列表。⑤.设置每个外部中断的触发方式:电平触发或边沿触发。⑥.设置每个中断属于group0还是group1。CPUInterface(CPU接口):CPU接口的名称与CPUCore相连,所以图中每个CPUCore都可以在GIC中找到对应的CPUInterface。CPU接口是分发器和CPUCore之间的桥梁。CPU接口的主要工作如下:①.启用或禁用发送到CPUCore的中断请求信号。②、响应中断。③.通知中断处理完成。④.设置优先级掩码,设置哪些中断不需要通过掩码上报给CPUCore。⑤.定义抢占策略。⑥.当多个中断到来时,选择优先级最高的中断通知CPUCore。GIC-v2支持旁路功能。当左上角的CFGSDISABLE信号为高电平时,外部IRQ和FIQ直接连接到CPU内核的IRQ和FIQ引脚上,无需GIC仲裁。这个场景在启动阶段可能会用到,一般不会用到。右上角有GICD_、GICC_、GICV_、GICH_系列寄存器。因为不讨论虚拟中断,所以我们一般只关心GICD_和GICC_开头的寄存器。GICD_代表Distributor分配器的寄存器,GICC_代表CPU接口的寄存器。有一点需要说明:无论GIC如何对中断进行分类,对于CPU内核来说,只是分为IRQ、FIQ、VIRQ、VFIQ。一般所有的外部中断都属于CPU内核的IRQ:即使分为GICSPI、SGI、PPI,但最后都是走CPU接口,CPU接口再交给CPU内核。CPU内核只认为有四种中断,一般都是IRQ。GIC-v3GIC-v3的架构发生了变化,中断数量增加了,但仍然向后兼容GIC-v2。GIC-v3支持超级多核,命名为xxx.xxx.xxx.xxx,超过8核,GIC-v2只支持8核,命名为0-7。GIC-v3将CPU接口从GIC端移到了CPU端,因为处理中断会频繁访问CPU接口的寄存器,移到CPU端加快访问速度会加快中断处理。GIC-v3的架构变化如下:以前SPI、PPI、SGI都是由Distributor(分发端)管理的,现在只有SPI由Distributor管理,PPI、SGI、LPI是Distributor管理的都由Redistributor管理,功能还是一样的。寄存器的分布,不同事物的寄存器有不同的开头:GIC-v3的中断号规定如下,来自ARM官方文档。主要区别是增加了LPI中断类型,这是一种基于消息的中断。一般IRQ和FIQ都会有一条物理线,会给CPU核心一个物理信号,代表中断的到来。LPI不同。它是一种基于消息的机制。写入寄存器时,将发送消息中断。这是ARM对未来的布局。以后会推出一些服务器产品,中断号是独占的。GIC-v3的逻辑图总结如下:GIC-v2架构寄存器:来自GIC-v2手册的最后几页:alias这里的别名很有意思,解释一下这个寄存器是做什么用的:GIC-的寄存器v3则不同,它是ICC_、ICV_、ICH_系列寄存器。
