天天看点

【Linux中断子系统】学习中断必备的基础知识之GIC控制器通用中断控制器GIC

通用中断控制器GIC

1.1 GIC简介

GIC 的全称是 generate interrupt controller,即 通用中断控制器。它是由 ARM公司 开发的一个 中断硬件IP,主要用于管理外设中断。

中断为什么需要管理呢?要解决这个问题,我们需要知道 ARM核CPU 的一些小知识。在我们的 ARM核 上,其实只有 2根 中断线,也就是 IRQ(普通中断) 和 FIQ(快速中断),我们一个SoC 有许多许多个片上外设,这些片上外设如串口UART、I2C总线 等等都需要使用到中断,但是我们只有 2根 中断线。CPU 要如何才能接收各种各样的外设中断呢?那么这个工作就交给我们的 GIC ,它负责连接到各个外设,接收各个外设的中断,并对这个中断进行仲裁,优先级高的中断的信息能够通过CPU的中断线发送到CPU上,从而引发CPU中断。如下图所示

【Linux中断子系统】学习中断必备的基础知识之GIC控制器通用中断控制器GIC

而GIC 和 CPU 的交互是通过访问对方寄存器,获取对相应的信息,如中断状态或者上报中断信息等,从而实现信息交互的功能,如下图所示:

【Linux中断子系统】学习中断必备的基础知识之GIC控制器通用中断控制器GIC

1.2 GIC及中断术语

1.2.1 GIC组成

我们从上图可以看到,GIC 主要由 Distributor 和 CPU Interface 这 2 个模块组成

Distributor 的作用是用于中断路由,即对中断进行配置及对中断进行仲裁,其主要工作如下:

  • 使能中断
  • 中断优先级配置
  • 中断触发方式配置
  • 中断CPU路由,即对于多核 CPU,决定中断发往哪个 CPU

    记录每个中断的状态,即是否到来,是否处理中,是否处理完,是否在等待发送状态等等。

CPUInterfac作用是与 CPU 进行中断信息的交互,其主要工作是:

  • 使能和发送一个具体的中断信号到特定对应的CPU上,
  • 中断状态确认,包括中断已经被CPU接受,处理,以及处理完成。
  • 中断仲裁。即根据中断优先级发给不同的CPU,或者进行中断抢占等等

中断信号的传送过程为:

  1. 中断信号先到 distributor
  2. 根据该中断设定的目标CPU,送到CPU对应的 CPU Interface 上
  3. 在 CPU Interface 进行中断仲裁。具体流程为判断中断是否优先级足够高,是否可以抢断或者打断当前的中断处理。如果可以,那么 CPU Interface 就发送一个 中断物理信号 到CPU的 中断线(IRQ或FIQ) 上。CPU感知到中断信号,从而转到中断模式进行处理。

1.2.2 中断类型

  • SPI: shared peripheral interrupt , 即共享中断,是常见的外部设备中断。共享的意思是说可以多个Cpu或者说Core处理,不限定特定的Cpu。一般定义的硬件中断号范围 31~1019。共享中断的数量可以通过对 GIC 进行配置来设定
  • PPI: private peripheral interrupt,即私有中断。此类中断产生的中断信号只发送给这个特定的cpu进行处理。一般定义的硬件中断号范围 16~31
  • SGI: software generatedinterrupt ,即软件中断,此类中断一般用于多核 CPU 之间的通信,是软件出发产生的中断,中断号范围 0~15

设备树节点的中断号属性 一般要减去 32,笔者的理解是:因为前32个中断不是共享中断,而一般外设中断都是共享中断

1.2.3 中断状态

  • Inactive:当GIC上配置的中断,配置好之后,没有其对应的中断到来。或者正在处理的中断已经结束,并且 CPU 操作了 GICC_EOIR 寄存器(该过程叫中断完成),那么此时中断处于 inactive 状态
  • Pending:如果中断信号到来,GIC获取到了,这个时候要经过一系列的的判断,然后送给对应的CPU来处理。在CPU确认该中断并处理之前,中断将处理 pending 状态
  • active:当 CPU 接收到中断后,并且读取到 GICD_IAR 寄存器中的中断号(该过程叫中断认可),那么中断会进入 active 状态。
  • pending and active:当中断处于 pending 或 active 状态时,又产生了一个 同样的 中断信号,此时会进入该状态

下面是 giv-v2 的中断状态机,上面的描述是相对简单一点的,有兴趣的朋友请阅读手册了解

【Linux中断子系统】学习中断必备的基础知识之GIC控制器通用中断控制器GIC

1.2.4 中断流程

  1. GIC 决定每个中断的使能状态。不使能的中断,是不能发送中断信号到 CPU
  2. 如果某个中断的中断源有效,GIC将该中断的状态设置为 pending状态 ,然后判断该中断的 目标CPU
  3. 对于每一个 CPU, GIC 将当前处于 pending状态 的优先级最高的中断,发送给对应CPU的 cpu interface, cpu interface 接收 GIC 发送的 中断请求,判断优先级是否满足要求,如果满足,就将中断通过 nFIQ 或 nIRQ管脚,发送给 CPU。
  4. CPU 响应该中断,通过读取 GICC_IAR寄存器,来认可该中断。读取该寄存器,如果是软中断,返回源处理器ID,否则返回中断号。
  5. 当 CPU 认可该中断后,GIC 将该中断的状态,修改为 active状态
  6. 当 CPU 完成该中断后,通过写 **EOIR(end of interrupt register)**来实现优先级重置,再通过写 GICC_DIR寄存器,来无效该中断

当然了,GIC 的功能不只上面所说,它还包括了 中断优先级设置,中断目标CPU设置,中断组设置 等等功能,这些功能的实现都是通过操作 GIC 的寄存器来实现。对于 GIC 有兴趣的同学可以找到官方文档进行阅读

  • 《GIC-400 Generic Interrupt Controller Technical Reference Manual》
  • 《Generic Interrupt Controller Architecture version 2.0 Architecture Specification》