GIC控制器 (三)

发布于:2025-07-12 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

分发器

GICD_CTLR寄存器

GICD_TYPER寄存器

 GICD_ISENABLERn寄存器组

GICD_ICENABLERn寄存器组

GICD_IPRIORITYRn寄存器组

GICD_IGROUPRn寄存器组

GICD_ICPENDRn寄存器组

CPU接口

GICC_CTLR寄存器

GICC_PMR寄存器

GICC_BPR寄存器

中断抢占的协同逻辑

GICC_IAR寄存器

GICC_EOIR寄存器


前言:

结合 GIC控制器(一)-CSDN博客 与 GIC控制器(二)-CSDN博客 ,本文旨在系统梳理 GIC 控制器的常用寄存器及其功能,详细介绍GIC控制器中的分发器寄存器与CPU接口寄存器;

分发器

GICD_CTLR寄存器

GICD_CTLR核心功能:控制 Pending(挂起)状态的中断是否会被转发给到CPU接口

bit[31:2]:  保留位,软件必须忽略这些位写操作可能触发未定义行为,读操作返回不可预测值;

bit [1]:Group 1 中断转发使能位,控制 Group 1 中断从分发器到 CPU 接口的转发;

  • 0:Group 1 中断不转发(即使处于 Pending 状态,也无法到达 CPU 接口);
  • 1:Group 1 中断允许转发,但最终是否触发 CPU 中断,还受 优先级规则、抢占逻辑 约束;

bit [0]:Group 0 中断转发使能位,控制 Group 0 中断从分发器到 CPU 接口的转发;

  • 0:Group 0 中断不转发。
  • 1:Group 0 中断允许转发,但受 优先级规则、抢占逻辑 约束;

优先级规则限制的具体含义:

即使 EnableGrp0或EnableGrp1 置 1,中断也不一定能触发 CPU需同时满足:

  • 中断优先级 > CPU 接口的优先级掩码(GICC_PMR);
  • 中断未被其他掩码(如 GICD_IGRP0/1 组掩码)屏蔽;
  • 符合抢占规则(如高优先级中断可抢占低优先级任务);

GICD_TYPER寄存器

GICD_TYPER 为只读寄存器,核心作用如下:

  • 告知系统支持的 CPU 接口数量(决定中断可分发到多少个核心);
  • 告知系统支持的 最大中断数量(决定可用中断 ID 范围);
  • 标识是否实现 安全扩展(Security Extensions),以及安全扩展相关的特性;

bit [31:16] 位:保留位

bit [15:11] 位:LSPI(Lockable SPIs)

  • 条件:仅当 GIC 实现 安全扩展(Security Extensions) 时,该字段有效,否则保留;
  • 功能:表示 GIC 支持的可锁定 SPI(共享外设中断)的最大数量,范围 0 到 31;
    • 可锁定 SPI:用于 配置锁定(Configuration Lockdown) 机制,确保安全关键的中断配置(如中断优先级、分组)不被非安全环境篡改,增强系统安全性;

bit [10] :SecurityExn,安全扩展指示,标识 GIC 是否实现安全扩展

  • 0:未实现安全扩展(系统不区分安全 / 非安全中断,所有中断统一管理);
  • 1:已实现安全扩展(系统支持安全 / 非安全中断分离,需配合其他寄存器管理);

bit [9:8] :Reserved(保留位)

bit [7:5] :CPUNumber(CPU 接口数量)

指示 GIC 实现的 CPU 接口数量,计算方式为:实际 CPU 接口数 = 字段值 + 1示例如下:

  • 字段值 0b011(3)→ 实际有 4 个 CPU 接口;
  • 字段值 0b000(0)→ 实际有 1 个 CPU 接口;

bit [4:0] :ITLinesNumber(中断线数量)用于指示 GIC 支持的 最大中断数量计算方式为:最大中断数 = 32 × (字段值 + 1)

  • 字段值 0b00011(3)→ 最大中断数   4 × 32 = 128,中断 ID 范围 0127
  • 字段值 0b11111(31)→ 最大中断数 32 × 32 = 1024(但实际文档提到最大为 1020,因 10201023 为特殊中断预留);

 GICD_ISENABLERn寄存器组

GICD_ISENABLERn寄存器控制单个中断的转发使能状态,每个比特位独立控制一个中断的使能状态,核心作用如下:

  • 写操作:对某一位写 1 → 允许对应中断从分发器转发到 CPU 接口(使能中断),写 0 → 无效果;
  • 读操作:某一位读 1 → 对应中断已使能,读 0 → 对应中断未使能;

GICD_ISENABLERn寄存器中n是寄存器编号,用于区分不同中断范围的使能控制因为 GIC 支持的中断数量必定超过 32 个(如最大 1020 个中断),而一个 32 位寄存器只能控制 32 个中断,因此需要多个 ISENABLER 寄存器,用 n 标识分组:

  • GICD_ISENABLER0 → 控制 中断 0~31
  • GICD_ISENABLER1 → 控制 中断 32~63
  • GICD_ISENABLER2 → 控制 中断 64~95
  • ... 以此类推,直到覆盖所有中断(数量由 GICD_TYPER.ITLinesNumber 决定)

若要控制中断 ID = m 的使能状态,需通过以下步骤找到对应的 GICD_ISENABLERn 寄存器及对应比特位:

一  确定寄存器编号 : n=m ÷ 32

  • 例:m=35 → 35 ÷ 32 = 1 → n=1(对应 GICD_ISENABLER1)。

二 计算寄存器偏移量:偏移量 = 0x100 + (4 × n)
0x100 是 ISENABLER 寄存器组的起始偏移;4 × n 是因每个寄存器占 4 字节,n 个寄存器的总偏移

  • 例:n=1 → 偏移量 = 0x100 + 4×1 = 0x104

 三 确定寄存器内的比特位位置:位号 = m % 32(取余)

  • 例:m=35 → 35 % 32 = 3 → 操作 GICD_ISENABLER1 的bit3

GICD_ICENABLERn寄存器组

中断清除使能寄存器(GICD_ICENABLERn)的核心作用是关闭特定中断从分发器到 CPU 接口,每个比特位独立控制一个中断的转发清除;

一 读操作

  • 某一位读 0 → 对应中断的转发已被禁用(无法从分发器到 CPU 接口);
  • 某一位读 1 → 对应中断的转发仍使能(可正常转发);
  • 本质:反馈当前中断的转发使能状态;

二 写操作

  • 写 0 → 无效果(无法通过写 0 恢复使能,需用 GICD_ISENABLERn 写 1 重新使能);
  • 写 1 → 强制清除转发使能:
    • 操作后,对应中断的转发被关闭(即使之前是使能状态);
    • 后续读该位会返回 0(确认清除成功);

GICD_IPRIORITYRn寄存器组

中断优先级配置寄存器(GICD_IPRIORITYR) 的核心作用是用于为每个中断设置优先级数值,决定中断的抢占顺序;

  • 当多个中断同时触发时,CPU 先响应谁(低数值的中断 "插队"能力更强);
  • 当高优先级中断触发时,能否打断当前正在处理的低优先级中断(低数值中断可抢占高数值中断);

GICD_IPRIORITYRn寄存器组中每个寄存器被拆分为 4 个独立的字节字段(每个 8 位),分别为字节偏移0、字节偏移1、字节偏移2、字节偏移3,每个字节控制一个中断源的优先级,一个寄存器覆盖 4 个中断 的优先级配置;

系统中每个中断源具有唯一的中断 ID,假设中断ID为m,需通过以下公式映射到具体寄存器和字节段:

一 计算寄存器编号 n: n = m ÷ 4 (取商)

  • 含义:每 4 个中断共享 1 个 GICD_IPRIORITYR 寄存器(节省硬件资源);

二 计算寄存器地址偏移:地址偏移 = 0x400 + (4 × n) 

  • 0x400 是 GICD_IPRIORITYR 寄存器组的起始偏移;
  • 4 × n 是因每个寄存器占 4 字节(32 位),n 个寄存器的总偏移;

三 计算字节段偏移:字节偏移 = m % 4 (取余)

  • 字节偏移 0 → 对应寄存器的 [7:0] 位(控制第 4n+0 号中断);
  • 字节偏移 1 → 对应寄存器的 [15:8] 位(控制第 4n+1 号中断);
  • 字节偏移 2 → 对应寄存器的 [23:16] 位(控制第 4n+2 号中断);
  • 字节偏移 3 → 对应寄存器的 [31:24] 位(控制第 4n+3 号中断);

假设中断 ID m=5,推导过程如下:

一 计算寄存器编号 n
n = 5 ÷ 4 = 1(商为 1)→ 对应 GICD_IPRIORITYR1 寄存器。

二 计算地址偏移
地址偏移 = 0x400 + (4 × 1) = 0x404
→ 若 GICD 基地址为 0x10000000,则实际地址为 0x10000404

三  计算字节偏移
字节偏移 = 5 % 4 = 1 → 对应 Priority, byte 1(寄存器的 [15:8] 位)

GICD_IGROUPRn寄存器组

中断组寄存器(GICD_IGROUPR)的核心作用是为 GIC 支持的每个中断提供一个状态位,每个比特位控制对应的中断属于 组 0(Group 0) 还是 组 1(Group 1)

• 0:对应中断属于 组 0(Group 0)
• 1:对应中断属于 组 1(Group 1)

注意:启动或复位时,ID≥32 的中断默认属于组 0,因此所有 SPI(共享外设中断)初始为组 0,除非系统重新编程对应的 GICD_IGROUPR 位;

GICD_ICPENDRn寄存器组

中断清除挂起寄存器(GICD_ICPENDRn)核心作用是清除中断挂起状态,中断挂起状态指中断信号已被硬件 / 软件触发,但尚未被处理器处理 时的中间状态;

读操作

  • 0:中断在所有 CPU 上均未挂起(或未实现);
  • 1:若为SGI/PPI类型中断,该中断当前 CPU 上中断挂起,若为SPI类型的中断,表示该中断至少一个 CPU 上中断挂起;

写操作

  •  0:无效果(不改变挂起状态)。
  •  1仅对 SPI 和 PPI 生效,若为边缘触发且中断状态之前为 pending → 变为 inactive,若为边缘触发且中断状态之前为 active and pending → 变为 active;若为电平触发,若挂起仅因写 GICD_ISPENDRn(软件触发)→ 清除为 inactive; 若硬件信号仍有效 → 清除后会重新挂起,需确保硬件信号已释放,否则无法彻底清除;

CPU接口

GICC_CTLR寄存器

CPU接口控制寄存器(GICC_CTLR),主要用于配置中断控制器的中断使能、EOI 模式、优先级掩码规则、FIQ/IRQ 控制等;

bit[0]:组 0 中断使能位EnableGrp0,用于控制 组 0 中断 的全局使能,当配置为0时,组 0 中断全部禁用,当配置为1时,组0中断全局使能
bit[3]: FIQ使能位FIQEn,用于控制 GIC 是否向 CPU 输出 FIQ 中断,配置为0代表禁用 FIQ 输出,配置为1代表使能 FIQ 输出;

bit[4]:   CBPR(Current Priority Binary Point) 决定 Group 0或者Group 1 中断的优先级比较规则,若配置为0,则优先级用 8 位纯数值比较(0 最高,255 最低);若配置为1,则 优先级按 "二进制点" 拆分(如高 4 位抢占优先级、低 4 位子优先级);

GICC_PMR寄存器

CPU 接口优先级掩码寄存器(GICC_PMR)决定 哪些中断可以被转发到 CPU,即只有中断的优先级高于该寄存器中存储的值时,CPU 接口才会向处理器发送中断信号;

bit[31:8]: 保留位;

bit[7:0]:  CPU 接口的 优先级掩码阈值,若中断优先级高于该阈值(数值更小),CPU 会收到中断信号;

  • 若GIC支持的级别少于 256 级,低位会被强制固定为 0,若GIC支持的优先级范围为256 级,则bit[7:0]全部有效;
  • 若GIC支持的优先级范围为128 级,则bit[7:1]有效,bit[0]被强制固定为 0
  • 若GIC支持的优先级范围为64 级,则bit[7:2]有效,bit[1:0]被强制固定为 0
  • 若GIC支持的优先级范围为32级,则bit[7:3]有效,bit[2:0]被强制固定为 0
  • 若GIC支持的优先级范围为16级,则bit[7:4]有效,bit[3:0]被强制固定为 0

GICC_BPR寄存器

二进制点寄存器(GICC_BPR)将中断优先级字段拆分为组优先级字段(group priority) 和 子优先级字段(subpriority),特点如下:

  • 组优先级(Group Priority):高几位,决定中断能否抢占当前任务(高组优先级可打断低组优先级);
  • 子优先级(Subpriority):低几位,决定同组优先级中断的响应顺序(不触发抢占,仅决定执行顺序);

中断源的优先级固定为8个比特位(GICD_IPRIORITYR),其分配规则如下:

  • 组优先级位数 =7 - Binary point(决定中断抢占),范围 [7: BP+1]
  • 子优先级位数 =  Binary point + 1(决定同组内响应顺序),范围  [BP: 0]

    中断抢占的协同逻辑

    GICC_BPR (二进制点)配合 GICC_PMR(优先级掩码) 和 GICD_IPRIORITYR(中断优先级配置),共同决定中断响应流程:

    1. GICD_IPRIORITYR:配置每个中断的 8 位优先级;
    2. GICC_BPR:分割优先级为组优先级(抢占控制)和子优先级(同组顺序);
    3. GICC_PMR:设置 CPU 响应的优先级门槛(仅高于门槛的中断才会触发);

    GICC_IAR寄存器

    CPU 接口端的中断确认寄存器(GICC_IAR)核心作用为 让 CPU 获取当前触发中断的唯一标识(中断ID),以及多核心场景下 SGI 的发起者信息;

    bit [31:13]: 保留位

    bit [12:10]: CPUID,仅对SGI类型中断有效,标识发起SGI类型的中断的CPU接口编号;

    bit [9:0]:   中断ID,范围通常为0~1019,标识中断源的唯一性,若读取 Interrupt ID ≥ 1020,可能是伪中断(Spurious Interrupt),需忽略(表示无实际中断触发);

    GICC_EOIR寄存器

    CPU 接口端的中断结束寄存器(GICC_EOIR),其核心作用如下:

    1. 通知 GIC:CPU 已完成对某中断的处理;
    2. 触发优先级调整(GICv2 场景):配合 GICC_CTLR的EOImode位,实现优先级下降(Priority Drop),控制后续中断的抢占规则;

    一  有效中断的 EOIR 必写

    • 若 GICC_IAR 读回 有效 ID(≠1023),必须向 GICC_EOIR 写入相同的 ID,否则 GIC 会认为中断未完成,导致同一中断持续触发并且阻塞后续中断响应;

    二  伪中断的 EOIR 可忽略

    • 若 GICC_IAR 读回 伪中断(ID=1023),无需写 EOIR;即使写了,GIC 也会忽略(防止无效操作干扰);

     通用中断响应流程:

    1. 中断触发:外设(SPI/PPI)产生中断,GIC 分发器将其路由到 CPU 接口;
    2. 进入中断模式:CPU 硬件自动响应中断,暂停当前任务;
    3. 读取 GICC_IAR:获取 Interrupt ID ,确定具体的中断源;
    4. 执行中断服务程序(ISR):根据 Interrupt ID 调用对应的中断处理函数;
    5. 清除中断:写 GICC_EOIR 寄存器,告知 GIC 中断已处理;

     

     


    网站公告

    今日签到

    点亮在社区的每一天
    去签到