美文网首页
ARM GIC介绍

ARM GIC介绍

作者: 小田BSP | 来源:发表于2023-03-11 16:14 被阅读0次

    一、GIC介绍

    GIC(Generic Interrupt Controller)ARM公司提供的一个通用的中断控制器,目前有4个版本GICv1 ~ GICv4GICv1已弃用;GICv2最多支持8个ARM CoreGICv3/GICv4支持更多的ARM Core)。

    GIC的核心功能:对SOC中外设的中断源的管理,并提供给软件,配置以及控制这些中断源。当对应的中断源有效时,GIC根据中断源配置,决定是否将该中断信号发给CPU。如果有多个中断源有效,那么GIC还会进行仲裁,选择最高优先级中断,发送给CPU。当CPU接收到GIC发送的中断,通过读取GIC的寄存器,可以知道中断的来源,从而做对应的处理。当CPU处理完中断后,会配置GIC寄存器,表示该中断已处理完毕。GIC接收到信息后,就将该中断源取消,避免又重新发送该中断给CPU,以及允许中断抢占。

    二、GIC IP

    对于不同的GIC版本,ARM公司设计了对应的GIC IP

    1)GIC-400:支持GICv2版本。

    2)GIC-500:支持GICv3版本。

    3)GIC-600:支持GICv3版本。

    4)GIC-700:支持GICv3/GICv4.1版本。

    CPUGIC之间兼容性见下图:

    image.png

    三、GIC框架

    GICv3架构包括:

    1、Distributor

    DistributorSPI外设中断分发器,外设经特定硬件中断线连接到DistributorDistributor判断SPI中断的优先级,决定优先处理哪个中断,使用中断重映射表决定中断的目的PE,同时维护中断的active/pending/acknowledged状态。

    2、Redistributor

    Redistributor:管理SGI/PPI/LPI中断,决定他们的优先级,触发方式,控制他们的状态,以及enable/disable特定中断。

    3、CPU interface

    CPU interface:传输中断给Core。每个Redistributor连接一个CPU interface,它负责打开和关闭PE的中断处理能力,acknowledge中断,为PE维护一个中断优先级掩码(只响应更高优先级中断),定义中断抢占策略,执行中断降级。

    4、ITS

    ITS(Interrupt Translation Service):接收LPI消息中断,根据消息携带的event iddevice id,翻译得到物理中断线以及目标PEITSdevice之间通过系统总线连接,device采用内存地址的形式发一个中断消息给ITS

    5、 PE

    PE(Process element)处理器单元,中断的最终接收者和处理者。

    image.png

    GICv2GICv3少了RedistributorITS等功能。

    image.png

    GICv4GICv3的功能基本相同,增加了直接注入虚拟中断的能力。

    四、GIC中断类型

    GIC中断类型包括:

    1、 SGI(Software Generated Interrupt)

    软中断,主要用于核间通信,通过写SGI寄存器产生。

    2、PPI(Private Peripheral Interrupt)

    私有外设中断,为某个核的私有中断。例(arch/arm64/boot/dts/rockchip/rk3399.dtsi):

            # RK3399小核CortexA53 pmu PPI中断
            pmu_a53 {
                    compatible = "arm,cortex-a53-pmu";
                    interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster0>;
            };
    
            # RK3399大核CortexA72 pmu PPI中断
            pmu_a72 {
                    compatible = "arm,cortex-a72-pmu";
                    interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW &ppi_cluster1>;
            };
            ...
            # ARMV8 timer PPI中断
            timer {
                    compatible = "arm,armv8-timer";
                    interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
                                 <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
                                 <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
                                 <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
                    arm,no-tick-in-suspend;
            };
    

    3、SPI(Shared Peripheral Interrupt)

    共享外设中断,外设中断可以发送到任何一个连接的core。例(arch/arm64/boot/dts/rockchip/rk3399.dtsi):

            # RK3399 uart SPI中断
            uart0: serial@ff180000 {
                    compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
                    reg = <0x0 0xff180000 0x0 0x100>;
                    clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
                    clock-names = "baudclk", "apb_pclk";
                    interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH 0>;
                    reg-shift = <2>;
                    reg-io-width = <4>;
                    pinctrl-names = "default";
                    pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
                    status = "disabled";
            };
    

    4、 LPI(Locality-specific Peripheral Interrupt)

    特定区域外设中断。只在GICv3GICv4上支持。

    不同中断类型的INITD范围如下:

    image.png image.png

    注:目前Linux内核驱动中,使用的是IRQ中断,没有使用FIQ中断,同时禁止IRQ中断嵌套。

    五、GIC中断触发方式

    GIC中断触发方式包括:

    1、edge-triggered interrupt

    边沿触发中断。支持的中断类型有:SGI/PPI/SPI/LPI

    2、 level-sensitive interrupt

    电平触发中断。支持的中断类型有:PPI/SPI

    注:GICv2/v3 SPI中断只支持上升沿或高电平触发。

    代码如下:

    drivers/irqchip/irq-gic-v3.c

    static int gic_set_type(struct irq_data *d, unsigned int type)
    {
            unsigned int irq = gic_irq(d);
            void (*rwp_wait)(void);
            void __iomem *base;
    
            /* Interrupt configuration for SGIs can't be changed */
            if (irq < 16)
                    return -EINVAL;
    
            ## GICv3 SPI只支持高电平和上升沿触发中断
            /* SPIs have restrictions on the supported types */
            if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
                             type != IRQ_TYPE_EDGE_RISING)
                    return -EINVAL;
            ...
    }
    

    drivers/irqchip/irq-gic.c

    static int gic_set_type(struct irq_data *d, unsigned int type)
    {
            void __iomem *base = gic_dist_base(d);
            unsigned int gicirq = gic_irq(d);
    
            /* Interrupt configuration for SGIs can't be changed */
            if (gicirq < 16)
                    return -EINVAL;
    
            ## GICv2 SPI只支持高电平和上升沿触发中断
            /* SPIs have restrictions on the supported types */
            if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
                                type != IRQ_TYPE_EDGE_RISING)
                    return -EINVAL;
            ...
    }
    

    六、GIC中断状态

    GIC中断状态包括:

    1、 Inactive

    该中断源当前无效,未发生中断。

    2、 Pending

    已产生中断,未被PE响应。

    3、 Active

    该中断源已经发生并且已被PE响应。

    4、 Active and pending

    这个中断已被响应,再一次的中断正在被pending

    GIC中断处理状态机如下:

    image.png

    七、GIC中断周期

    GIC中断处理基于GIC中断生命周期,中断生命周期为描述中断处理过程,包括:

    1、Generate interrupt

    外设或软件产生一个中断。

    2、Distribute

    IRI(Interrupt Router Interface)实现中断分组、中断优先级控制、并控制中断转发到CPU接口。PPI/SGI是各个Core独有的中断,不参与目的Core仲裁。SPI是所有Core共享的,根据配置决定中断发往的Core。最后选择优先级最高的中断发给CPU interface。寄存器用GICD_做前缀。

    3、Deliver

    CPU接口将中断发给PE。将GICD发送的中断信息,通过IRQ、FIRQ引脚传输给Core。寄存器使用GICC_做前缀。

    4、Activate

    PE通过读取GICC_IAR寄存器识别中断,设置最高优先级的SGI/PPI/SPI中断为激活状态。

    5、Priority drop

    PE通过配置GICC_EOIR寄存器,实现优先级重置。

    6、Deactivation

    PE通过配置GICC_DIR寄存器,使该中断无效。

    中断生命周期流程如下:

    image.png

    参考:

    https://developer.arm.com/documentation/ka002107/1-0

    IHI0048B_b_gic_architecture_specification.pdf

    IHI0069H_gic_architecture_specification.pdf

    相关文章

      网友评论

          本文标题:ARM GIC介绍

          本文链接:https://www.haomeiwen.com/subject/bypxrdtx.html