Cortex-R52:GIC

   一、基本概念

        GIC(Generic Interrupt Controller)用于管理中断;在R52中,GIC版本为GIC v3,支持如下功能:

  • 中断优先级管理
  • 路由中断到core 或者输出到port
  • 中断抢占
  • 中断虚拟化

        在R52中,GIC有如下构成:

  • 一个GIC Distributor,每个Distributor中有一个Redistributor对应每个核;
  • 一个CPU interface对应每个核

        总结下来,即假设当前R52使用最高配置,有4个核,注意都是单核簇。这个处理器就包含了1个Distributor、4个Redistributor、4个CPU interface,结构如下:

       所以对于一个系统来说,通常只有一个GIC,这个GIC的memory map如下:

         针对与CPU interface,只能是每个核单独去配置,必须使用协处理器进行配置。如下:

        这每个部件是干啥的呢?根据Arm® Generic Interrupt Controller Architecture Specification
GIC architecture version 3 and version 4描述,我们进一步分析:

         上图可以看到,总共出现了SPI、PPI、SGI和LPI给了GIC,我们首先看下各自路径:

  1. SPI通过Distributor分发给不同的Redistributor,再由redistributor分发给CPU interface,最后交由PE(Process element)处理;
  2. PPI直接交由redistributor分发;
  3. SGI是由一个PE产生直接透传给Distributor,分发到不同的PE里去;
  4. LPI 根据亲和度指定路由到某个PE上,R52中暂时没有用到;

        了解了路径,我们来看这些名词的缩写,

名词 解释 在R52中的ID 备注
SPI         Shared Peripheral Interrupt

INTID32(SPI[0])-INTID991(SPI[959])

(最多960SPI可配)

上升沿触发 or 高电平触发

在R52有种硬件机制可以极低延迟将SPI路由到其他PE;INTID(32x+32)~INTID(32x+63)

例如,x=1,那么对于core1,就有INTID64~95的SPI是低延迟的路由

PPI         Private Peripheral Interrupts

INTID16~INTID31每个核

上升沿触发 or 低电平触发

1、意味着每个核都有自己的INTID16-31 PPI

2、PPI有固定分配,如下

未分配的PPI可作为SPI的进行触发 

SGI Software Generated Interrupts

INTID0~INTID15每个核

软件触发类似外设中断的边沿触发

通过写SGI生成系统寄存器产生中断

         通过上述描述,假设现在有4个核,那么每个核都有16个SGI、16个PPI,同时SPI960个共享,其中INTID(32x+32)~INTID(32x+63)对于对应核都是低延迟的。

二、GIC寄存器初识

        上面我们了解到GIC由三大部分构成,那么对应的每个部分应该都有寄存器要配置,特别是GIC的功能。那么我们根据GIC结构来看,有哪些寄存器要处理。

2.1 Distributor

        在R52 TRM里,Distributor 的相关寄存器简写为GICD_xxx,属于RW类型的有:

名字  描述 作用

GICD_CTLR

0x0000

Distributor Control Register

1、使能Group0、Group1

在R52中,Group0 处理 FIQ,Group1处理IRQ

2、CICD_CTLR和ICENABLER状态寄存器写操作pending指示

GICD_IGROUPR1-30

0x0084-0x00F8

Interrupt Group Register                

用于控制SPI属于Group0还是Group1

总共30个寄存器,30*32 = 960

GICD_ISENABLER1-30

0x0104-0x0178

Interrupt Set-Enable Registers

使能SPI路由功能,默认是关闭的,因此配置时要打开,

写1打开,写0无效

读出得到0表示关闭 读出得到1表示使能

GICD_ICENABLER1-30

0x0184-0x01F8

Interrupt Clear-Enable Registers

关闭SPI路由功能,

写1关闭,写0无效

读出得到0表示关闭,读出得到1表示打开

GICD_ISPENDR1-30

0x0204-0x0278

Interrupt Set-Pending Registers

设置SPI的pending标志位(需要了解一个中断的生命周期)

写1设置pending,写0无效

读1表示pending,读0表示没有pending

GICD_ICPENDR1-30

0x0284-0x02F8

Interrupt Clear-Pending Registers

清除SPI pending标志

方式如上

GICD_ISACTIVER1-30

0x0304-0x0378

Interrupt Set-Active Registers

设置SPI的激活标志

方式如上

GICD_ICACTIVER1-30

0x0384-0x03F8

Interrupt Clear-Active Registers

清除SPI的激活标志

方式如上

GICD_IPRIORITYR8-247

0x0420-0x07DF

Interrupt Priority Registers

设置SPI的优先级,5bit位域的优先级(0-31),值越小优先级越高,相同优先级的中断,越低的ID越先处理

一共240个寄存器,一个寄存器可以配置4个SPI的优先级,依次对应;例如reg8对应SPI32、33、34、35的优先级配置

GICD_ICFGR2-61

0x0C08-0x0CF4

Interrupt Configuration Registers

配置SPI触发方式,2bit,高位有效,地位保留

0x :高电平触发

1x:上升沿触发

60*16 = 960个中断配置

GICD_IROUTER32-991

0x6100-0x7EF8

Interrupt Routing Registers 根据affinity提供路由信息

        上面这个表,很晕,主要还是因为有960个SPI,对每个SPI的配置需要多个寄存器来完成,例如优先级、中断激活、pending、使能等,最重要的还有一个路由,我们可以看到,路由寄存器总共有960个,意味着每个SPI都有一个寄存器来处理。

        除此之外,我们可以看到寄存器之间的memmap不是连续的,例如GICD_ISENABLER寄存器是从1开始的,那GICD_ISENABLER0是表示啥呢?思考一下,这里面还有SGI和PPI的配置啊,由于GICD没办法对Redistributor操作,因此,在TRM Redistributor那一章,我们可以看到GICR_ISENABLER0的地址为gicr_base + 0x0100。而这里地址不连续是为了代码中更方便定位寄存器?

2.2 Redistributor

        Redistributor在系统里是全局的,意味着在core0的程序里可以配置core1的PPI使能。

同理,我们来以Redistributor0为例,来看哪些寄存器可以配置

名字  描述 作用

GICR_WAKER

0x0014

Redistributor Wake Register

1、设置Redistributor的休眠唤醒,

bit2:ChildrenAsleep:0没有休眠,1休眠,默认值

bit1:ProcessorSleep:写0 关闭休眠状态,影响bit2;写1进入procesor sleep,默认值

GICD_IGROUPR0

0x0080

Interrupt Group Register                

用于控制SGI、PPI属于Group0还是Group1

总共1个寄存器,32bit 对应32个中断

GICD_ISENABLER0

0x0100

Interrupt Set-Enable Registers

使能SPI路由功能,默认是关闭的,因此配置时要打开,

写1打开,写0无效

读出得到0表示关闭 读出得到1表示使能

GICD_ICENABLER0

0x0180

Interrupt Clear-Enable Registers

关闭SPI路由功能,

写1关闭,写0无效

读出得到0表示关闭,读出得到1表示打开

GICD_ISPENDR0

0x0200

Interrupt Set-Pending Registers

设置SPI的pending标志位(需要了解一个中断的生命周期)

写1设置pending,写0无效

读1表示pending,读0表示没有pending

GICD_ICPENDR0

0x0280

Interrupt Clear-Pending Registers

清除SPI pending标志

方式如上

GICD_ISACTIVER0

0x0300

Interrupt Set-Active Registers

设置SPI的激活标志

方式如上

GICD_ICACTIVER0

0x0380

Interrupt Clear-Active Registers

清除SPI的激活标志

方式如上

GICD_IPRIORITYR

0x0400-0x041C

Interrupt Priority Registers

设置SPI的优先级,5bit位域的优先级(0-31),值越小优先级越高,相同优先级的中断,越低的ID越先处理

一共8个寄存器,一个寄存器可以配置4个SPI的优先级,依次对应

GICD_ICFGR

0x0C00

Interrupt Configuration Registers

配置SPI触发方式,2bit,高位有效,地位保留

0x :高电平触发

1x:上升沿触发

GICD_ICFGR1

0x0C04

Interrupt Configuration Registers

配置SPI触发方式,2bit,高位有效,地位保留

0x :高电平触发

1x:上升沿触发

 2.3 CPU interface

        cpu interface的寄存器是每个核的,从memmap上是看不到地址的,因此用协处理器进行访问

        这个太多了,就不多说了,看TRM吧

三、总结

        GIC对于软件开发的难点在于理解GICD\GICR之间的映射关系;例如GICD有很多寄存器地址是不连续的,如果看GICR的寄存器地址就很容易误解GICR寄存器穿插在GICD里,其实不然,GICR在GIC的memmap中共有5个,分别不同的基地址,而GICR的偏移是基于这个基地址来的。

猜你喜欢

转载自blog.csdn.net/djkeyzx/article/details/132317747
GIC
52