3、中断控制器:T113 内部 GIC 架构与中断号分配
全志 T113 处理器内部集成了 ARM 通用中断控制器 (Generic Interrupt Controller, GIC),版本为 GIC-400。GIC 是连接外设中断源与 CPU 核心的桥梁,负责中断的使能、屏蔽、优先级仲裁以及分发。理解 GIC 的架构、中断号分配规则以及触发类型,是编写正确且高效 GPIO 中断驱动的理论基础。
3.1 GIC 架构分层与核心组件
T113 的 GIC-400 采用经典的两层架构:分发器 (Distributor) 和 CPU 接口 (CPU Interface)。分发器负责全局中断管理,CPU 接口则负责将中断信号传递给具体的 CPU 核心。
架构要点: 分发器与 CPU 接口通过独立的寄存器组进行配置,驱动开发中需要分别操作这两类寄存器以实现中断的完整控制流程。
3.2 中断号分配规则
T113 的 GIC 支持三种中断类型:共享外设中断 (SPI)、私有外设中断 (PPI) 和 软件触发中断 (SGI)。GPIO 中断属于 SPI 类型,其中断号由 GPIO Bank 和 Pin 的物理位置共同决定。
| 中断类型 | ID 范围 | 描述 | 典型用途 |
|---|---|---|---|
| SGI | ID 0 – 15 | 软件触发中断,用于核间通信 | CPU Core 0 向 Core 1 发送 IPI |
| PPI | ID 16 – 31 | 私有外设中断,每个 CPU 核心独有 | 本地定时器、看门狗、性能监视 |
| SPI | ID 32 – 159 | 共享外设中断,所有核心共享 | GPIO 中断、UART、SPI、I2C、DMA |
GPIO 中断号速查: GPIO Bank A 对应 SPI ID 32–63,Bank B 对应 64–95,Bank C 对应 96–127,Bank D 对应 128–159。每个 Bank 内部按 Pin 号顺序分配,例如 PA0 对应 ID 32,PA1 对应 ID 33,以此类推。
3.3 中断触发类型:边沿与电平
GIC 支持两种中断触发类型:边沿触发 (Edge-triggered) 和 电平触发 (Level-triggered)。GPIO 中断通常配置为边沿触发,但某些特殊场景(如按键长按检测)可能需要电平触发。两种类型的差异直接影响中断响应逻辑和去抖处理方式。
| 特性 | 边沿触发 (Edge) | 电平触发 (Level) |
|---|---|---|
| 触发条件 | 信号上升沿或下降沿 | 信号保持高电平或低电平 |
| 中断锁存 | GIC 锁存边沿事件,即使 CPU 未及时响应也不会丢失 | 中断信号必须保持有效电平,直到 CPU 应答 |
| 重复触发 | 仅触发一次,除非信号再次跳变 | 只要电平有效,中断会持续挂起 |
| 去抖需求 | 硬件或软件去抖,防止毛刺误触发 | 通常不需要去抖,但需注意电平保持时间 |
| GPIO 适用场景 | 按键按下/释放、脉冲计数、编码器 | 状态检测、唤醒源、长按检测 |
| GIC 配置寄存器 | GICD_ICFGRn 对应位设为 0b01 (上升沿) 或 0b11 (双沿) |
GICD_ICFGRn 对应位设为 0b00 (高电平) 或 0b10 (低电平) |
电平触发陷阱: 使用电平触发时,如果中断服务程序 (ISR) 没有清除外设的中断挂起状态(例如 GPIO 中断状态寄存器),GIC 会认为中断仍然有效,导致 CPU 反复进入中断,形成“中断风暴”。务必在 ISR 中先清除 GPIO 内部中断标志,再写 GIC 的 EOI 寄存器。
3.4 GIC 寄存器操作要点
在 GPIO 中断驱动中,需要操作以下 GIC 关键寄存器组:
- GICD_CTLR (0x01C81000):分发器控制寄存器,使能分发器。
- GICD_ISENABLERn (0x01C81100 + 4*n):中断使能寄存器,将对应 SPI ID 的位写 1 使能中断。
- GICD_ICENABLERn (0x01C81180 + 4*n):中断屏蔽寄存器,写 1 屏蔽中断。
- GICD_ICFGRn (0x01C810C00 + 4*n):中断配置寄存器,配置触发类型(边沿/电平)和极性。
- GICD_ICPENDRn (0x01C81280 + 4*n):中断清除挂起寄存器,用于清除误挂起状态。
- GICC_IAR (0x01C8200C):CPU 接口中断应答寄存器,读取获取当前中断 ID。
- GICC_EOIR (0x01C82010):CPU 接口中断结束寄存器,写入中断 ID 表示处理完成。
驱动初始化流程:
1. 配置 GPIO 引脚为中断模式,设置触发极性 (上升沿/下降沿/高电平/低电平)。
2. 配置 GICD_ICFGRn 设置触发类型。
3. 配置 GICD_ISENABLERn 使能对应 SPI 中断。
4. 配置 CPU 接口 GICC_PMR 设置优先级掩码。
5. 使能 GICD_CTLR 和 GICC_CTLR。
6. 在 ISR 中:读取 GICC_IAR → 处理 GPIO 中断状态 → 清除 GPIO 中断标志 → 写 GICC_EOIR。
1. 配置 GPIO 引脚为中断模式,设置触发极性 (上升沿/下降沿/高电平/低电平)。
2. 配置 GICD_ICFGRn 设置触发类型。
3. 配置 GICD_ISENABLERn 使能对应 SPI 中断。
4. 配置 CPU 接口 GICC_PMR 设置优先级掩码。
5. 使能 GICD_CTLR 和 GICC_CTLR。
6. 在 ISR 中:读取 GICC_IAR → 处理 GPIO 中断状态 → 清除 GPIO 中断标志 → 写 GICC_EOIR。
3.5 中断响应延迟与优先级
GIC 支持 16 级中断优先级 (0–15,0 为最高)。GPIO 中断通常配置为中等优先级 (例如 8–10),避免阻塞高实时性外设(如定时器、DMA)。中断响应延迟受以下因素影响:
| 因素 | 典型延迟 (CPU 主频 1.2GHz) | 说明 |
|---|---|---|
| GIC 硬件仲裁 | ~50 ns | 分发器比较优先级,选择最高优先级中断 |
| CPU 中断入口 | ~100 ns | CPU 保存上下文,跳转到中断向量表 |
| ISR 执行 | 取决于代码 | GPIO 中断 ISR 应尽量短,仅做标志置位或数据搬运 |
| 中断嵌套 | 额外 50–200 ns | 高优先级中断可抢占低优先级 ISR |
优化建议: 在 GPIO 中断 ISR 中,避免调用可能导致睡眠的函数(如
printk、mutex_lock)。使用 tasklet 或 workqueue 将耗时操作推迟到下半部执行,确保中断响应延迟在微秒级。