ARM通用中断控制器GIC之中断控制

2023-05-16

在阅读本章之前,可以参考笔者之前关于GIC的一些描述:

ARM通用中断控制器GIC(generic Interrupt Controller)简介

ARM架构Generic Interrupt Controller(GIC)之Distributor和CPU interface功能介绍

ARM架构Generic Interrupt Controller(GIC)详解之术语介绍

ARM通用中断控制器GIC之中断处理简介

文章目录

  • 一,GIC中断使能
  • 二,设置或清除一个中断的Pending状态
    • 2.1 Interrupt Set-Pending Registers, GICD_ISPENDRn
    • 2.2 Interrupt Clear-Pending Registers, GICD_ICPENDRn
  • 三,查找处于active或者pending状态的中断
  • 四,产生SGI中断
    • 4.1 Software Generated Interrupt Register, GICD_SGIR
    • 4.2 安全扩展下产生SGI中断
    • 五,GIC 1-N模型

一,GIC中断使能

对于外设中断,处理器可以通过:

  • 写入GICD_ISENABLERn 寄存器的对应bit来使能该中断。
  • 写入 GICD_ICENABLERn 寄存器的对应bit来禁止该中断。
    对于SGI中断是否能通过上述两个寄存器来enable和disable,这个由具体的实现( IMPLEMENTATION DEFINED)来定义。
    此外写入GICD_ISENABLERn 和GICD_ICENABLERn 寄存器只是控制Distributor是否能将该中断转发到CPU interface,并不会阻止该中断改变状态。比如写入GICD_ICENABLERn 寄存器来disable对应中断,并不能阻止他变成pending状态。

二,设置或清除一个中断的Pending状态

对于外设中断,处理器可以:

  • 写入GICD_ISPENDRn寄存器的对应bit来设置中断状态为pending。
  • 写入 GICD_ICPENDRn寄存器的对应bit来清除该中断的pending状态。
    对于电平敏感的中断:
  • 如果中断信号已经被assert,处理器再写入GICD_ICPENDRn寄存器的对应bit来清除中断将不产生作用。
  • 如果处理器通过写入GICD_ISPENDRn来使对应中断状态变为pending,将忽略该中断的硬件信号,并且保留pending状态,不管该中断是被asserted还是deasserted。
    包含pending的中断状态有两种:
  • pending
  • active and pending
    对于边沿触发的中断来讲,包含pending的中断状态可以通过写入GICD_ISPENDRn寄存器,或者GIC对该中断信号的assertion来进行锁定。
    但是对于电平敏感的中断来讲,它的包含pending的中断状态可以通过写入GICD_ISPENDRn寄存器来锁定,但是不能根据传递到GIC的中断信号来锁定。
    以下是电平敏感中断的电路逻辑示意图:
     Logic of the pending status of a level-sensitive interrupt
    此外,对于SGI中断,GIC将忽略对GICD_ISPENDRn和GICD_ICPENDRn寄存器的写入,处理器不能通过写入这些寄存器来改变SGI中断的中断状态。一般情况下,处理器可以通过写入 GICD_SGIR寄存器来使SGI中断变成pending,在GICv2中,SGI的pending状态可以通过直接写入GICD_SPENDSGIRn 和 GICD_CPENDSGIRn 寄存器的对应位来改变。

2.1 Interrupt Set-Pending Registers, GICD_ISPENDRn

GICD_ISPENDRn寄存器提供一个Set-pending bit,对该bit写入1能够将对应外设中断的状态设置为pending,读取对应bit则可以知道该中断是否处于pending状态。
在多处理器系统中,GICD_ISPENDR0(PPI和SGI)寄存器被每个与GIC相连的处理器banked(复用)。
 GICD_ISPENDR bit assignments
从GICD_ISPENDR0开始,寄存器里每个bit代表一个不同中断ID的中断控制位,比如GICD_ISPENDR0[0]表示控制中断ID为0的中断。
对该寄存器进行读取:

  • 读到0:表明对应中断在任何处理器中都不处于pending状态。
  • 读到1:
    - 对于SGI和PPI中断,当前中断在当前处理器中是pending状态的。
    - 对于SPI中断,当前中断至少在一个处理器中处于pending状态。
    上文提到过,对于SGI中断,写入GICD_ISPENDRn寄存器的操作将会被忽略,因为SGI有自己的Set-pending寄存器 SGI
    Set-Pending Registers, GICD_SPENDSGIRn。对于SPI和PPI中断来讲:
  • 写入0:无影响
  • 写入1:其效果取决于是边缘触发还是电平敏感中断:
    - 边缘触发(Edge-triggered),如果当前中断已经是pending状态,则不受影响;如果之前是inactive状态,则会变成pending状态;如果之前是active状态,则会变成active and pending状态。
    - 电平敏感(Level sensitive),如果当前中断已经是pending状态,如果对应中断信号已经被asserted,写操作将不会改变中断的状态,但是该中断信号被deasserted后该中断将仍保持pending状态;如果对应中断未处于pending状态,如果之前是inactive状态,则会变成pending状态;如果之前是active状态,则会变成active and pending状态。

2.2 Interrupt Clear-Pending Registers, GICD_ICPENDRn

GICD_ICPENDRs为GIC支持的每个中断提供一个Clear-pending bit。写入对应中断的Clear-pending位将清除该中断的pending状态。读取该bit位是否为1可以确定中断是否处于pending状态。
在这里插入图片描述
对该寄存器进行读取:

  • 读到0:表明对应中断在任何处理器中都不处于pending状态。
  • 读到1:
    - 对于SGI和PPI中断,当前中断在当前处理器中是pending状态的。
    - 对于SPI中断,当前中断至少在一个处理器中处于pending状态。
    对于SPI和PPI中断来讲:
  • 写入0:无影响
  • 写入1:其效果取决于是边缘触发还是电平敏感中断:
    - 边缘触发(Edge-triggered),如果中断不处于pending状态,则不受影响。如果之前是pending状态,则会变成inactive状态;如果之前是active and pending状态,则会变成active状态。
    - 电平敏感(Level sensitive),如果当前中断的pending状态是由于写入GICD_ISPENDRn寄存器导致的:如果之前是pending状态,则会变成inactive状态;如果之前是active and pending状态,则会变成active状态。否则,如果中断信号仍被asseted,中断将保持pending状态。

三,查找处于active或者pending状态的中断

若想知道一个中断是否处于pending状态,可以读取 GICD_ISPENDRn 或者GICD_ICPENDRn寄存器。若想知道中断是否处于active状态,可以读取 GICD_ISACTIVERn 或者GICD_ICACTIVERn,这两个寄存器有Set-active和clear-active 位用来控制中断的active状态。

四,产生SGI中断

处理器可以通过写入GICD_SGIR寄存器来产生一个SGI中断,一个SGI中断可以设置多个目标处理器,并且SGIR寄存器里有目标寄存器列表。GICD_SGIR包括如下优化:

  • 只中断写入GICD_SGIR的处理器
  • 中断除写入GICD_SGIR的处理器以外的所有处理器
    来自不同处理器的SGI中断使用同一个中断ID,所以任何目标处理器可以收到来自不同处理器产生的相同中断ID的SGI。但是如果以下条件不同,则任意两个SGI中断的pending状态是独立的:
  • 中断ID
  • 源处理器
  • 目标处理器
    在CPU interface中,在任何时候,一次只能有一个特定中断ID的中断处于active状态,这意味着CPU interface不能同时有两个SGI处于active状态,甚至是不同处理器使用相同中断ID的SGI中断发送中断信号到该处理器。
    在目标处理器的CPU interface中,通过读取 GICC_IAR寄存器,可以获得中断ID,以及产生该中断的CPU ID,即源处理器ID。中断ID加上源处理器ID,可以让目标处理器获知该中断独一无二的来源。
    此外,在多处理器系统中,每个SGI中断的优先级可以为每个目标处理器单独设置,详情可查看 Interrupt Priority Registers, GICD_IPRIORITYRn,中断优先级寄存器。对于每个CPU interface来讲,对于所有优先级相同的,特定中断ID的,处于pending状态的SGI中断,CPU interface序列化地处理它们,具体的系列化处理顺序取决于系统的实现定义(IMPLEMENTATION SPECIFIC.)。

4.1 Software Generated Interrupt Register, GICD_SGIR

处理器写入GICD_SGIR可以产生SGI中断。使用限制:通过写入 GICD_CTLR寄存器来将Distributor的转发功能禁止,是否会影响GICD_SGIR,这个由具体的实现定义( IMPLEMENTATION DEFINED)。以下是GICD_SGIR寄存器的字段分配图:
GICD_SGIR bit assignments

  • [25:24] TargetListFilter:这将决定Distributor如何处理被请求的SGI中断,即要转发到何处:
    - 0b00:将中断转发到在CPUTargetList定义的CPU interface中
    - 0b01:将中断转发到所有CPU interface中,除了当前请求中断的处理器。
    - 0b10:将中断转发到当前请求SGI中断的处理器相连的CPU interface中。
    - 0b11:保留
  • [23:16] CPUTargetList:如果TargetListFilter的值为0b00,CPUTargetList中将定义Distributor必须被转发到的CPU interface。CPUTargetList中共八个bit,每个bit代表一个处理器。比如CPUTargetList[0]对应CPU interface 0,如果CPUTargetList[0]=1,表明该SGI中断必须转发到CPU interface 0。如果TargetListFilter的值为0b00,并且CPUTargetList也为0,说明Distributor不需要将中断转发到任何CPU interface。
  • [15] NSATT:仅在系统包含安全扩展中实现,如果没有实现安全扩展,这个字段将保留。NSATT指定SGI需要的security value:
    - 只有当SGI在该CPU interface上被配置为Group 0时,才将SGIINTID字段中指定的SGI转发到指定的CPU interface。
    - 只有当SGI在该CPU interface上被配置为Group 1时,才将SGIINTID字段中指定的SGI转发到指定的CPU interface。
    - 该字段只可以在安全状态下被写入,只有当指定的SGI中断被配置成group 1时,任何对GICD_SGIR的非安全写入才会生成SGI,并且忽略NSATT的值。
  • [3:0] SGIINTID : 需要被转发到指定的CPU interface中的SGI中断的中断ID,范围是0到15。

4.2 安全扩展下产生SGI中断

如果GIC实现了安全扩展,通过写入GICD_SGIR寄存器,使得SGI中断转发到指定的处理器,这取决于:

  • 写入GICD_SGIR的是Group 0(secure)还是Group 1(non-secure)
  • 对于secure写入SGIR,写入 GICD_SGIR的NSATT字段的值。
  • 在目标处理器中,特定的中断是否被配置成Group 0(secure)还是Group 1(non-secure)。

GICD_IGROUPR0寄存器中保存了SGI中断的安全状态。在多处理器系统中, GICD_IGROUPR0被每个与之相联的处理器banked(复用),所以系统可以为每个处理器独立设置SGI中断的安全状态。对GICD_SGIR寄存器写一次,可以配置多个目标处理器,对于每个目标处理器,Distributor将决定是否将SGI中断转发到该处理器。
下表展示了Distributor是否可以将SGI转发到指定的CPU interface的真值表:
Truth table for sending an SGI to a target processor

五,GIC 1-N模型

GIC在多处理器实现中,会使用1-N模型,处理有多个目标处理器的外设中断,比如SPI。这意味着,这意味着,当GIC从其中一个目标处理器识别出一个中断确认时,它将清除所有其他目标处理器上的中断的pending状态。GIC必须确保使用1-N模型处理的任何中断时,只能被一个CPU interface确认,并且所有其他CPU interface都返回一个虚假中断ID。
当目标处理器试图确认中断时,有两种情况会发生:

  • 处理器读取 GICC_IAR寄存器,并获得需要被服务的中断的ID。在GICv1中,如果多个处理器读取GICC_IAR寄存器的时间非常接近,可以会有多个处理器会获取到该中断ID。系统必修要求在目标处理器上运行的软件来确保只有一个处理器能进行中断服务程序。一种典型的实现方案是使用共享内存,并且在中断服务程序(interrupt service routine,ISR)中加锁。
  • 处理器读取 GICC_IAR寄存器,获取到虚假中断ID:1023。该处理器会从中断服务程序中返回,并且不用写入GICC_EOIR寄存器。读到虚假中断ID,是因为原始的中断不再 处于pending状态,一般是因为有其他目标处理器在处理该中断。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARM通用中断控制器GIC之中断控制 的相关文章

  • 抢占和上下文切换的区别

    一点介绍 我目前正在编写一个小型 读微型 RTOS 内核 它应该与内核中的大多数内容是一体的 然而 我找不到关于下面列出的一些事情的太多信息 这会很有帮助 除此之外 它实际上不是某种大学项目 而是我按照自己的意愿做的事情 回答所有问题的一个
  • 通用 ELF 中的重定位(EM:40)

    我尝试从 Ubuntu 交叉编译到Friendly arm 但出现了奇怪的错误 root kevin VirtualBox home kevin Desktop makef make ARCH arm CROSS COMPILE arm n
  • 多核ARM cpu上的中断如何工作

    这个问题已经针对 x86 得到了解答 但是 我找不到太多关于 ARM MP cpu 如 Cortex A9 Cortex A15 等 的信息 更重要的是我想知道是否可以在非主CPU上引发中断而无需任何配置等 我正在开发一款仅处理主 cpu
  • ARM 汇编不能同时使用立即值和 ADDS/ADCS

    我目前正在尝试使用汇编来加速 Cortex M0 Freescale KL25Z 上的一些 C 函数 我遇到这个最小测试程序的问题 syntax unified cpu cortex m0 text global test code 16
  • arm gcc工具链为arm-elf或arm-none-eabi,有什么区别?

    当您构建 gcc 工具链时 可以将其构建为arm elf 或arm none eabi 但是有什么区别呢 我今天使用 eabi 但这只是因为其他人似乎都这样做 但由于这是一个非常糟糕的论点 因此理解其中的差异真的很高兴 注意 此工具链将为基
  • 使用 GCC 编译器为代码的特定部分保留寄存器

    是否可以为 C 代码的特定部分保留寄存器 ffixed reg 选项或声明全局寄存器变量不是我正在寻找的答案 我想保留特定范围 比如说特定函数 的寄存器值 使用局部寄存器变量是不可能的 因为它不能保证在整个范围内保留寄存器的值 我正在寻找类
  • 将结构体偏移属性赋予汇编器

    如何将 C 结构体的偏移量发送到汇编代码 例如 在我的 C 代码中 typedef struct unsigned int a unsigned int b CMyStruct 我向 ASM 函数发送一个 CMyStruct 结构的指针 假
  • 使用 gnueabihf 为 ARMv6 构建

    我尝试为 ARMv6 构建应用程序 但失败了 我猜问题是工具链支持硬浮点 但 ARMv6 不支持 好吧 首先我设置 march armv6 编译失败 opt gcc linaro arm linux gnueabihf 4 8 2014 0
  • ARM 汇编分支到寄存器或内存内部的地址

    我想知道在 ARM 汇编中我可以使用哪条指令分支到存储在某个内存地址中的地址或标签 例如 我们可以使用B LABEL来跳转到LABEL 但现在目的地只能在运行时知道 并且它存储在某个已知的内存位置 是否有类似 B 地址 的东西 Thanks
  • 手臂“版本”之间的差异? (仅限 ARMv7)

    基本上我想知道ARMv7l和ARMv7之间的区别hl 我有一个带有armv7l的arm处理器 并且有很多armv7的rpmhl 我完全不知道我必须搜索什么才能获得相关信息 这个 后缀 叫什么 还有其他类型吗 他们的做法有何不同 我假设它指示
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • RAM 存储二进制数和汇编语言的冒泡排序

    我必须使用 ARM v7 执行一个例程 在 RAM 内存中存储 10 个二进制数 然后使用冒泡排序对这些数字从高到低进行排序 我应该如何开始 func bubbleSortAscendingU32 ldr r3 r0 4 mov r1 9
  • ARM 中只有两个操作数的 ADD 或 SUB

    我正在学习ARM汇编语言 我读过 ADD 应该有 3 个操作数 然而 我见过很多案例 现实中只有两种 例如 STR R1 SP 0x20 var 1C LDR R1 a lua 0x1DE4E6 MOVS R0 R4 haystack AD
  • 可以使用Visual Studio 2012构建ARM桌面程序吗?

    我正在使用 Visual Studio 2012 beta 我的桌面 win32 程序在 ARM 架构中编译得很好 升级到 Visual Studio 2012 RC 后 编译器无法工作并出现以下错误 不支持为 ARM 平台编译桌面应用程序
  • 交叉编译 Qt 4.7 时出现“非法指令”

    我已经在这个问题上苦苦挣扎了一个多星期了 但仍然找不到解决方案 我正在尝试为 ARM 设备交叉编译 Qt 4 7 嵌入式开源版本 构建过程本身可以顺利完成 但生成的二进制文件似乎包含处理器无法理解的指令 构建主机是 i386 上的 Debi
  • 有没有办法在 Xcode 4 中为 ARM 而不是 Thumb 进行编译?

    如果有很多浮点运算正在进行 Apple 建议针对 ARM 进行编译 而不是针对拇指进行编译 我的整个应用程序几乎是一个大型浮点运算 iOS 应用程序开发工作流程指南中是这样说的 iOS 设备支持两种指令集 ARM 和 Thumb Xcode
  • 了解 U-Boot 内存占用

    我不明白加载 U Boot 时 RAM 中发生了什么 我正在开发 Xilinx Zynq ZC702 评估套件 并尝试使用 U Boot 在其上加载 Linux 内核 于是我使用Xilinx工具Vivado和SDK生成了一个BOOT bin
  • iPhone 3GS 上的 ARM 与 Thumb 性能比较,非浮点代码

    我想知道是否有人有关于 iPhone 3GS 上 ARM 与 Thumb 代码性能的硬性数据 特别是对于非浮点 VFP 或 NEON 代码 我知道 Thumb 模式下的浮点性能问题 更大的 ARM 指令的额外代码大小是否会在某个时刻成为性能
  • 如何获取结构体中任意成员的位位置

    如何获取结构体中任意成员的位位置 在示例中 gt typedef struct BitExamStruct unsigned int v1 3 unsigned int v2 4 unsigned int v3 5 unsigned int

随机推荐

  • Elasticsearch 解决 log4j 安全漏洞 - 升级镜像

    一 概论 Apache Log4j 2 被披露出存在严重代码执行漏洞 xff0c 目前官方已发布正式安全公告及版本 xff0c 漏洞编号 xff1a CVE 2021 44228 xff0c 漏洞被利用可导致服务器被入侵等危害 公司 ES
  • Prometheus 实现 podDown 实时告警

    一 需求 每个 pod 重启 删除时 xff0c 都能发出告警 要及时和准确 二 告警架构 集群部署在 k8s 上 xff0c 告警使用 Prometheus 43 alertManager 43 prometheusManager xff
  • prometheus 告警机制 -(为什么告警发的不及时)

    为什么告警有时发的及时 xff0c 有时发的慢 数据异常到监控发出告警的时间与多个参数相关 xff0c 包括采集间隔 xff0c 扫描间隔 xff0c group 发送间隔 xff0c 告警持续时间 for 等 最长的时间为 采集间隔 43
  • prometheus 告警机制 - 我的告警为什么重发

    为什么告警总在重复发 xff0c 有时不重复发 xff0c 怎么避免 告警会在两种情况下重发 告警 group 列表中告警有变更 xff08 增加或者减少 xff09 告警持续到 repeat interval 配置的重发时间 告警 gro
  • linux 盘格式化并挂载

    一 概论 如果 linux 要格式化盘 xff0c 需要先解挂 xff0c 才能格式化 xff0c 格式化的速度比 rm rf 会快 xff0c 作用一样 如果是初始化机器挂载盘 xff08 不要解绑操作 xff09 xff0c 直接查看第
  • grafana 画富集多个指标 label 的表格

    下午5点 xff1a 老哥 xff0c 今天把业务趋势图搞出来吧 一 怎么画表格 我们的需要是做下面的视图 xff0c 他是一个表格 xff0c 而且有着多个数据源 添加图表 填入数据 xff0c 展示原始图形 转换为 table 只显示最
  • [golang] 实现 jwt 方式登录

    1 Jwt 和 Session 登录方案介绍 JSON Web Token xff08 缩写 JWT xff09 是目前流行的跨域认证解决方案 原理是生存的凭证包含标题 header xff0c 有效负载 payload 和签名组成 用户信
  • Stochastic Light Culling for VPLs on GGX Microsurfaces论文研读

    前言 好久没写博客了 xff0c 今天来共享一下最近研读的一篇论文吧 xff0c 文章中 pdf 为参考文献可自行谷歌学术下载 因为本人还是个图形学菜鸟 xff0c 所以有什么问题希望大家多多指正 Stochastic Light Cull
  • 瞎更新,container_cpu_usage_seconds_total{job=“cadvisor“} 怎么没有啦

    一 基本介绍 1 1 概论 1 1 1 故事背景 今天在同步其他团队的 grafana 监控大盘时 xff0c Prometheus 服务报告说不能找到名为 container cpu usage seconds total job 61
  • Prometheus MySQL 性能监控

    一 介绍 Prometheus 是一种开源的监控系统和时序数据库 xff0c 旨在收集和处理大量数据并提供可视化 监控警报等功能 它支持多种语言 多种部署方式 xff0c 并且非常灵活 xff0c 而且社区支持非常活跃 xff0c 为用户提
  • 二、nodeJS 项目架构详解(app.js + Express + Http)

    参考 xff1a https www cnblogs com ostrich sunshine p 7474471 html 其中重点文件 文件夹说明 xff1a techNode xff1a bin www 启动运行 xff08 服务端口
  • centos 安装freeswitch

    首先安装freeswitch的运行库 更新yum yum update 安装依赖 yum install y git gcc c 43 43 wget alsa lib devel autoconf automake bison broad
  • Visio、Matlab高清图片插入word文档的几种方法。

    2023 3 30 直接参考这两个就行了 xff0c 不用花里胡哨的 MATLAB 1 重要的第一步 xff0c 另存为png图片 xff1b 2 导出之前先设置分辨率 xff0c 很多期刊要求600dpi 这一步很关键 Visio 1 重
  • CTF Crypto---RSA NC不互素

    题目 span class token keyword from span Crypto span class token punctuation span Util span class token punctuation span nu
  • 看一看Ubuntu的目录结构

    先了解一下Ubuntu的目录结构 xff0c 对于后面学习Ubuntu软件安装和使用都有帮助 一 Linux没有盘符这个概念 Windows存在多个驱动器盘符 xff0c 每个盘符形成多个树形并列的情形 xff0c Linux没有盘符这个概
  • 【C语言】——结构体进阶:结构体的内存对齐(超详细)

    前言 xff1a 上一篇已经讲了结构体的基本用法 相信各位小伙伴以经学会怎么使用 但是还有一个问题没有弄明白 结构体到底多大 xff0c 占内存空间多不多 xff0c 以经系统到底怎么访问结构体内的数据的 接下来 xff0c 详细分析一下结
  • [OpenCV实战]15 基于深度学习的目标跟踪算法GOTURN

    目录 1 什么是对象跟踪和GOTURN 2 在OpenCV中使用GOTURN 3 GOTURN优缺点 4 参考 在这篇文章中 xff0c 我们将学习一种基于深度学习的目标跟踪算法GOTURN GOTURN在Caffe中搭建 xff0c 现在
  • **在Linux的shell脚本里激活conda 虚拟环境**

    在Linux的shell脚本里激活conda 虚拟环境 之前突发其想 xff0c 既然在命令行可以通过conda activate tf激活tf的虚拟环境 xff0c 那么能不能写个脚本实现呢 xff1f 费了好大劲 xff0c 发现并不行
  • Hierarchical Russian Roulette for Vertex Connections论文研读

    第二篇论文研读文章了 xff0c 虽然依旧很菜 xff0c 但这一篇开始就相对轻松一点了 文档种有些问题 xff0c 其中所有 实时 应该替换为 高效 Hierarchical Russian Roulette for Vertex Con
  • ARM通用中断控制器GIC之中断控制

    在阅读本章之前 xff0c 可以参考笔者之前关于GIC的一些描述 xff1a ARM通用中断控制器GIC generic Interrupt Controller 简介 ARM架构Generic Interrupt Controller G