5、GIC中断控制器

  当处理器收到中断,它会停下当前正在做的任务,然后跳转到需要处理的地方去。这和轮询的方式是相反的,轮询是由软件同步获取设备的状态。在中断方式中,不需要由处理器不断地轮询设备的 I/O 端口来查看是否需要处理,设备本身会进入中断处理器。中断(主要是硬件中断)可以进一步被分类为以下几种类型:

  (1)可屏蔽中断( Maskable Interrupts, IRQ)

  可通过在中断屏蔽寄存器中设定位掩码来关闭。触发可屏蔽中断的事件源不总是重要的。程序设计人员需要决定该事件是否应该导致程序跳到所需处理的地方去。使用可屏蔽中断的设备包括定时器、比较器和 ADC。

  (2)不可屏蔽中断( Non-Maskable Interrupts, NMI)

  无法通过在中断屏蔽寄存器中设定位掩码来关闭。这些是不可忽视的中断。 NMI 的事件包括上电、外部重启(用实际的按钮)和严重的设备失效。

  (3)处理器间中断( Inter-Processor Interrupts, IPI)

  在多处理器系统中,一个处理器可能需要中断另一个处理器的操作。在这种情况下,就会产生一个 IPI,以便于处理器间通信或同步。

  Zynq 芯片的 PS 部分是基于使用双核 Cortex-A9 处理器GIC pl390 中断控制器的 ARM 架构。中断结构与 CPU 紧密链接,并接受来自 I/O 外设( IOP)和可编程逻辑( PL)的中断。中断控制器架构如下图所示:

 

  从图中可以看到, CPU 接收的中断来源有三种,分别是私有外设中断( private peripheral interrupts, PPI)、软件生成的中断( software generated interrupts, SGI)和共享外设中断( shared peripheral interrupts、 SPI)

  每个 CPU 都有一组私有外设中断,使用存储寄存器进行私有访问。 PPI 包括全局定时器、专用看门狗定时器( AWDT)、专用定时器和来自 PL 的 FIQ/IRQ。

  软件生成的中断通过 SGI 分配(派)器分配给一个或两个 CPU。

  共享外设中断由 PS 和 PL 中的各种 I/O 和存储控制器生成。它们被路由到任一个或两个 CPU,来自 PS 外设的 SPI 中断也可以路由到 PL。

  下面我们从下图的系统级中断环境来进一步了解中断:

  首先我们来看通用中断控制器。通用中断控制器是一个用于集中管理从 PS 和 PL 发送到 CPU 的中断,启用、禁用、屏蔽和优先化中断源的处理中心,将具有最高优先级的中断源分配给各个 CPU 之前集中所有中断源,并在 CPU 接口接受下一个中断时以编程方式将它们发送到选定的 CPU。此外,控制器还支持用于实现安全感知系统的安全扩展。该控制器基于非矢量化的 ARM 通用中断控制器架构版本 1.0( GIC v1)。GIC 寄存器通过 CPU 私有总线访问寄存器,以避免临时阻塞或互连中的瓶颈,从而实现快速读/写响应。GIC 确保针对多个 CPU 的中断一次只能由一个 CPU 占用。所有中断源都由唯一的中断 ID 号标识,对应有它自己的可配置优先级和目标 CPU 列表。

  接下来我们依次来看软件生成中断、 CPU 私有外设中断和共享外设中断。

  每个 CPU 都可以使用软件生成的中断来中断自身、另一个 CPU 或同时中断两个 CPU。有 16 个软件生成中断,具体见表 4.1.1。向软件产生的中断寄存器( Software Generated Interrupts Register, ICDSGIR)写入 SGI 中断编号并指定目标 CPU(或两个 CPU),就产生了一个 SGI。该写操作通过 CPU 自己的专用(私有)总线进行。每个 CPU 都有自己的一组 SGI 寄存器,用于生成 16 个软件生成的中断中的一个或多个。

  中断的清除是通过读取中断确认寄存器( Interrupt Acknowledge Register, ICCIAR)或向中断挂起清除寄存器( Interrupt Clear-Pending Register, ICDICPR)对应的位写入“ 1”来实现的。

  所有的 SGI 都是边缘触发的,且其敏感性类型是固定的,不能修改。只读的 ICDICFR0 寄存器指定了所有 16 个 SGI 的灵敏度类型。

  每个 CPU 核连接到了一个有五个外设中断的私有组上,这五个外设中断见表 4.1.2。 PPI 的敏感类型是固定的,不能改变。需要注意的是:来自 PL 的快速中断( FIQ)信号和中断( IRQ)信号在发送给中断控制器之前,会在传输给 PS 的时候被反转。因此,这些信号因此在 PL 内低电平有效,在 PS-PL 接口处高电平有效。

  来自各种模块的大约 60 个中断的组可以被路由到 PL 或 CPU 中的一个或两个,这 60 个中断见表 4.1.3。

  那些目标为 CPU 的中断的优先级和中断的接收情况是由中断控制器管理的。除 IRQ# 61 至# 68 和# 84 至# 91 外,所有中断灵敏度类型均由请求源固定,无法更改。必须对 GIC 进行编程以适应这种情况。 Boot ROM不编程这些寄存器。因此, SDK 设备驱动程序必须对 GIC 进行编程以适应这些敏感类型。

  对于电平敏感类型的中断,请求源必须为中断处理程序提供一种机制,以便在确认中断后清除中断。此要求适用于具有高电平敏感类型的任何 IRQF2P [n](来自 PL)。对于上升沿敏感的中断,请求源必须提供足够宽的脉冲以便 GIC 捕获。这通常至少为 2 个 CPU_2x3x 周期。此要求适用于具有上升沿灵敏度类型的任何 IRQF2P [n](来自 PL)。

  了解了软件生成中断 SGI、 CPU 私有外设中断 PPI 和共享外设中断 SPI 后,我们来看下中断优先级定序。

  所有的中断请求,无论是 PPI、 SGI 还是 SPI,都分配了一个唯一的 ID 编号,以用于中断控制器的仲裁。中断分派(配)器保存每个 CPU 的中断挂起列表,并从中选择优先级最高的中断,然后把它发送到 CPU 接口。如果具有相同优先级的两个中断同时到达,具有最低中断 ID 的会首先被发送。

  每个 CPU 都存在着优先级定序逻辑,所以对最高优先级中断的选择是每个 CPU 各自进行的。中断分配器具有中断、处理器和活跃信息的中央列表,并负责触发 CPU 的软件中断。为了给每个处理器提供单独的副本, SGI 和 PPI 分派器寄存器是分组的。硬件确保针对多个 CPU 的中断同一时间只能被一个 CPU 获取。

  在发送挂起的最高优先级的中断给 CPU 接口后,中断分配器会从该 CPU 收到中断已被确认的消息,这样它就可以改变对应的中断的状态。只有确认中断的 CPU 才能结束该中断。

  以上我们大概了解了 ZYNQ 的中断,下面我们来看作为 GPIO 的 MIO 的中断:

  左边有 7 个寄存器,说明如下:

  INT_MASK:这个寄存器是只读的,显示哪些位当前被屏蔽,哪些位未被屏蔽/启用。

  INT_EN:向该寄存器的任何位写入 1,可以启用/解除中断信号的掩码。从该寄存器读取将返回一个不可预测的值。

  INT_DIS:向该寄存器的任何位写入 1 都会屏蔽该中断信号。从该寄存器读取会返回不可预测的值。

  INT_STAT:该寄存器显示是否发生了中断事件。将 1 写入该寄存器中的某个位可清除该位的中断状态。

  将 0 写入该寄存器中的某个位将被忽略。

  INT_TYPE:该寄存器控制中断是边沿敏感还是电平敏感。

  INT_POLARITY:该寄存器控制中断是低电平有效还是高电平有效(或下降沿敏感或上升沿敏感)。

  INT _ANY:如果 INT_TYPE 设置为边沿敏感, 则该寄存器在上升沿和下降沿都会启用中断事件。如果INT_TYPE 设置为电平敏感,则忽略该寄存器。

  从 INT_TYPE、 INT_POLARITY 和 INT _ANY 寄存器我们可以看到中断触发方式可以是上升沿,下降沿,边沿,低电平或高电平。

  从图 4.1.3 中我们可以看到, INT_TYPE、 INT_POLARITY 和 INT _ANY 控制监视 GPIO 输入信号的中断检测逻辑。如果检测到中断,中断检测逻辑将 GPIO 的 INT_STAT 状态设置为真。如果中断未屏蔽,则中断传输到一个或电路(图中未画出)。该或电路将四个 BANK 中所有 GPIO 的所有中断组合成一个输出( IRQID# 52)到中断控制器。如果中断被禁止(屏蔽),则 INT_STAT 状态将保持直到被清除,但它不会传输到中断控制器,除非稍后写入 INT_EN 以禁用屏蔽。由于所有 GPIO 共享相同的中断,因此软件必须同时考虑 INT_MASK 和 INT_STAT 以确定哪个 GPIO 导致中断。

  通过向 INT_EN 和 INT_DIS 寄存器写入 1 来控制中断屏蔽状态。向 INT_EN 寄存器写入 1 将禁用屏蔽,允许活动中断传输到中断控制器。将 1 写入 INT_DIS 寄存器可启用屏蔽。可以使用 INT_MASK 寄存器读取中断屏蔽的状态。

  如果 GPIO 中断是边沿触发的,则 INT 状态由检测逻辑锁存。通过向 INT_STAT 寄存器写入 1 来清除INT 锁存器。对于电平触发的中断,必须清零 GPIO 中断输入源,以清除中断信号。或者,软件可以使用INT_DIS 寄存器屏蔽该输入。

  可以通过读取 INT_STAT 和 INT_MASK 寄存器来推断进入中断控制器的中断信号的状态。如果INT_STAT = 1 且 INT_MASK = 0,则该中断信号有效。

posted @ 2022-07-10 20:30  孤情剑客  阅读(867)  评论(0编辑  收藏  举报