Cortex-R52:GIC

   1. Basic concepts

        GIC (Generic Interrupt Controller) is used to manage interrupts; in R52, the GIC version is GIC v3, which supports the following functions:

  • Interrupt priority management
  • Route interruption to core or output to port
  • Interrupt preemption
  • Disrupt virtualization

        In R52, GIC has the following composition:

  • A GIC Distributor, each Distributor has a Redistributor corresponding to each core;
  • One CPU interface corresponds to each core

        To sum up, it is assumed that the current R52 uses the highest configuration and has 4 cores. Note that they are all single-core clusters. This processor contains 1 Distributor, 4 Redistributors, and 4 CPU interfaces. The structure is as follows:

       So for a system, there is usually only one GIC, and the memory map of this GIC is as follows:

         For the interface with the CPU, each core can only be configured individually, and a coprocessor must be used for configuration. as follows:

        What does each of these parts do? According to the Arm® Generic Interrupt Controller Architecture Specification
GIC architecture version 3 and version 4 description, we further analyze:

         As you can see in the picture above, a total of SPI, PPI, SGI and LPI appear for GIC. Let’s first look at their respective paths:

  1. SPI is distributed to different Redistributors through Distributor, and then distributed to CPU interface by redistributor, and finally handed over to PE (Process element) for processing;
  2. PPI is distributed directly to the redistributor;
  3. SGI is generated by a PE and is directly transmitted to the Distributor and distributed to different PEs;
  4. LPI specifies routing to a certain PE based on affinity, which is not currently used in R52;

        Now that we understand the path, let’s look at the abbreviations of these nouns,

noun explain ID in R52 Remark
SPI         Shared Peripheral Interrupt

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

(Up to 960SPI can be configured)

Rising edge trigger or high level trigger

There is a hardware mechanism in R52 that can route SPI to other PEs with extremely low latency; INTID(32x+32)~INTID(32x+63)

For example, x=1, then for core1, there are SPIs of INTID64~95 which are low-latency routes.

PPI         Private Peripheral Interrupts

INTID16~INTID31 for each core

Rising edge trigger or low level trigger

1. It means that each core has its own INTID16-31 PPI

2. PPI has a fixed allocation, as follows

Unallocated PPI can be triggered as SPI 

SGI Software Generated Interrupts

INTID0~INTID15 for each core

Software triggers edge triggering similar to peripheral interrupts

Generate an interrupt by writing to the SGI generation system register

         Through the above description, assuming that there are 4 cores now, each core has 16 SGIs, 16 PPIs, and SPI960 shares at the same time, of which INTID (32x+32)~INTID (32x+63) are low for the corresponding cores delayed.

2. First introduction to GIC registers

        We learned above that GIC consists of three parts, so each corresponding part should have registers to configure, especially the functions of GIC. So let's look at the GIC structure and see which registers need to be processed.

2.1 Distributor

        In R52 TRM, the abbreviation of Distributor related registers is GICD_xxx, and the ones belonging to RW type are:

name  describe effect

GICD_CTLR

0x0000

Distributor Control Register

1. Enable Group0 and Group1

In R52, Group0 handles FIQ and Group1 handles IRQ

2. CICD_CTLR and ICENABLER status register write operation pending instructions

GICD_IGROUPR1-30

0x0084-0x00F8

Interrupt Group Register                

Used to control whether SPI belongs to Group0 or Group1

Total 30 registers, 30*32 = 960

GICD_ISENABLER1-30

0x0104-0x0178

Interrupt Set-Enable Registers

Enable SPI routing function. It is turned off by default, so it must be turned on during configuration.

Write 1 to open, write 0 to have no effect

Reading out 0 means it is closed. Reading out 1 means it is enabled.

GICD_ICENABLER1-30

0x0184-0x01F8

Interrupt Clear-Enable Registers

Turn off SPI routing function,

Write 1 to turn off, write 0 to have no effect

Reading out 0 means closed, reading out 1 means open.

GICD_ISPENDR1-30

0x0204-0x0278

Interrupt Set-Pending Registers

Set the pending flag of SPI (need to understand the life cycle of an interrupt)

Writing 1 sets pending, writing 0 has no effect.

Reading 1 means pending, reading 0 means there is no pending

GICD_ICPENDR1-30

0x0284-0x02F8

Interrupt Clear-Pending Registers

Clear SPI pending flag

As above

GICD_ISACTIVER1-30

0x0304-0x0378

Interrupt Set-Active Registers

Set the SPI activation flag

As above

GICD_ICACTIVER1-30

0x0384-0x03F8

Interrupt Clear-Active Registers

Clear the active flag of the SPI

As above

GICD_IPRIORITYR8-247

0x0420-0x07DF

Interrupt Priority Registers

Set the priority of SPI, the priority of 5-bit bit field (0-31). The smaller the value, the higher the priority. For interrupts of the same priority, the lower the ID, the earlier it will be processed.

一共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的偏移是基于这个基地址来的。

 

Guess you like

Origin blog.csdn.net/djkeyzx/article/details/132317747