09_GIC介绍与编程
GIC介绍与编程
参考资料:ARM® Generic Interrupt Controller Architecture Specification Architecture version 2.0(IHI0048B_b_gic_architecture_specification_v2).pdf
1.1 GIC介绍
ARM体系结构定义了通用中断控制器(GIC),该控制器包括一组用于管理单核或多核系统中的中断的硬件资源。GIC提供了内存映射寄存器,可用于管理中断源和行为,以及(在多核系统中)用于将中断路由到各个CPU核。它使软件能够屏蔽,启用和禁用来自各个中断源的中断,以(在硬件中)对各个中断源进行优先级排序和生成软件触发中断。它还提供对TrustZone安全性扩展的支持。GIC接受系统级别中断的产生,并可以发信号通知给它所连接的每个内核,从而有可能导致IRQ或FIQ异常发生。
你可以把 ARM的通用中断控制器(GIC) 想象成一个 公司的全能调度中心,专门负责接收各种设备(比如按键、传感器、网卡等)的“紧急呼叫”(中断请求),然后根据优先级、安全等级、目标处理部门(CPU核心)等规则,快速分派任务。以下是通俗解释:
一、GIC的核心功能
-
统一接听所有“电话”
- 公司有很多部门(外设),每个部门有事都会打“电话”给调度中心(GIC)。比如按键按下、传感器报警、网卡收到数据,都会发送中断信号。GIC统一接收这些请求,避免设备直接“轰炸”老板(CPU核心)导致混乱。
-
智能分派任务
- 优先级排序:火灾警报(高优先级)比打印机缺纸(低优先级)更紧急,GIC会优先处理。
- 路由规则:有些任务只能给特定部门处理(比如财务问题只能转给财务部),对应多核系统中将中断路由到指定CPU核心。
-
安全隔离
- 调度中心有“保密部门”(TrustZone安全扩展),机密任务(如指纹识别)只能交给安全部门处理,普通员工(非安全模式)无权接触。
二、GIC的“分派流程”
-
接收请求
- 外设触发中断 → GIC检测到信号(如按键电平变化)→ 记录在“待办清单”(挂起寄存器)中。
-
分类处理
- 普通电话(IRQ):常规任务,比如处理传感器数据。
- 紧急电话(FIQ):最高优先级任务,比如硬件故障,必须立刻处理。
-
分派给CPU核心
- 调度中心(Distributor)根据预设规则,将任务分给空闲的“员工”(CPU核心)。例如:
- 核心A处理网卡数据(高负载任务)
- 核心B处理按键输入(低负载任务)。
- 调度中心(Distributor)根据预设规则,将任务分给空闲的“员工”(CPU核心)。例如:
-
任务完成确认
- CPU处理完中断后,必须通知GIC“任务已完成”(清除中断标志),否则GIC会反复提醒。
三、GIC支持的“电话类型”
中断类型 | 通俗比喻 | 技术作用 |
---|---|---|
SGI | 内部对讲机:员工之间沟通(如核A通知核B处理任务) | 软件生成的中断,用于多核协作(如任务分配、数据同步)。 |
PPI | 部门专线:财务部的报销专线(仅财务部能接听) | 每个CPU核心独有的中断(如本地定时器),不与其他核共享。 |
SPI | 公共热线:客户服务电话(如400热线) | 共享外设中断(如网卡、硬盘),可路由到任意CPU核心处理。 |
LPI | VIP直通专线:重要客户直接联系高层(如PCIe设备中断) | 基于消息的中断,配置灵活(GICv3及以上支持),适合高性能场景。 |
四、为什么需要GIC?
-
减轻CPU负担
- 没有GIC时,所有设备直接找CPU,CPU会疲于应付。GIC像秘书一样先过滤、排序请求,让CPU专注处理核心任务。
-
支持多核协作
- 调度中心可动态分配任务给多个核心(比如让大核处理复杂计算,小核处理实时任务),提升系统效率。
-
安全与实时性
- 安全中断(如支付验证)与非安全中断(如游戏画面渲染)隔离,防止敏感操作被干扰。
一句话总结
“GIC就像公司的全能调度员:统一接收所有设备的‘紧急呼叫’,按优先级和安全规则精准分派给CPU核心,既保证火警优先处理,又能让多核团队高效协作!”
通过这套机制,ARM系统可以同时处理数百个中断请求,兼顾性能、实时性和安全性,是手机、服务器、物联网设备的“中枢神经”。
从软件角度来看,GIC具有两个主要功能模块,简单画图如下:
这张图展示了 ARM通用中断控制器(GIC) 的工作原理,可以类比为 一家公司的电话总机系统,专门负责接听各部门的“紧急电话”(中断请求),并按规则转接给对应的负责人(CPU核心)。以下是分步解析:
一、核心角色与流程
-
来电方(各种中断)
- 比喻:公司各部门(外设)遇到紧急事件时会拨打电话。例如:
- 键盘部门:按键被按下(需要CPU处理输入)。
- 网络部门:网卡收到数据包(需要CPU转发)。
- 传感器部门:温度超标(需要CPU触发警报)。
- 比喻:公司各部门(外设)遇到紧急事件时会拨打电话。例如:
-
总机接线员(Distributor)
- 核心作用:接收所有来电,分类、排序、分配。
- 具体工作:
- 分类:区分普通电话(IRQ)和加密电话(TrustZone安全中断)。
- 优先级排序:火灾报警电话(高优先级)比打印机缺纸电话(低优先级)优先处理。
- 安全检查:加密电话只能转接给保密部门(安全模式CPU核)。
- 分配规则:根据预设策略,将电话转给空闲的部门负责人(CPU核心)。
-
部门对接员(CPU Interface 0~N)
- 比喻:每个部门(CPU核心)有专属对接员,负责接收总机转来的电话,并确认处理结果。
- 工作流程:
- 接收总机分配的任务(中断)。
- 提醒负责人(CPU核心)处理任务(触发IRQ/FIQ异常)。
- 任务完成后,通知总机“电话已接听”(清除中断标志)。
-
部门负责人(Processor 0~N)
- 比喻:公司的各部门经理(CPU核心),专注处理分配到的任务。
- 分工举例:
- Processor 0:处理实时任务(如电机控制)。
- Processor 1:处理后台任务(如数据备份)。
二、GIC的工作流程(以按键触发中断为例)
-
来电接入:
- 按键按下 → 键盘部门拨打电话(产生中断信号)→ 总机(Distributor)接听。
-
总机处理:
- 分类:识别为普通电话(非安全中断)。
- 排序:优先级设为中等(高于温度传感器,低于硬件故障)。
- 分配:转接给当前最空闲的对接员(如CPU Interface 0)。
-
对接员转接:
- CPU Interface 0通知Processor 0:“有按键任务待处理”。
-
负责人处理:
- Processor 0暂停当前工作,执行按键处理程序(如更新屏幕显示)。
-
任务确认:
- Processor 0处理完成后,通知对接员 → 对接员反馈总机“任务完成”。
三、为什么需要GIC?
-
避免混乱:
- 没有总机时,所有电话直接打给老板(CPU核心),老板会被频繁打断。
- GIC的作用:总机先过滤、排序,只转接必要电话,让老板专注核心任务。
-
多核协作:
- 总机可动态分配任务给多个老板(多核CPU),提升效率(如大核处理复杂任务,小核处理简单任务)。
-
安全隔离:
- 保密电话(如指纹识别)只能转给保密部门(安全模式CPU核),防止信息泄露。
一句话总结
“GIC像公司的电话总机系统:接线员(Distributor)接听所有部门来电,按优先级和安全规则转接给对应负责人(CPU核心),既避免电话轰炸,又让多核团队高效协作!”
通过这张图,可以清晰理解中断如何从外设传递到CPU核心,以及GIC在实时性、安全性和多核调度中的核心作用。
① 分发器(Distributor) 系统中的所有中断源都连接到该单元。可以通过仲裁单元的寄存器来控制各个中断源的属性,例如优先级、状态、安全性、路由信息和使能状态。 分发器把中断输出到“CPU接口单元”,后者决定将哪个中断转发给CPU核。
② CPU接口单元(CPU Interface) CPU核通过控制器的CPU接口单元接收中断。CPU接口单元寄存器用于屏蔽,识别和控制转发到CPU核的中断的状态。系统中的每个CPU核心都有一个单独的CPU接口。 中断在软件中由一个称为中断ID的数字标识。中断ID唯一对应于一个中断源。软件可以使用中断ID来识别中断源并调用相应的处理程序来处理中断。呈现给软件的中断ID由系统设计确定,一般在SOC的数据手册有记录。
要理解ARM的中断控制器GIC中的 分发器(Distributor) 和 CPU接口单元(CPU Interface),可以用一个 公司电话系统 来比喻:
一、分发器(Distributor)——总机接线员
核心作用:统一接收所有“紧急电话”(中断请求),分类、排序后分派给对应部门(CPU核心)处理。
通俗解释:
-
接收所有来电
- 公司所有部门(外设)遇到问题都会拨打总机电话(产生中断),比如键盘部门报告按键被按下(SPI中断)、财务部门申请报销(PPI中断)等。
-
分类与规则设置
- 优先级排序:火灾报警(高优先级中断)比打印机缺纸(低优先级)优先处理。
- 目标分配:报销电话只能转给财务部(PPI中断只能发给特定CPU核心),客户投诉电话可转给任意部门(SPI中断可路由到任意核心)。
- 安全隔离:机密电话(安全中断)只能转接给保密部门(安全模式CPU核)。
-
状态管理
- 记录来电状态:
- 未接电话(挂起状态):记录在“待办清单”(Pending状态)。
- 正在通话(活动状态):转接给部门后标记为处理中(Active状态)。
- 记录来电状态:
技术细节:
- 分发器通过寄存器(如
GICD_
前缀)配置每个中断的触发方式(电平/边沿)、优先级、目标CPU列表等。 - 支持1020个中断ID(0~1019),其中0~31为私有中断(SGI/PPI),32~1019为共享外设中断(SPI)。
二、CPU接口单元(CPU Interface)——部门对接员
核心作用:接收总机转接的“电话”(中断),提醒部门负责人(CPU核心)处理,并确认任务完成。
通俗解释:
-
接收并提醒处理
- 总机转来报销申请(PPI中断)→ 对接员(CPU接口)通知财务部经理(CPU核心):“有任务待处理!”。
-
屏蔽与优先级过滤
- 设置门槛:财务部只处理金额超过100元的报销(设置优先级掩码,低于阈值的中断不转交)。
- 紧急插队:若火灾报警(高优先级中断)到来,对接员会打断当前报销处理(中断抢占)。
-
处理完成确认
- 财务部处理完报销后,对接员需向总机反馈:“任务完成!”(写入EOI寄存器清除中断标志)。
技术细节:
- 每个CPU核心有独立的接口单元(如
GICC_
前缀寄存器),负责中断确认、优先级掩码设置等。 - 中断处理完成后需分两步操作:优先级下降(允许其他中断抢占)和状态清除(标记为Inactive)。
三、中断处理全流程(以按键触发中断为例)
- 按键按下:键盘部门拨打总机(产生SPI中断)→ 分发器接收并标记为Pending。
- 总机处理:根据优先级和目标列表,转接给最空闲的对接员(CPU Interface 0)。
- 对接员转达:通知技术部负责人(CPU核心0):“有按键任务待处理!”→ 触发IRQ异常。
- 处理与反馈:
- 技术部处理按键输入(更新屏幕显示)→ 写入EOI寄存器通知对接员。
- 对接员清除中断状态,总机更新记录为Inactive。
一句话总结
“分发器像总机接线员:统一接听所有设备的中断请求,按优先级和安全规则分派任务;CPU接口像部门对接员:确保中断精准送达CPU核心,并跟踪处理结果。两者配合,让多核系统高效响应外设需求!”
通过这套机制,GIC实现了中断的优先级管理、多核协作和安全隔离,是手机、服务器等设备稳定运行的关键。
中断可以有多种不同的类型:
① 软件触发中断(SGI,Software Generated Interrupt) 这是由软件通过写入专用仲裁单元的寄存器即软件触发中断寄存器(ICDSGIR)显式生成的。它最常用于CPU核间通信。SGI既可以发给所有的核,也可以发送给系统中选定的一组核心。中断号0-15保留用于SGI的中断号。用于通信的确切中断号由软件决定。
② 私有外设中断(PPI,Private Peripheral Interrupt) 这是由单个CPU核私有的外设生成的。PPI的中断号为16-31。它们标识CPU核私有的中断源,并且独立于另一个内核上的相同中断源,比如,每个核的计时器。
③ 共享外设中断(SPI,Shared Peripheral Interrupt) 这是由外设生成的,中断控制器可以将其路由到多个核。中断号为32-1020。SPI用于从整个系统可访问的各种外围设备发出中断信号。
中断可以是边沿触发的(在中断控制器检测到相关输入的上升沿时认为中断触发,并且一直保持到清除为止)或电平触发(仅在中断控制器的相关输入为高时触发)。
中断可以处于多种不同状态:
① 非活动状态(Inactive)–这意味着该中断未触发。 ② 挂起(Pending)–这意味着中断源已被触发,但正在等待CPU核处理。待处理的中断要通过转发到CPU接口单元,然后再由CPU接口单元转发到内核。 ③ 活动(Active)–描述了一个已被内核接收并正在处理的中断。 ④ 活动和挂起(Active and pending)–描述了一种情况,其中CPU核正在为中断服务,而GIC又收到来自同一源的中断。
中断的优先级和可接收中断的核都在分发器(distributor)中配置。外设发给分发器的中断将标记为pending状态(或Active and Pending状态,如触发时果状态是active)。distributor确定可以传递给CPU核的优先级最高的pending中断,并将其转发给内核的CPU interface。通过CPU interface,该中断又向CPU核发出信号,此时CPU核将触发FIQ或IRQ异常。
作为响应,CPU核执行异常处理程序。异常处理程序必须从CPU interface寄存器查询中断ID,并开始为中断源提供服务。完成后,处理程序必须写入CPU interface寄存器以报告处理结束。然后CPU interface准备转发distributor发给它的下一个中断。
在处理中断时,中断的状态开始为pending,active,结束时变成inactive。中断状态保存在distributor寄存器中。
你可以把ARM的中断系统想象成 一个快递分拣中心,里面有快递员(中断源)、分拣机器人(GIC分发器)和派送员(CPU接口)。以下是通俗解释:
一、三种“快递包裹”(中断类型)
-
SGI(内部快递)
- 比喻:同事之间的小纸条,用于核间通信。比如核A让核B处理任务,写个纸条(触发SGI)扔到核B的工位上。
- 特点:
- 中断号0-15,像公司内部的16个快递柜编号。
- 软件触发,无需硬件连线,类似微信消息。
-
PPI(私人快递)
- 比喻:每个员工的专属快递柜。比如核A的定时器到期,快递只能放进核A的柜子(中断号16-31)。
- 特点:
- 仅对特定CPU核有效,如私人事务(如本地计时器、传感器报警)。
- 每个核的PPI独立,互不干扰。
-
SPI(公共快递)
- 比喻:全公司的公共快递站。比如网卡收到数据,快递员把包裹放在公共区(中断号32-1020),分拣机器人决定派给哪个员工。
- 特点:
- 外设共享,可路由到任意核(如USB设备、传感器)。
- 触发方式分两种:边沿触发(按一次门铃)或电平触发(门铃一直响)。
二、快递的“物流状态”(中断状态)
-
非活动(Inactive)
- 快递未发出,包裹还在仓库里躺着。
-
挂起(Pending)
- 快递已发出,但分拣中心还没分拣。比如按键按下后,GIC检测到信号但未处理。
-
活动(Active)
- 快递正在派送中,员工已签收(CPU开始处理中断)。
-
活动且挂起(Active and Pending)
- 员工正在拆快递,快递员又送来一个同款包裹。比如传感器连续触发两次中断。
三、分拣中心的工作流程
-
分拣机器人(Distributor)
- 核心任务:
- 优先级排序:火灾警报(高优先级)比打印机缺纸(低优先级)优先处理。
- 路由规则:公共快递(SPI)分给最闲的员工(CPU核)。
- 状态管理:标记包裹状态(Pending→Active)并更新物流信息。
- 核心任务:
-
派送员(CPU Interface)
- 具体工作:
- 接收分拣好的包裹(最高优先级中断)。
- 通知员工:“有你的快递!”(触发IRQ/FIQ异常)。
- 员工签收后,撕掉快递单(清除中断标志)。
- 具体工作:
-
员工处理(CPU核)
- 步骤:
- 暂停手头工作,查快递单号(读取中断ID)。
- 拆包裹(执行中断处理程序)。
- 处理完通知分拣中心:“任务完成!”(写EOI寄存器)。
- 步骤:
四、为什么需要这套系统?
-
避免混乱:
- 没有分拣中心,所有快递直接堆到员工桌上,员工会被频繁打断。
-
多核协作:
- 分拣中心动态分配任务,大核处理复杂计算,小核处理实时任务。
-
实时性与安全:
- 高优先级中断(如硬件故障)插队处理,机密任务(如指纹识别)隔离到安全核。
一句话总结
“ARM的中断系统像快递分拣中心:分拣机器人(Distributor)按优先级派送包裹(中断),派送员(CPU Interface)确保快递精准送达员工(CPU核),既避免包裹堆积,又让多核团队高效协作!”
掌握这套机制,就能理解手机、服务器如何快速响应按键、网络数据等事件,同时避免系统卡顿或崩溃。
下图是GIC控制器的逻辑结构:
这张图展示的是 ARM通用中断控制器(GIC) 的架构,可以把它想象成一个 国际快递分拣中心,负责接收全球各地(外设、软件、虚拟机)的包裹(中断请求),分拣后派送到对应的国家(CPU核心)或跨国分公司(虚拟机)。以下是逐层解析:
一、核心角色与流程
1. 分拣中心(Distributor)
- 功能:统一接收所有包裹(中断请求),分类、标记、排序。
- 处理流程:
- 接收包裹:
- 本地快递(PPI/SGI):员工私人包裹(如核0的定时器中断、核1发来的内部通知)。
- 国际快递(SPI):跨国包裹(如网卡数据、USB设备中断)。
- 跨国分公司快递(Virtual):虚拟机的包裹(如虚拟机监控程序发来的请求)。
- 贴标签:每个包裹贴上唯一ID(中断号0~1019),记录优先级和安全等级(如机密/普通)。
- 分拣规则:
- 优先级最高的包裹(如火灾警报)优先派送。
- 机密包裹(安全中断)只能派给指定国家(安全模式CPU核)。
- 接收包裹:
2. 国家分拣站(CPU Interface)
- 功能:每个国家(CPU核心)有自己的分拣站,负责接收总部分拣的包裹,并通知本地快递员(CPU核心)签收。
- 例如:
- 分拣站0ICC_0):对应核0,处理本地包裹(PPI)和分派的国际包裹(SPI)。
- 分拣站7(GICC_7):对应核7,支持虚拟化包裹(GICV_7)。
- 例如:
3. 跨国分公司通道(Virtual Interface)
- 功能:处理跨国分公司(虚拟机)的包裹。
- 虚拟监控分拣站(GICH):跨国总部的分拣员,负责接收虚拟机请求(如虚拟机需要访问硬件)。
- 虚拟分拣站(GICV):分公司的本地分拣员,处理虚拟机内部的中断(如虚拟机中的APP触发请求)。
二、快递类型与标签(中断分类)
快递类型 | 通俗比喻 | 技术细节 |
---|---|---|
SGI(0~15号包裹) | 公司内部文件:员工A给员工B发通知(如核0让核1处理任务)。 | 软件触发,用于多核通信(如核间任务分配)。 |
PPI(16~31号包裹) | 私人包裹:每个员工的专属快递(如核0的本地定时器到期)。 | 每个核独享,不与其他核共享。 |
SPI(32~1019号包裹) | 国际包裹:全球可送达的公共快递(如网卡、硬盘中断)。 | 可路由到任意CPU核心,优先级由分发器动态分配。 |
虚拟包裹(VFIQ/VIRQ) | 跨国分公司快递:虚拟机内部的需求(如虚拟机中的APP请求访问硬件)。 | 通过虚拟接口(GICV/GICH)与物理CPU核心通信。 |
三、分拣中心的“黑科技”
-
优先级与抢占
- 插队规则:高优先级包裹(如硬件故障)会打断低优先级任务(如音乐播放),类似急救车优先通行。
- 多核负载均衡:自动将包裹分给最空闲的国家(CPU核心),提升整体效率。
-
安全隔离(TrustZone)
- 机密包裹:安全中断(如指纹识别)只能派送给“保密国家”(安全模式CPU核),普通员工(非安全模式)无权接触。
-
虚拟化支持(GICV/GICH)
- 跨国分公司管理:虚拟机监控程序(Hypervisor)像跨国总部,通过虚拟接口协调虚拟机的中断请求。
- 示例流程:
- 虚拟机中的APP触发中断 → 虚拟分拣站(GICV)接收并标记为“虚拟包裹”。
- 虚拟监控分拣站(GICH)将包裹转发给物理分拣站(GICC)。
- 物理CPU核心处理完成后,通过虚拟接口返回结果给虚拟机。
四、分拣中心的“物流状态”
-
包裹状态
- 未分拣(Pending):包裹在分拣中心等待处理。
- 派送中(Active):包裹已派送给某个国家(CPU核心),但未签收。
- 已签收(Inactive):包裹被处理完成,状态清除。
-
异常情况
- 重复包裹(Active and Pending):员工正在拆包裹,分拣中心又收到同款包裹(如传感器连续触发两次中断)。
一句话总结
“GIC像一个国际快递分拣中心:分发器(Distributor)是总部,接收全球包裹(中断)并按规则分派;CPU接口是国家分拣站,确保包裹精准送达;虚拟接口是跨国通道,协调虚拟机的中断请求——整套系统让手机、服务器能同时处理上千个任务,既高效又安全!”
1.1.1 配置
GIC作为内存映射的外围设备,被软件访问。所有内核都可以访问公共的distributor单元,但是CPU interface是备份的,也就是说,每个CPU核都使用相同的地址来访问其专用CPU接口。一个CPU核不可能访问另一个CPU核的CPU接口。
Distributor拥有许多寄存器,可以通过它们配置各个中断的属性。这些可配置属性是:
-
中断优先级:Distributor使用它来确定接下来将哪个中断转发到CPU接口。
-
中断配置:这确定中断是对电平触发还是边沿触发。
-
中断目标:这确定了可以将中断发给哪些CPU核。
-
中断启用或禁用状态:只有Distributor中启用的那些中断变为挂起状态时,才有资格转发。
-
中断安全性:确定将中断分配给Secure还是Normal world软件。
-
中断状态。
Distributor还提供优先级屏蔽,可防止低于某个优先级的中断发送给CPU核。 每个CPU核上的CPU interface,专注于控制和处理发送给该CPU核的中断。
你可以把 GIC(通用中断控制器) 想象成一个 大型快递分拣中心,负责接收来自全球各地(外设、软件、虚拟机)的包裹(中断请求),并精准分发给每个快递员(CPU核心)。以下是通俗解释:
一、分拣中心(Distributor)——公共总控台
功能:统一管理所有包裹(中断),决定分发给谁、按什么规则分发。
通俗比喻:
- 分拣中心是公共的,所有快递员(CPU核心)都可以查看总控台的规则,但无法修改其他快递员的专属设置。
- 关键配置:
- 包裹优先级:火灾包裹(高优先级)比普通包裹优先处理。
- 包裹类型:
- 边沿触发:按一次门铃就记录(如按键按下一次)。
- 电平触发:门铃一直响才记录(如传感器持续高温)。
- 目标快递员:指定包裹只能给张三或李四(如核0处理实时任务,核1处理网络数据)。
- 安检规则:机密包裹(安全中断)只能交给保密部门(安全模式CPU核)。
- 包裹状态:记录包裹是否已签收(中断是否处理完成)。
技术细节:
- Distributor通过寄存器配置每个中断的优先级(0-255,数值越小优先级越高)、触发方式、目标核列表等[]。
- 高优先级中断可抢占低优先级任务(如消防车优先通行)。
二、专属快递站(CPU Interface)——每个快递员的私人柜台
功能:接收分拣中心分配的包裹,并确保快递员(CPU核心)能专注处理。
通俗比喻:
- 每个快递员有独立柜台,只能处理自己的包裹,无法查看他人柜台。
- 关键操作:
- 设置门槛:只接收重要包裹(如屏蔽优先级低于50的中断)。
- 签收确认:快递员处理完包裹后,必须向分拣中心反馈“已签收”(写EOI寄存器清除中断标志)。
- 紧急插队:若新包裹更紧急(高优先级中断),快递员会暂停当前任务,优先处理新包裹。
技术细节:
- 每个CPU核的接口单元独立控制中断屏蔽、优先级过滤和抢占逻辑。
- 中断处理完成后需两步操作:优先级降级(允许其他中断抢占)和状态清除(标记为Inactive)。
三、分拣流程示例(以网络数据中断为例)
- 包裹到达:网卡收到数据 → 分拣中心标记为“待处理”(Pending状态)。
- 分拣规则:
- 优先级设为80(高于按键中断,低于硬件故障)。
- 目标核设为核1(负责网络任务)。
- 派送通知:分拣中心将包裹转给核1的快递站 → 触发IRQ异常。
- 处理与反馈:
- 核1处理数据转发 → 写入EOI寄存器通知分拣中心。
- 分拣中心更新状态为“已签收”(Inactive)。
一句话总结
“GIC像快递分拣系统:分拣中心(Distributor)统一管理所有中断规则,专属快递站(CPU Interface)确保每个核专注处理自己的任务。高优先级中断插队,安全中断隔离,多核协作高效稳定!”
通过这套机制,手机、服务器能同时处理上千个中断请求,兼顾实时性与安全性。
1.1.2 初始化
Distributor和CPU interface在复位时均被禁用。复位后,必须初始化GIC,才能将中断传递给CPU核。 在Distributor中,软件必须配置优先级、目标核、安全性并启用单个中断;随后必须通过其控制寄存器使能。 对于每个CPU interface,软件必须对优先级和抢占设置进行编程。每个CPU接口模块本身必须通过其控制寄存器使能。 在CPU核可以处理中断之前,软件会通过在向量表中设置有效的中断向量并清除CPSR中的中断屏蔽位来让CPU核可以接收中断。 可以通过禁用Distributor单元来禁用系统中的整个中断机制;可以通过禁用单个CPU的CPU接口模块或者在CPSR中设置屏蔽位来禁止向单个CPU核的中断传递。也可以在Distributor中禁用(或启用)单个中断。 为了使某个中断可以触发CPU核,必须将各个中断,Distributor和CPU interface全部使能,并
将CPSR中断屏蔽位清零,如下图:
可以把ARM的中断控制器(GIC)想象成一个 国际快递分拣中心,而CPU核是各个国家的快递员。复位状态相当于整个分拣中心停电关机,所有包裹(中断)都无法处理。要让快递系统运作起来,需要一步步开启设备、设置规则。以下是通俗分步解释:
一、分拣中心重启:Distributor的初始化
-
停电重启(复位后状态)
- 比喻:分拣中心停电Distributor和CPU Interface被禁用),所有包裹堆积在仓库,无法派送。
- 技术细节:复位后GIC默认关闭所有中断传递功能。
-
制定派送规则(配置中断属性)
- 优先级标签:火灾包裹(高优先级)比普通包裹优先派送 - 目标国家:指定包裹只能发给美国(CPU核0)或中国(CPU核1)。
- 安全等级:机密包裹(安全中断)只能派给保密部门(安全模式核)。
- 启用包裹通道:逐个开启允许派送的包裹类型(启用单个中断)。
- 技术操作:通过Distributor寄存器(如
GICD_ICENABLER
禁用所有中断,再通过GICD_ISENABLER
启用特定中断)[^^5]。
-
启动分拣中心(使能Distributor)
- 比喻:按下总电源开关,分拣机器人开始工作。
- 技术操作:设置
GICD_CTLR
寄存器的使能位(如写入1)。
二、各国快递站激活:CPU Interface的配置
-
设置接单门槛(优先级过滤)
- 比喻:美国快递站只接收价值超过100美元的包裹(设置优先级掩码)。
- 技术操作:通过
GICC_PMR
寄存器设置CPU核的优先级阈值(如0xF0表示仅处理优先级高于16的中断)。
-
允许插队规则(抢占设置)
- 比喻:急救车(高优先级包裹)可打断当前派送任务。
- 技术操作:通过
GICC_BPR
设置抢占级别(如设置为2,允许两级抢占)。
-
开启快递站电源(使能CPU Interface)
- 比喻:各国快递站通电,准备接收包裹。
- 技术操作:设置
GICC_CTLR
寄存器的使能位。
三、快递员准备接单:CPU核的启动
-
设置接单热线(中断向量表)
- 比喻:快递员需要知道包裹处理流程(如火灾包裹拨打119)。
- 技术操作:在内存中设置中断向量表,指向中断处理函数地址。
-
摘掉“请勿打扰”牌子(清除CPSR屏蔽位)
- 比喻:快递员摘掉“休息中”的牌子,开始接电话。
- 技术操作:清除CPU核的CPSR寄存器中的中断屏蔽位(如IRQ/FIQ位)。
四、中断触发全链路:缺一不可的条件
只有当以下条件全部满足时,中断才能送达CPU核:
- 包裹已贴标签:中断在Distributor中启用。
- 分拣中心通电:Distributor全局使能。
- 快递站通电:目标CPU核的Interface使能。
- 快递员在线:CPU核的CPSR屏蔽位已清除。
任一环节关闭,包裹都会被拦截(如禁用Distributor相当于切断全球物流)。
五、灵活的中手段
- 全局关停:禁用Distributor(切断所有包裹派送)。
- 单个国家拒收:禁用某个CPU核的Interface(如美国快递站罢工)。
- 屏蔽特定包裹:在Distributor中禁用单个中断(如拒收所有来自键盘的包裹)。
一句话总结
“GIC像快递分拣系统:分拣中心(Distributor)制定规则并启动物流,各国快递站(CPU Interface)设置接单门槛,快递员(CPU核)打开接单热线。只有全链路打通,中断才能精准送达!”
通过这套机制,手机、服务器能高效处理实时事件,同时支持多核协作与安全隔离。
1.1.3 GIC中断处理
当CPU核接收到中断时,它会跳转到中断向量表执行。 顶层中断处理程序读取CPU接口模块的Interrupt Acknowledge Register,以获取中断ID。除了返回中断ID之外,读取操作还会使该中断在Distributor中标记为active状态。一旦知道了中断ID(标识中断源),顶层处理程序现在就可以分派特定于设备的处理程序来处理中断。 当特定于设备的处理程序完成执行时,顶级处理程序将相同的中断ID写入CPU interface模块中的End of Interrupt register中断结束寄存器,指示中断处理结束。除了把当前中断移除active状态之外,这将使最终中断状态变为inactive或pending(如果状态为inactive and pending),这将使CPU interface能够将更多待处理pending的中断转发给CPU核。这样就结束了单个中断的处理。 同一CPU核上可能有多个中断等待服务,但是CPU interface一次只能发出一个中断信号。顶层中断处理程序重复上述顺序,直到读取特殊的中断ID值1023,表明该内核不再有任何待处理的中断。这个特殊的中断ID被称为伪中断ID(spurious interrupt ID)。 伪中断ID是保留值,不能分配给系统中的任何设备。
可以把CPU处理中断的过程想象成 快递员处理包裹(中断)的标准化流程,每个环节都有明确的操作步骤和规则。以下是通俗解释:
一、收到包裹:跳转到“分拣中心”(中断向量表)
- 比喻:快递员(CPU核)收到包裹(中断请求),立刻跑到分拣中心(中断向量表)查看包裹类型对应的处理流程。
- 技术细节:
- 中断向量表是内存中的一张“地址清单”,每个中断ID对应一个处理程序的入口地址(类似“火灾包裹处理区”或“键盘包裹处理区”)。
- CPU收到中断信号后,自动根据中断类型号(如1023是伪中断)跳转到对应的处理程序入口。
二、拆包验货:获取“包裹单号”(中断ID)
- 比喻:快递员打开包裹,扫描单号(读取Interrupt Acknowledge Register),确认这是哪个包裹(中断源)。
- 关键操作:
- 标记为“处理中”:扫描单号后,分拣中心(Distributor)会将此包裹状态从“待处理”(Pending)改为“处理中”(Active),防止其他快递员重复处理。
- 获得唯一ID:例如键盘中断ID是32,网卡中断ID是100,这些编号在系统设计时就已确定。
三、分派任务:呼叫“专业处理员”(设备处理程序)
- 比喻:根据单号(中断ID),快递员呼叫对应的专业团队(如“键盘维修组”或“网卡数据组”)处理包裹。
- 技术细节:
- 分派规则:顶层处理程序通过中断ID查表,找到对应的设备驱动函数(如处理键盘按键的代码)。
- 快速处理原则:设备处理程序需短小精悍,避免长时间占用快递员(例如仅记录按键值,不立刻更新屏幕)。
四、完成签收:通知“包裹已送达”(写入EOI寄存器)
- 比喻:专业团队处理完包裹后,快递员在系统里点击“签收完成”(写入End of Interrupt Register),包裹状态变为“已完成”(Inactive)。
- 关键作用:
- 释放资源:标记中断为完成,分拣中心(Distributor)可以继续派送新包裹(其他Pending中断)。
- 状态更新:若处理期间同一中断源再次触发,状态会变为“活动且待处理”(Active and Pending),避免遗漏。
五、循环检查:确认“没有遗漏包裹”(检测伪中断ID 1023)
- 比喻:快递员反复检查分拣中心,直到系统显示“无包裹”(读取到伪中断ID 1023),才停止工作。
- 技术细节:
- 伪中断ID 1023:相当于系统设置的“空箱标识”,告诉CPU“当前无待处理中断”。
- 避免死循环:若未检测到1023,CPU会误以为还有包裹,导致无意义循环(类似快递员反复扫描空货架)。
六、多包裹处理:一次只能拿一个包裹
- 比喻:快递员一次只能搬运一个包裹(CPU核一次处理一个中断),处理完再取下一个。
- 优先级规则:高优先级包裹(如火灾警报)会插队处理,低优先级需等待。
一句话总结
“CPU处理中断就像快递分拣:跳转分拣中心查单号→呼叫专业团队处理→签收后释放资源→循环检查直到无包裹。伪中断ID 1023是‘空箱信号’,防止快递员空跑!”
通过这套机制,CPU能高效处理键盘、网络等外设请求,同时避免中断丢失或重复处理。
1.2 GIC的寄存器
GIC分为两部分:Distributor和CPU interface,它们的寄存器都有相应的前缀:“GICD”、“GICC”。这些寄存器都是映射为内存接口(memery map),CPU可以直接读写。
1.2.1 Distributor 寄存器描述
1. Distributor Control Register, GICD_CTLR
位域 | 名 | 读写 | 描述 |
---|---|---|---|
1 | EnableGrp1 | R/W | 用于将pending Group 1中断从Distributor转发到CPU interfaces 0:group 1中断不转发 1:根据优先级规则转发Group 1中断 |
0 | EnableGrp0 | R/W | 用于将pending Group 0中断从Distributor转发到CPU interfaces 0:group 0中断不转发 1:根据优先级规则转发Group 0中断 |
- 整体结构
GIC就像一个大快递分拣中心,分为两个部门:
- 分拣部(Distributor):相当于分拣员,负责接收所有快递(中断信号)
- 派送部(CPU接口):负责把分拣好的快递派送给收件人(CPU处理)
- 控制开关(寄存器)
图中展示的是分拣部的总控开关(GICD_CTLR寄存器),这个开关有32个按钮位,但目前只有最底下的两个按钮有用:
- 🟡 黄色按钮1(EnableGrp1):控制VIP快递(高优先级中断)是否进入派送流程
- 🟡 黄色按钮0(EnableGrp0):控制普通快递(基础中断)是否进入派送流程
- 工作模式
每个按钮都有两种状态:
- 按下去(写1):允许此类快递进入分拣流程,系统会根据包裹上的优先级标签(中断优先级)自动安排派送顺序
- 弹起来(写0):直接拦截此类快递,整个分拣中心会假装没收到这类包裹
- 实际应用
假设现在要系统维护:
① 先关闭普通快递通道(EnableGrp0=0),避免普通中断干扰
② 保持VIP通道开启(EnableGrp1=1),只处理紧急事务
③ 维护完成后,再同时打开两个按钮(都写1),恢复正常服务
这种设计让操作系统像物流调度员一样,可以通过简单操作这两个关键开关,灵活控制哪些类型的中断需要立即处理,哪些可以暂时屏蔽,从而保证系统高效稳定运行。
2. Interrupt Controller Type Register, GICD_TYPER
位域 | 名 | 读写 | 描述 |
---|---|---|---|
15:11 | LSPI | R | 如果GIC实现了安全扩展,则此字段的值是已实现的可锁定SPI的最大数量,范围为0(0b00000)到31(0b11111)。 如果此字段为0b00000,则GIC不会实现配置锁定。 如果GIC没有实现安全扩展,则保留该字段。 |
10 | SecurityExtn | R | 表示GIC是否实施安全扩展: 0未实施安全扩展; 1实施了安全扩展 |
7:5 | CPUNumber | R | 表示已实现的CPU interfaces的数量。 已实现的CPU interfaces数量比该字段的值大1。 例如,如果此字段为0b011,则有四个CPU interfaces。 |
4:0 | ITLinesNumber | R | 表示GIC支持的最大中断数。 如果ITLinesNumber = N,则最大中断数为32*(N+1)。 中断ID的范围是0到(ID的数量– 1)。 例如:0b00011最多128条中断线,中断ID 0-127。 中断的最大数量为1020(0b11111)。 无论此字段定义的中断ID的范围如何,都将中断ID 1020-1023保留用于特殊目的 |
整个寄存器 = 快递中心的配置表
这张图告诉我们这个快递中心(GIC中断控制器)有多大容量、有什么特殊功能,就像一份“分拣中心能力说明书”。
核心配置项解读
-
📦 最大包裹处理能力(ITLinesNumber)
- 字段位置:第4-0位(最右侧5个开关)
- 作用:决定快递中心最多能处理多少个包裹(中断信号)。
- 计算公式:
最大中断数 = 32 × (N+1)
- 比如:如果这里显示
0b00011
(十进制的3),则能处理 32×(3+1)=128个包裹 - 特殊规则:最后4个包裹号(1020-1023)是“保留快递柜”,专门存放紧急物资,普通包裹不能用这些编号。
- 比如:如果这里显示
-
👨💼 分拣员数量(CPUNumber)
- 字段位置:第7-5位
- 作用:告诉你有多少个分拣员(CPU接口)在岗。
- 计算公式:实际分拣员数 = 数值 + 1
- 比如:显示
0b011
(十进制的3),则实际有 3+1=4个分拣员。
- 比如:显示
-
🔒 安全保险柜功能(SecurityExtn)
- 字段位置:第10位(单个开关)
- 作用:快递中心是否有“安全保险柜”(安全扩展功能)。
0
:没有保险柜,所有包裹混在一起处理1
:有保险柜,重要包裹(安全相关中断)可以单独上锁保护。
-
🗝️ 保险柜钥匙数量(LSPI)
- 字段位置:第15-11位(仅当有保险柜时生效)
- 作用:如果启用了安全保险柜,这里说明最多有多少把钥匙(可锁定SPI中断数量)。
- 范围:0到31把钥匙
0
:虽然有保险柜,但暂时不提供锁包裹功能- 其他值:比如
0b11111
(十进制的31),表示最多能锁住31个重要包裹。
-
🚧 预留区域(Reserved)
- 说明书上的空白格(其他位),是快递中心为未来升级预留的空间,暂时用不上。
实际场景举例
假设你看到这份配置表显示:
ITLinesNumber=0b11111
→ 最大处理 32×(31+1)=1024个包裹CPUNumber=0b100
→ 4+1=5个分拣员SecurityExtn=1
→ 有安全保险柜LSPI=0b10101
→ 最多能锁住21个重要包裹
那么说明这个快递中心:
1️⃣ 能处理1024个包裹(但1020-1023号包裹是保留的)
2️⃣ 有5个分拣员随时待命
3️⃣ 支持重要包裹单独上锁保护
4️⃣ 安全模式下最多锁定21个包裹
为什么需要这份表?
就像快递中心经理需要知道仓库有多大、有多少员工一样,操作系统通过读取这个寄存器,就能知道当前中断控制器的能力上限,从而合理分配任务(比如:最多能注册多少中断?是否需要处理安全相关的中断?)。
希望这个比喻能帮你轻松理解! 😄
3. Distributor Implementer Identification Register, GICD_IIDR
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:24 | ProductID | R | 产品标识ID |
23:20 | 保留 | ||
19:16 | Variant | R | 通常是产品的主要版本号 |
15:12 | Revision | R | 通常此字段用于区分产品的次版本号 |
11:0 | Implementer | R | 含有实现这个GIC的公司的JEP106代码; [11:8]:JEP106 continuation code,对于ARM实现,此字段为0x4; [7]:始终为0; [6:0]:实现者的JEP106code,对于ARM实现,此字段为0x3B |
整块牌子 = 分拣中心的身份名片
这个寄存器就像一块电子铭牌,记录了分拣中心(中断控制器)的型号、版本、制造商信息,操作系统每次启动就会自动读取这些信息。
分拣中心名片详解
-
📦 型号编号(ProductID)
- 位置:31-24位(最左边的8个格)
- 作用:类似分拣中心的设备型号,比如“快递中心Pro-2024款”。
- 特点:
- 只读不可修改(就像机器出厂时镭雕的编号)
-
🏷️ 版本大升级(Variant)
- 位置:19-16位
- 作用:记录架构大改版,比如:
- V1到V2可能从传统仓库升级成自动化分拣
- V3可能新增AI调度机器人
-
🔧 维修小版本(Revision)
- 位置:15-12位
- 作用:记录小优化补丁,比如:
- Rev1.0 ➔ Rev1.1:修正传送带卡顿问题
- Rev1.2 ➔ Rev1.3:优化包裹扫码速度
-
🏢 制造商密码(Implementer)
- 位置:11-0位
- 作用:相当于制造商身份证(类似公司营业执照号),ARM的专属解码:
- [举例]
→0x4
+0x3B
= ARM公司独家代码
→ 就像“顺丰编码SF-9527”代表官方认证分拣中心
- [举例]
-
🚧 留空扩展位(Reserved)
- 位置:23-20位
- 作用:给未来升级预留的空白栏位(比如应急通道扩建位置)
举个实际例子
假设寄存器显示:
- ▶️ Variant=0x4 → 第四代分拣中心架构(比如配备无人机投递)
- ▶️ Revision=0x2 → 第二个优化版本(修复了无人机电池过热问题)
- ▶️ Implementer=0x43B → ARM认证的标志(刻在设备上的正品钢印)
此时操作系统就能知道:
🔹 正在使用ARM制造的第四代分拣中心
🔹 当前版本已升级到Rev.2
🔹 无需人工设置,所有参数自动识别
为什么需要这个寄存器?
就像快递总部要核查每个分拣中心的资质一样:
1️⃣ 兼容性问题:某新款快递机器人只能在V4架构的分拣中心运行
2️⃣ 调试定位:发现传送带卡顿时,通过Revision判断是否需要升级固件
3️⃣ 正版验证:Implementer代码确保不是山寨分拣中心
希望这个比喻能让你轻松看懂这个「硬件身份证」😊
4. Interrupt Group Registers, GICD_IGROUPRn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:0 | Group status bits | R/W | 组状态位,对于每个位: 0:相应的中断为Group 0; 1:相应的中断为Group 1。 |
对于一个中断,如何设置它的Group ?首先找到对应的GICD_IGROUPRn寄存器,即n是多少?还要确定使用这个寄存器里哪一位。 对于interrtups ID m,如下计算:
n = m DIV 32,GICD_IGROUPRn里的n就确定了; GICD_IGROUPRn在GIC内部的偏移地址是多少?0x080+(4*n) 使用GICD_IPRIORITYRn中哪一位来表示interrtups ID m? bit = m mod 32。
5. Interrupt Set-Enable Registers, GICD_ISENABLERn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:0 | Set-enable bits | R/W | 对于SPI和PPI类型的中断,每一位控制对应中断的转发行为:从Distributor转发到CPU interface: 读: 0:表示当前是禁止转发的; 1:表示当前是使能转发的; 写: 0:无效 1:使能转发 |
对于一个中断,如何找到GICD_ISENABLERn并确定相应的位?
对于interrtups ID m,如下计算: n = m DIV 32,GICD_ISENABLERn里的n就确定了; GICD_ISENABLERn在GIC内部的偏移地址是多少?0x100+(4*n) 使用GICD_ISENABLERn中哪一位来表示interrtups ID m? bit = m mod 32。
6. Interrupt Clear-Enable Registers, GICD_ICENABLERn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:0 | Clear-enable bits | R/W | 对于SPI和PPI类型的中断,每一位控制对应中断的转发行为:从Distributor转发到CPU interface: 读: 0:表示当前是禁止转发的; 1:表示当前是使能转发的; 写: 0:无效 1:禁止转发 |
对于一个中断,如何找到GICD_ICENABLERn并确定相应的位?
对于interrtups ID m,如下计算: n = m DIV 32,GICD_ICENABLERn里的n就确定了; GICD_ICENABLERn在GIC内部的偏移地址是多少?0x180+(4*n) 使用GICD_ICENABLERn中哪一位来表示interrtups ID m? bit = m mod 32。
7. Interrupt Set-Active Registers, GICD_ISACTIVERn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:0 | Set-active bits | R/W | 读: 0:表示相应中断不是active状态; 1:表示相应中断是active状态; 写: 0:无效 1:把相应中断设置为active状态,如果中断已处于Active状态,则写入无效 |
对于一个中断,如何找到GICD_ISACTIVERn并确定相应的位?
对于interrtups ID m,如下计算: n = m DIV 32,GICD_ISACTIVERn里的n就确定了; GICD_ISACTIVERn在GIC内部的偏移地址是多少?0x300+(4*n) 使用GICD_ISACTIVERn 中哪一位来表示interrtups ID m? bit = m mod 32。
8. Interrupt Clear-Active Registers, GICD_ICACTIVERn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:0 | Clear-active bits | R/W | 读: 0:表示相应中断不是active状态; 1:表示相应中断是active状态; 写: 0:无效 1:把相应中断设置为deactive状态,如果中断已处于dective状态,则写入无效 |
对于一个中断,如何找到GICD_ICACTIVERn并确定相应的位?
对于interrtups ID m,如下计算: n = m DIV 32,GICD_ICACTIVERn里的n就确定了; GICD_ICACTIVERn 在GIC内部的偏移地址是多少?0x380+(4*n) 使用GICD_ICACTIVERn中哪一位来表示interrtups ID m? bit = m mod 32。
9. Interrupt Priority Registers, GICD_IPRIORITYRn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:24 | Priority, byte offset 3 | R/W | 对于每一个中断,都有对应的8位数据用来描述:它的优先级。 每个优先级字段都对应一个优先级值,值越小,相应中断的优先级越高 |
23:16 | Priority, byte offset 2 | R/W | |
15:8 | Priority, byte offset 1 | R/W | |
7:0 | Priority, byte offset 0 | R/W |
对于一个中断,如何设置它的优先级(Priority),首先找到对应的GICD_IPRIORITYRn寄存器,即n是多少?还要确定使用这个寄存器里哪一个字节。
对于interrtups ID m,如下计算: n = m DIV 4,GICD_IPRIORITYRn里的n就确定了; GICD_IPRIORITYRn在GIC内部的偏移地址是多少?0x400+(4*n) 使用GICD_IPRIORITYRn中4个字节中的哪一个来表示interrtups ID m的优先级? byte offset = m mod 4。 byte offset 0对应寄存器里的[7:0]; byte offset 1对应寄存器里的[15:8]; byte offset 2对应寄存器里的[23:16]; byte offset 3对应寄存器里的[31:24]。
10. Interrupt Processor Targets Registers, GICD_ITARGETSRn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
31:24 | CPU targets, byte offset 3 | R/W | 对于每一个中断,都有对应的8位数据用来描述:这个中断可以发给哪些CPU。 处理器编号从0开始,8位数里每个位均指代相应的处理器。 例如,值0x3表示将中断发送到处理器0和1。 当读取GICD_ITARGETSR0~GICD_ITARGETSR7时,读取里面任意字节,返回的都是执行这个读操作的CPU的编号。 |
23:16 | CPU targets, byte offset 2 | R/W | |
15:8 | CPU targets, byte offset 1 | R/W | |
7:0 | CPU targets, byte offset 0 | R/W |
对于一个中断,如何设置它的目杯CPU?优先级(Priority),首先找到对应的GICD_ITARGETSRn寄存器,即n是多少?还要确定使用这个寄存器里哪一个字节。
对于interrtups ID m,如下计算: n = m DIV 4,GICD_ITARGETSRn里的n就确定了; GICD_ITARGETSRn在GIC内部的偏移地址是多少?0x800+(4*n) 使用GICD_ITARGETSRn中4个字节中的哪一个来表示interrtups ID m的目标CPU? byte offset = m mod 4。 byte offset 0对应寄存器里的[7:0]; byte offset 1对应寄存器里的[15:8]; byte offset 2对应寄存器里的[23:16]; byte offset 3对应寄存器里的[31:24]。
想象这个寄存器是快递包裹的派送规则表,每个包裹(中断信号)都有专属的派送标签(目标CPU配置),告诉分拣中心:“这个包裹要送给几号分拣员(CPU)”。
核心规则详解
1️⃣ 表格结构(寄存器布局)
- 每个格子(寄存器)能管理4个包裹(中断ID),每个包裹的派送规则占一个小格子(8位)。
- 格子内部划分:
- 小格子3(字节偏移3):控制包裹的高优先级分拣员(对应寄存器的[31:24]位)
- 小格子2(字节偏移2):控制中等优先级分拣员(对应寄存器的[23:16]位)
- 小格子1(字节偏移1):控制普通分拣员(对应寄存器的[15:8]位)
- 小格子0(字节偏移0):控制备用分拣员(对应寄存器的[7:0]位)
2️⃣ 派送规则设定(二进制位含义)
- 每个小格子(8位)对应8个分拣员(CPU编号0-7),每位代表一个分拣员:
- 二进制1:这个分拣员需要接收此类包裹(中断)
- 二进制0:不分派给这个分拣员
- 举例:
0b00000111
(二进制)→ 分拣员0、1、2要接收包裹
3️⃣ 如何找到包裹对应的格子?
假设现在有一个包裹编号是 m(中断ID):
- 步骤1:找大格子(寄存器编号n)
n = m ÷ 4
(只取整数部分)- 比如:包裹编号m=9 →
n=9÷4=2
(第2个大格子)
- 比如:包裹编号m=9 →
- 步骤2:找小格子(字节偏移)
字节偏移 = m % 4
(取余数)- 比如:包裹编号m=9 →
9%4=1
→ 字节偏移1(对应寄存器的[15:8]位)
- 比如:包裹编号m=9 →
4️⃣ 实际贴标签(配置示例)
案例:想让包裹m=5同时派送给分拣员1和3:
1️⃣ 计算位置
n=5÷4=1
(使用第1个大格子GICD_ITARGETSR1)字节偏移=5%4=1
(操作寄存器的[15:8]位)
2️⃣ 设置二进制位- 分拣员1 → 第1位写1
- 分拣员3 → 第3位写1
- 最终值:
0b00001010
(二进制,对应十六进制0x0A)
特殊机制(隐藏规则)
- 自动识别分拣员:如果分拣员查看自己的派送任务表(读取寄存器),系统会自动显示当前分拣员的编号(比如CPU2读寄存器时,返回的值会包含自己的编号)。
- 多分拣员协作:一个包裹可以同时贴多个分拣员标签(多CPU处理同一个中断),但需要分拣中心协调避免重复派送。
为什么需要这个设计?
就像快递总部需要灵活调度:
1️⃣ 负载均衡:紧急包裹(高优先级中断)可以指定给空闲分拣员
2️⃣ 容灾备份:重要包裹可同时派送多个分拣员,避免漏单
3️⃣ 动态调整:根据分拣员忙闲状态,随时修改派送规则
希望这个比喻能让你像快递调度员一样轻松配置中断目标! 🚚💨
11. Interrupt Configuration Registers, GICD_ICFGRn
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[2F+1:2F] | Int_config, field F | R/W | 对于每一个中断,都有对应的2位数据用来描述:它的边沿触发,还是电平触发。 对于Int_config [1],即高位[2F + 1],含义为: 0:相应的中断是电平触发; 1:相应的中断是边沿触发。 对于Int_config [0],即低位[2F],是保留位。 |
对于一个中断,如何找到GICD_ICFGRn并确定相应的位域F?
对于interrtups ID m,如下计算: n = m DIV 16,GICD_ICFGRn里的n就确定了; GICD_ICACTIVERn 在GIC内部的偏移地址是多少?0xC00+(4*n) F = m mod 16。
12. Identification registers: Peripheral ID2 Register, ICPIDR2
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:0] | - | R/W | 由实现定义 |
[7:4] | ArchRev | R | 该字段的值取决于GIC架构版本: 0x1:GICv1; 0x2:GICv2。 |
[3:0] | - | R/W | 由实现定义 |
1.2.2 CPU interface寄存器描述
1. CPU Interface Control Register, GICC_CTLR
此寄存器用来控制CPU interface传给CPU的中断信号。对于不同版本的GIC,这个寄存器里各个位的含义大有不同。以GICv2为例,有如下2种格式:
以GIC2 with Security Extensions, Non-secure copy
为例,GICC_CTLR中各个位的定义如下:
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:10] | - | 保留 | |
[9] | EOImodeNS | R/W | 控制对GICC_EOIR和GICC_DIR寄存器的非安全访问: 0:GICC_EOIR具有降低优先级和deactivate中断的功能; 对GICC_DIR的访问是未定义的。 1:GICC_EOIR仅具有降低优先级功能; GICC_DIR寄存器具有deactivate中断功能。 |
[8:7] | - | 保留 | |
[6] | IRQBypDisGrp1 | R/W | 当CPU interface的IRQ信号被禁用时,该位控制是否向处理器发送bypass IRQ信号: 0:将bypass IRQ信号发送给处理器; 1:将bypass IRQ信号不发送到处理器。 |
[5] | FIQBypDisGrp1 | R/W | 当CPU interface的FIQ信号被禁用时,该位控制是否向处理器发送bypass FIQ信号: 0:将bypass FIQ信号发送给处理器; 1:旁路FIQ信号不发送到处理器 |
[4:1] | - | 保留 | |
[0] | - | R/W | 使能CPU interface向连接的处理器发出的组1中断的信号: 0:禁用中断信号 1:使能中断信号 |
整体比喻
这个寄存器相当于快递分拣中心控制台的 核心控制面板,有 32个隐藏开关(对应32个二进制位),但只有 5个关键按钮 真正生效,其他都是预留的空白按钮(保留位)。
重点按钮说明
1️⃣ VIP包裹处理模式(EOImodeNS 第9位)
- 作用:控制 VIP包裹(高优先级中断) 的分拣流程
- 按钮状态:
- 按下去(写1) → 流程:
✔️ 分拣员只需降低包裹优先级
✔️ 禁止手动取出包裹(无法调用DIR寄存器的退件功能) - 弹起来(写0) → 完整VIP流程:
✔️ 分拣员既要降低优先级,又要取出包裹
✔️ 手动退件功能激活(允许调用DIR寄存器)
- 按下去(写1) → 流程:
2️⃣ 紧急通道开关(IRQBypDisGrp1 第6位)
- 作用:当普通分拣通道(IRQ信号)关闭时,是否启用 紧急通道(bypass IRQ)
- 按钮状态:
- 按下去(写1) → 锁死紧急通道
🚫 所有包裹必须走常规分拣流程 - 弹起来(写0) → 开放紧急通道
🚨 紧急包裹直接送达分拣员(绕过常规流程)
- 按下去(写1) → 锁死紧急通道
3️⃣ 超级紧急通道开关(FIQBypDisGrp1 第5位)
- 作用:当特快分拣通道(FIQ信号)关闭时,是否启用 超级紧急通道(bypass FIQ)
- 按钮状态:与IRQ通道逻辑相同
- 写1:禁用超级通道
- 写0:激活超级通道
4️⃣ 总闸门开关(EnableGrp1 第0位)
- 作用:整个分拣中心的总电源开关
- 按钮状态:
- 按下去(写1) → 启动分拣中心
💡 所有分拣员开始处理包裹 - 弹起来(写0) → 切断电源
🔌 分拣中心停止运作,所有包裹堆积在仓库
- 按下去(写1) → 启动分拣中心
控制台操作指南
场景1:处理系统崩溃
1️⃣ 按下 总闸门(EnableGrp1=1) → 启动分拣中心
2️⃣ 按下 VIP处理模式(EOImodeNS=1) → 仅处理优先级,禁止手动退件
3️⃣ 弹起 紧急通道开关(IRQBypDisGrp1=0) → 允许紧急包裹直达CPU
场景2:系统维护模式
1️⃣ 关闭总闸门(EnableGrp1=0)→ 暂停所有分拣
2️⃣ 锁死所有紧急通道(IRQ/FIQBypDisGrp1=1)→ 彻底隔离系统
为什么这样设计?
就像快递分拣中心需要灵活应对各种突发状况:
- 模式切换:通过EOImodeNS切换VIP包裹处理逻辑,适应不同安全需求
- 紧急逃生:当常规通道故障时,bypass通道确保关键包裹不丢失
- 全局控制:总闸门一键切断所有分拣流程,便于系统维护
这排按钮让操作系统像分拣中心主管一样,既能精细控制单个流程,又能快速响应全局状态变化。💡
2. Interrupt Priority Mask Register, GICC_PMR
提供优先级过滤功能,优先级高于某值的中断,才会发送给CPU。
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:8] | - | 保留 | |
[7:0] | - | R/W | 优先级高于这个值的中断,才会发送给CPU |
[7:0]
共8位,可以表示256个优先级。但是某些芯片里的GIC支持的优先级少于256个,则某些位为RAZ / WI,如下所示:
如果有128个级别,则寄存器中bit[0] = 0b0,即使用[7:1]来表示优先级; 如果有64个级别,则寄存器中bit[1:0] = 0b00,即使用[7:2]来表示优先级; 如果有32个级别,则寄存器中bit[2:0] = 0b000,即使用[7:3]来表示优先级; 如果有16个级别,则寄存器中bit[3:0] = 0b0000,即使用[7:4]来表示优先级;
注意:imx6ull最多为32个级别
3. Binary Point Register, GICC_BPR
此寄存器用来把8位的优先级字段拆分为组优先级和子优先级,组优先级用来决定中断抢占。
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:3] | - | 保留 | |
[2:0] | Binary point | R/W | 此字段的值控制如何将8bit中断优先级字段拆分为组优先级和子优先级,组优先级用来决定中断抢占。 更多信息还得看看GIC手册。 |
想象每个包裹(中断)贴着一个 8位二进制紧急度标签(优先级字段,如0b10110011
)。GICC_BPR寄存器相当于一把 智能切割刀,它的作用是把这8位标签切成两部分:
- 前半段:组优先级(Group Priority) → 决定能否插队
(比如标签前半段不同,高优先级的包裹可以直接抢过分拣机) - 后半段:子优先级(Sub Priority) → 决定同组内的排队顺序
(同一组内的包裹按后半段顺序处理)
切割刀的使用说明书(寄存器结构)
这把刀只有 3个刻度按钮(对应寄存器的[2:0]位),其他区域都是固定死的([31:3]位保留无用):
███████████████████████████████ ▼ 刻度按钮 ███
[31.....................................3][2 1 0]
保留区域 二进制点位置
刻度按钮的作用(Binary Point值)
- 数值范围:0-7(3位二进制能表示的数)
- 实际含义:切割刀在第几位后落下
(比如刻度=3 → 前5位是组优先级,后3位是子优先级)
举个实际切割案例
假设现在有一个包裹的紧急度标签是 0b10110011
(十进制179):
1️⃣ 刻度设置为3(Binary Point=3)
- 切割位置:第3位(从右往左数,第0位开始)
→ 组优先级:0b10110
(前5位,十进制22)
→ 子优先级:0b011
(后3位,十进制3) - 效果:不同组的包裹可以互相抢占,同组的按子优先级排序
2️⃣ 刻度设置为5(Binary Point=5)
- 切割位置:第5位
→ 组优先级:0b101
(前3位,十进制5)
→ 子优先级:0b10011
(后5位,十进制19) - 效果:组划分更粗粒度,更多包裹可能属于同一组,减少抢占次数
为什么需要这把刀?
就像快递分拣中心需要动态调整插队规则:
-
高抢占模式(刻度值小):
→ 组优先级位数多 → 分组更细致 → 更多包裹能插队
(适合医院急救物资运输,紧急任务频繁的场景) -
低抢占模式(刻度值大):
→ 组优先级位数少 → 分组更粗略 → 系统更稳定
(适合普通物流,减少频繁插队导致的分拣机卡顿)
操作指南
- 开机初始化:根据业务需求设置切割刻度(比如刻度=3)
// 代码示例:设置二进制点为3 GICC_BPR = 3; // 写入[2:0]位
- 动态调整:若发现系统频繁被中断打乱,可调大刻度值减少分组数量
- 保留位警告:其他按钮([31:3]位)严禁乱按,可能导致分拣机故障!
通过这把“切割刀”,操作系统就像分拣中心主管,能灵活控制中断插队的精细度,平衡系统响应速度和稳定性。✂️🚚
4. Interrupt Acknowledge Register, GICC_IAR
CPU读此寄存器,获得当前中断的interrtup ID。
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:13] | - | 保留 | |
[12:10] | CPUID | R | 对于SGI类中断,它表示谁发出了中断。例如,值为3表示该请求是通过对CPU interface 3上的GICD_SGIR的写操作生成的。 |
[9:0] | Interrupt ID | R | 中断ID |
5. Interrupt Register, GICC_EOIR
写此寄存器,表示某中断已经处理完毕。GICC_IAR的值表示当前在处理的中断,把GICC_IAR的值写入GICC_EOIR就表示中断处理完了。
位域 | 名 | 读写 | 描述 |
---|---|---|---|
[31:13] | - | 保留 | |
[12:10] | CPUID | W | 对于SGI类中断,它的值跟GICD_IAR. CPUID的相同。 |
[9:0] | EOIINTID | W | 中断ID,它的值跟GICD_IAR里的中断ID相同 |
1.3 GIC编程
使用cortex A7处理器的芯片,一般都是使用GIC v2的中断控制器。 处理GIC的基地址不一样外,对GIC的操作都是一样的。 在NXP官网可以找到IMX6ULL的SDK包。 下载后可以参考这个文件:core_ca7.h,里面含有GIC的初始化代码。
10_实战_GPIO中断编程(IMX6ULL)
GPIO中断编程
目的:实现KEY2中断,按下、松开按键,串口输出相应信息。
1.1 先看原理图
-
100ASK IMX6ULL按键原理图
-
我们使用KEY2来演示中断的处理(它更复杂一点)
-
课后作业:实现KEY1的中断处理函数。
-
KEY2用的是GPIO04_IO14引脚
1.2 IMX6ULL的GPIO中断
IMX6ULL的GPIO中断在硬件上的框架,跟STM32MP157是类似的。 IMX6ULL中没有EXTI控制器,对GPIO的中断配置、控制,都在GPIO模块内部实现:
1.2.1 GPIO控制器
1. 配置GPIO中断
每组GPIO中都有对应的GPIOx_ICR1、GPIOx_ICR2寄存器(interrupt configuration register )。 每个引脚都可以配置为中断引脚,并配置它的触发方式:
整体比喻
这个寄存器相当于 16条快递传送带的触发规则控制面板,每条传送带(对应GPIO的16个输入引脚)有 4种触发模式,比如:
- 包裹静止不动时报警(低电平触发)
- 包裹被举起时报警(高电平触发)
- 包裹刚放上传送带时报警(上升沿触发)
- 包裹刚离开传送带时报警(下降沿触发)
控制面板结构
1️⃣ 面板布局(寄存器位结构)
- 总共有32个开关位(从31到0位),但 每2个位控制一条传送带
- 举例:
- 传送带15 → 31-30位(ICR15)
- 传送带0 → 1-0位(ICR0)
- 举例:
- 复位值全0:所有传送带默认关闭报警功能(就像感应器没通电)
2️⃣ 每条传送带的触发规则(2位字段的4种模式)
每个2位开关可以设置4种状态:
二进制值 | 比喻场景 | 实际含义 |
---|---|---|
00 | 关掉感应器 | 中断禁用 |
01 | 包裹一碰到传送带就响 | 高电平触发 |
10 | 包裹刚被放上传送带时响 | 上升沿触发(从低到高的瞬间) |
11 | 包裹刚被拿走时响 | 下降沿触发(从高到低的瞬间) |
实际操作指南
场景1:设置传送带5的触发规则
假设想让 传送带5(对应ICR5,占用11-10位)在 包裹刚被放上时报警:
1️⃣ 计算二进制值:
- 选择模式 10(上升沿触发)
2️⃣ 写入寄存器: - 将11-10位的值改为
0b10
// 代码示例(假设基地址为0x4000)
*(volatile uint32_t*)(0x4000 + 0xICR1偏移) |= (0b10 << 10);
场景2:关闭传送带15的报警
将31-30位(ICR15)设为 00
:
// 清空31-30位
*(volatile uint32_t*)(0x4000 + 0xICR1偏移) &= ~(0b11 << 30);
注意事项
1️⃣ 不要乱按其他按钮(保留位):
- 图中灰色区域(如位16-31中未被ICR占用的部分)是预留位,随意修改可能导致传送带混乱!
2️⃣ 复位状态全0:
- 系统重启后所有传送带默认关闭报警,需要重新设置触发模式
为什么需要这个设计?
就像快递中心需要灵活管理不同包裹的警报规则:
- 紧急包裹(如易碎品):设置为 上升沿触发(刚放上就优先处理)
- 普通包裹:设置为 下降沿触发(离开时才统计数量)
- 维护模式:直接关闭所有报警(设为00)
通过这个「触发感应器控制面板」,操作系统可以像调度员一样,精细控制每个GPIO引脚的中断触发条件,让硬件资源高效协作! 📦🚨
2. 使能GPIO中断
3. 判断中断状态、清中断
1.2.2 GIC
ARM体系结构定义了通用中断控制器(GIC),该控制器包括一组用于管理单核或多核系统中的中断的硬件资源。GIC提供了内存映射寄存器,可用于管理中断源和行为,以及(在多核系统中)用于将中断路由到各个CPU核。它使软件能够屏蔽,启用和禁用来自各个中断源的中断,以(在硬件中)对各个中断源进行优先级排序和生成软件触发中断。它还提供对TrustZone安全性扩展的支持。GIC接受系统级别中断的产生,并可以发信号通知给它所连接的每个内核,从而有可能导致IRQ或FIQ异常发生。
GIC比较复杂,下一个视频再详细讲解。
1.2.3 CPU
CPU的CPSR寄存器中有一位:I位,用来使能/禁止中断。
可以使用以下汇编指令修改I位:
CPSIE I ; 清除I位,使能中断 CPSID I ; 设置I位,禁止中断