LINUX-I.MX6U从零开始之1.6--中断

一,Cortex-A7 中断系统

Cortex-A7 内核有 8 个异常中断
在这里插入图片描述
复位中断(Rest), CPU 复位以后就会进入复位中断, 我们可以在复位中断服务函数里面做一些初始化工作,比如初始化 SP 指针、DDR 等等。
未定义指令中断(Undefined Instruction),如果指令不能识别的话就会产生此中断。
软中断(Software Interrupt,SWI),由 SWI 指令引起的中断,Linux 的系统调用会用 SWI 指令来引起软中断,通过软中断来陷入到内核空间。
指令预取中止中断(Prefetch Abort),预取指令的出错的时候会产生此中断。
数据访问中止中断(Data Abort),访问数据出错的时候会产生此中断。
IRQ 中断(IRQ Interrupt),外部中断,前面已经说了,芯片内部的外设中断都会引起此中断的发生。
FIQ 中断(FIQ Interrupt),快速中断,如果需要快速处理中断的话就可以使用此中。
我们常用的就是复位中断和 IRQ 中断,Cortex-A 内核 CPU 的所有外部中断都属于IQR 中断。
在这里插入图片描述

二,中断控制器GIC
2.1 GIC框架

GIC 有 4 个版本:V1~V4,V1 是最老的版本,已经被废弃了。GIC V2 是给 ARMv7-A 架构使用的,比如 Cortex-A7、Cortex-A9、Cortex-A15 等,V3 和 V4 是给 ARMv8-A/R 架构使用的,也就是 64 位芯片使用的。
ARM 针对 GIC V2 开发出了 GIC400 这个中断控制器 IP 核。当 GIC 接收到外部中断信号以后就会报给 ARM 内核,但是ARM 内核只提供了四个信号给 GIC 来汇报中断情况:
VFIQ:虚拟快速 FIQ。
VIRQ:虚拟快速 IRQ。
FIQ:快速中断 IRQ。
IRQ:外部中断 IRQ。
在这里插入图片描述
GICV2 的逻辑图如图所示:
在这里插入图片描述
左侧部分就是中断源,中间部分就是 GIC 控制器,最右侧就是中断控制器向处理器内核发送中断信息。中间 GIC 部分将众多的中断源分为分为三类:
①、SPI(Shared Peripheral Interrupt),共享中断,顾名思义,所有 Core 共享的中断,这个是最
常见的,那些外部中断都属于 SPI 中断(注意!不是 SPI 总线那个中断) 。比如按键中断、串口中断等等,这些中断所有的 Core 都可以处理,不限定特定 Core。
②、PPI(Private Peripheral Interrupt),私有中断,我们说了 GIC 是支持多核的,每个核肯定有自己独有的中断。 这些独有的中断肯定是要指定的核心处理, 因此这些中断就叫做私有中断。
③、SGI(Software-generated Interrupt),软件中断,由软件触发引起的中断,通过向寄存器GICD_SGIR 写入数据来触发,系统会使用 SGI 中断来完成多核之间的通信。

2.2 中断 ID

中断源有很多,为了区分这些不同的中断源肯定要给他们分配一个唯一 ID,这些 ID 就是中断 ID。每一个 CPU 最多支持 1020 个中断 ID,中断 ID 号为 ID0~ID1019。这 1020 个 ID 包含了 PPI、SPI 和 SGI.
ID0~ID15:这 16 个 ID 分配给 SGI。
ID16~ID31:这 16 个 ID 分配给 PPI。
ID32~ID1019:这 988 个 ID 分配给 SPI,像 GPIO 中断、串口中断等这些外部中断。
I.MX6U 的总共使用了 128 个中断 ID,加上前面属于 PPI 和 SGI 的 32 个 ID,I.MX6U 的中断源共有 128+32=160个。
128 个中断 ID 对应的中断在《I.MX6ULL 参考手册》的“3.2 Cortex A7 interrupts”小节。
MCIMX6Y2C.h里的枚举类型 IRQn_Type,枚举出了 I.MX6U 的所有中断。

2.3 GID逻辑分块

GIC 架构分为了两个逻辑块: Distributor 和 CPU Interface, 也就是分发器端和 CPU 接口端。
例程“9_int”(原子LINUX),core_ca7.h 定义了 GIC 结构体。
结构体第 5 行是 GIC 的分发器端相关寄存器,其相对于 GIC 基地址偏移为 0X1000,获取到GIC 基地址以后只需要加上 0X1000 即可访问 GIC 分发器端寄存器。
结构体第 51 行是 GIC 的 CPU 接口端相关寄存器,其相对于 GIC 基地址的偏移为 0X2000,获取到 GIC 基地址以后只需要加上 0X2000 即可访问 GIC 的 CPU 接口段寄存器。

2.3.1 Distributor( 分发器端)

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

2.3.2 CPU Interface(CPU 接口端)

CPU 接口端听名字就知道是和 CPU Core 相连接的,因此每个 CPU Core 都可以在 GIC 中找到一个与之对应的 CPU Interface。CPU 接口端就是分发器和 CPU Core 之间的桥梁,CPU 接口端主要工作如下:
①、使能或者关闭发送到 CPU Core 的中断请求信号。
②、应答中断。
③、通知中断处理完成。
④、设置优先级掩码,通过掩码来设置哪些中断不需要上报给 CPU Core。
⑤、定义抢占策略。
⑥、当多个中断到来的时候,选择优先级最高的中断通知给 CPU Core。

2.4 CP15 协处理器

关于 CP15 协处理器和其相关寄存器的详细内容请参考下面两份文档:
《ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf》第 1469 页“B3.17
Oranization of the CP15 registers in a VMSA implementation” 。
《Cortex-A7 Technical ReferenceManua.pdf》第 55 页“Capter 4 System Control” 。
CP15 协处理器一般用于存储系统管理,但是在中断中也会使用到,CP15 协处理器一共有
16 个 32 位寄存器。CP15 协处理器的访问通过指令完成
在这里插入图片描述

三,中断使能
3.1 IRQ 和 FIQ 总中断使能

寄存器 CPSR 的 I=1 禁止 IRQ,当 I=0 使能 IRQ;F=1 禁止 FIQ,F=0 使能 FIQ。
我们还有更简单的指令来完成 IRQ 或者 FIQ 的使能和禁止.
在这里插入图片描述

3.2 ID0~ID1019 中断使能和禁止

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 中断的。

四,中断优先级设置
4.1 优先级数

Cortex-A7 最多可以支持 256 个优先级,数字越小,优先级越高!I.MX6U 选择了 32 个优先级。在使用中断的时候需要初始化 GICC_PMR 寄存器,此寄存器用来决定使用几级优先级。
GICC_PMR 寄存器只有低 8 位有效,这 8 位最多可以设置 256 个优先级。
I.MX6U 支持 32 个优先级,所以 GICC_PMR 要设置为 0b11111000。

4.2 抢占优先级和子优先级位数设置

抢占优先级和子优先级各占多少位是由寄存器 GICC_BPR 来决定的。
寄存器GICC_BPR只有低3位有效, 其值不同, 抢占优先级和子优先级占用的位数也不同。
在这里插入图片描述
为了简单起见,一般将所有的中断优先级位都配置为抢占优先级,比如 I.MX6U 的优先级位数为 5(32 个优先级), 所以可以设置 Binary point 为 2, 表示 5 个优先级位全部为抢占优先级。

4.3 优先级设置

前面已经设置好了 I.MX6U 一共有 32 个抢占优先级,数字越小优先级越高。具体要使用某个中断的时候就可以设置其优先级为 0~31。某个中断 ID 的中断优先级设置由寄存器D_IPRIORITYR 来完成,前面说了 Cortex-A7 使用了 512 个中断 ID,每个中断 ID 配有一个优先级寄存器,所以一共有 512 个 D_IPRIORITYR 寄存器。如果优先级个数为 32 的话,使用寄存器 D_IPRIORITYR 的 bit7:4 来设置优先级,也就是说实际的优先级要左移 3 位。比如要设置ID40 中断的优先级为 5,示例代码如下:

GICD_IPRIORITYR[40] = 5 << 3;

五,core_ca7.h

core_ca7.h中关于中断主要有10个函数:

个人理解(如有错误,还望留言指正)

I.MX6U 有很多中断,这里主要说的是IRQ总中断,串口中断啥的都在里面,有中断就有中断源,中断源由中断ID配置。GID逻辑分块是配置中断模式和中断优先级的,而中断模式地址是由 CP15 协处理器获得。
设置 GICC_PMR,配置优先级个数, I.MX6U 支持 32 级优先级。
设置抢占优先级和子优先级位数,将所有的位数都设置为抢占优先级。
设置指定中断 ID 的优先级,也就是设置外设优先级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值