I.MX6UL 中断控制器GIC浅析

GIC架构简介

GIC是中断管理控制器,类似STM32的NVIC

GIC负责收集中断源并发送给CPU

中断源--->GIC--->CPU

I.MX6UL 中断控制器GIC浅析_第1张图片

问题一:中断源有哪些?

中断源分为三种:

SPI:共享中断(如串口中断,定时器中断等)

PPI:私有中断

SGI:软件中断

为了区分这些中断源引入中断ID

 I.MX6U 的总共使用了 128 +32个中断 ID

ID0~ID15:这 16 个 ID 分配给 SGI。
ID16~ID31:这 16 个 ID 分配给 PPI。

ID32~ID1019:这 988 个 ID 分配给 SPI,像 GPIO 中断、串口中断等这些外部中断 。、

问题二:GIC怎么告诉CPU

GIC 接收众多的外部中断,然后对其进行处理,最终就只通过四个信号报给 ARM 内核,这四个信号的含义如下:
VFIQ:虚拟快速 FIQ。
VIRQ:虚拟快速 IRQ。
FIQ:快速中断 IRQ。
IRQ:外部中断 IRQ。

我们主要关心IRQ

问题三:GIC对中断源都进行什么操作

GIC 架构分为了两个逻辑块:Distributor 和 CPU Interface,也就是分发器端和 CPU 接口端。这两个逻辑块的功能如下:

Distributor( 分发器端) :此逻辑块负责处理各个中断事件的分发问题,也就是中断事件应该发送到哪个 CPU Interface 上去。分发器收集所有的中断源,可以控制每个中断的优先级,它总是将优先级最高的中断事件发送到 CPU 接口端。分发器端要做的主要
工作如下:
①、全局中断使能控制。
②、控制每一个中断的使能或者关闭。
③、设置每个中断的优先级。
④、设置每个中断的目标处理器列表。
⑤、设置每个外部中断的触发模式:电平触发或边沿触发。
⑥、设置每个中断属于组 0 还是组 1。

CPU Interface(CPU  接口端):CPU 接口端听名字就知道是和 CPU Core 相连接的,因此每个 CPU Core 都可以在 GIC 中找到一个与之对应的 CPU Interface。CPU 接口端就是分发器和 CPU Core 之间的桥梁,CPU 接口端主要工作如下:
①、使能或者关闭发送到 CPU Core 的中断请求信号。、

②、应答中断。
③、通知中断处理完成。
④、设置优先级掩码,通过掩码来设置哪些中断不需要上报给 CPU Core。
⑤、定义抢占策略。
⑥、当多个中断到来的时候,选择优先级最高的中断通知给 CPU Core。

问题四,如何操作GIC寄存器?

首先要知道GIC寄存器的地址

GIC寄存器的基地址保存在CP15协处理器的CBAR寄存器中,使用一下命令来获取GIC基地址

MRC p15, 4, r1, c15, c0, 0 ; 获取 GIC 基础地址,基地址保存在 r1 中。

CPU接口端基地址为GIC基地址+0x2000偏移地址

ADD r1, r1, #0X2000  ;GIC 基地址加 0X2000 得到 CPU 接口端寄存器起始地址

GICC_IAR寄存器保存中断ID,其地址为CPU接口端地址+0XC偏移地址

LDR r0, [r1, #0XC] ;读取 CPU 接口端起始地址+0XC 处的寄存器值,也就是寄存器;GIC_IAR 的值

 

问题五:GIC中如何控制中断使能?

使能中断首先要开启IRQ总开关。

如何开启IRQ中断使能

cpsid i  禁止 IRQ 中断。
cpsie i  使能 IRQ 中断。

然后开启各个外部中断开关。

如何使能串口中断,定时器中断,也就是说如何使能128个外部中断

GIC 寄存器 GICD_ISENABLERn 和 GICD_ ICENABLERn 用来完成外部中断的使能和禁止,对于 Cortex-A7 内核来说中断 ID 只使用了 512 个。一个 bit 控制一个中断 ID 的使能,那么就需要 512/32=16 个 GICD_ISENABLER 寄存器来完成中断的使能。同理,也需要 16 个GICD_ICENABLER 寄存器来完成中断的禁止。其中 GICD_ISENABLER0 的 bit[15:0]对应
ID15~0 的 SGI 中断,GICD_ISENABLER0 的 bit[31:16]对应 ID31~16 的 PPI 中断。

剩下的GICD_ISENABLER1~GICD_ISENABLER15 就是控制 SPI 中断的。

问题六:如何设置中断优先级?

GICC_PMR 寄存器只有低 8 位有效,这 8 位最多可以设置 256 个优先级。

11111111  256 个优先级
11111110  128 个优先级
11111100  64 个优先级
11111000  32 个优先级
11110000  16 个优先级

I.MX6U 最多支持 32 个优先级,所以 GICC_PMR 要设置为 0b11111000。

设置抢占优先级和子优先级。

GICC_BPR寄存器决定抢占优先级和子优先级的比例,寄存器GICC_BPR只有低3位有效。

000 :7 级抢占优先级,1 级子优先级。

001:6 级抢占优先级,2 级子优先级。

010:5 级抢占优先级,3 级子优先级。

011:4 级抢占优先级,4 级子优先级。

100:3 级抢占优先级,5 级子优先级。

101:2 级抢占优先级,6 级子优先级。

110:1 级抢占优先级,7 级子优先级。

111:  0 级抢占优先级,8 级子优先级。

 I.MX6U 的优先级位数为 5(32 个优先级),所以可以设置 Binary point 为 2,表示 5 个优先级位全部为抢占优先级。

每个中断ID优先级配置

 I.MX6U 一共有 32 个抢占优先级,数字越小优先级越高。具体要使用某个中断的时候就可以设置其优先级为 0~31。某个中断 ID 的中断优先级设置由寄存器D_IPRIORITYR 来完成。

每个中断 ID 配有一个优先级寄存器,使用寄存器 D_IPRIORITYR 的 bit7:4 来设置优先级

比如要设置ID40 中断的优先级为 5,示例代码如下:

GICD_IPRIORITYR[40] = 5 << 3;

你可能感兴趣的:(I.MX6UL+Linux)