当前位置: 首页 > news >正文

GIC控制器(二)

目录

GIC结构框图

中断类型

外部中断触发方式

边缘触发(Edge-triggered)

电平敏感(Level-sensitive)

中断状态

中断分派模式

1-N 模式

N-N 模式

处理器安全状态

GIC逻辑分块

分发器(GIC Distributor)

GICD Memory-Map    

CPU接口(CPU Interface)

GICC Memory-Map

编写IRQ异常处理框架


前言:

         结合GIC控制器(一)-CSDN博客 由于协处理器CP15的CBAR寄存器 保存 GIC(通用中断控制器)的基地址当 IRQ 中断发生时,处理器会跳转到IRQ入口执行,汇编启动文件IRQ异常需要处理的任务如下:

  • 保存上下文(寄存器状态),通过 CBAR寄存器获取GIC控制器的基地址;
  • 通过GIC 的某个寄存器获取中断 ID,确定是哪个中断源;
  • 跳转到 C 语言的中断处理函数;
  • 中断处理函数执行完成后,通过 GIC 的某个寄存器清除中断状态;
  • 最后恢复上下文,返回被中断的程序继续执行;

由于 GICv2 广泛应用于 Cortex-A 系列处理器,基于前文基础,本文将对GICv2控制器展开深入讨论;

GIC 接收众多的外部中断,然后对其进行处理,最终通过FIQ(快速中断)信号与IRQ(普通中断) 报给 ARM 内核,本文仅讨论 IRQ,所以相当于 GIC 最终向 ARM 内核上报一个 IRQ 信号;

参考资料

Cortex-A7 MPCore Technical Reference Manual

ARM Generic Interrupt Controller Architecture version 2.0

GIC结构框图

中断类型

  • SGI (Software-generated Interrupt),软件中断,由软件触发引起的中断,采用中断号标识中断源的唯一性,SGI中断号为0~15,系统会使用 SGI 中断来完成多核之间的通信;
  • GIC 架构中,外设中断(Peripheral Interrupt)是通过硬件信号触发的中断类型,主要分为私有外设中断(PPI)和共享外设中断(SPI),每种中断又支持边缘触发电平敏感 两种触发方式;
  • PPI (Private Peripheral Interrupt),私有外设中断,GIC 控制器支持多核,每个核具有自己独有的中断,PPI中断号为16~31,中断信号直接绑定到特定处理器,无需分发器仲裁;
  • SPI(Shared Peripheral Interrupt) ,共享外设中断,所有处理器共享的中断,可被分发器路由到多个处理器组合的外设中断,SPI中断号为 32~1019 ,既支持中断信号仅发送给指定处理器(默认模式)又可以使得多个处理器同时接收中断,但各自应答;

由于常用外设(GPIO/UART/...) 通常为系统级资源,而非某个处理器核心的私有资源,所哟常用外设产生的中断属于SPI类型,某个 中断ID 对应 哪个中断 取决于芯片厂商定义;

外部中断触发方式

边缘触发(Edge-triggered)

核心特点:由信号的 “跳变瞬间” 触发,触发后状态持续保持直到主动清除;

  • 触发条件:当检测到中断信号的 上升沿/ 下降沿 时,中断状态被激活,通知处理器需要处理;
  • 状态保持:一旦触发,无论后续信号是高电平还是低电平,中断的 激活状态 会一直保持,直至满足清除条件;
  • 注意事项:边沿触发中断则需要确保触发后及时清除状态(否则可能因状态持续存在导致重复处理);

电平敏感(Level-sensitive)

核心特点:由信号的 “持续电平状态” 决定,中断状态随信号电平实时变化;

  • 触发条件:当中断信号处于有效电平(高电平/低电平)时,中断状态被激活;
  • 状态保持:只要电平有效,中断就持续存在;电平无效,中断就立刻消失,没有保持的过程;
  • 注意事项:电平敏感中断要求外设必须保持有效电平直到处理器处理完毕(否则信号提前消失会导致中断被 GIC 移除导致漏处理)

中断状态

  • Inactive:中断未触发状态
  • Pending:由于外设硬件或者软件产生中断事件,该中断事件通过硬件信号已通知GIC,等待GIC分配具体某个CPU进行处理;
  • Active: CPU已经应答某个中断请求并且正在处理该请求但未处理结束;
  • Active and Pending: 当一个中断源处于Active状态时,同一中断源又触发了中断,进入Pending状态;

中断分派模式

1-N 模式

1-N 模式的中断表示中断可以发给所有的 CPU,但只能由一个 CPU 来处理中断

  • 1-N 模式的中断有 N 个目标 CPU,但只能由其中一个来处理;
  • 当某一个处理器应答了该中断,便会清除在所有目标处理器上该中断的挂起状态;
  • SPI 使用 1-N 模式;

N-N 模式

N-N 模式的中断表示中断可以发给所有 CPU,每个 CPU 可以同时处理该中断;

  • 当该中断被某一个处理器应答了,这不会影响该中断在其他 CPU 接口上的状态;
  • PPI 和 SGI 使用 N-N 模式;

处理器安全状态

ARM处理器状态分类:

  • 安全状态(Secure state):运行敏感代码,可访问安全资源;
  • 非安全状态(Non-secure state):运行普通代码,仅能访问非安全资源;
  • 当处理器为非安全状态,只能操作 GIC中非安全相关的资源;
  • 当处理器为安全状态,既能操作 GIC中安全资源,也能操作GIC中非安全资源;

GICv2 为支持 ARM 安全扩展,将中断划分为两组:

  • Group 0:安全中断,用于处理敏感事件(如安全启动、加密模块中断),优先配置为FIQ保证高优先级,仅允许安全状态的处理器访问和处理;
  • Group 1:非安全中断,用于处理通用外设事件(如 SPI、UART、GPIO),只能配置为 IRQ,允许非安全状态的处理器访问,也支持安全状态的处理器兼容访问;

GIC逻辑分块

 GIC 架构分为两个逻辑块:Distributor 和 CPU Interface,即分发器端和 CPU 接口端;

分发器(GIC Distributor)

分发器 集中管理所有中断源,确定每个中断的优先级,并为每个 CPU 接口转发当前最高优先级的中断,分发器提供以下编程接口功能:

  • 全局使能 中断向 CPU 接口的转发 功能;
  • 使能或禁用单个中断;
  • 设置每个中断的优先级;
  • 设置每个中断的目标处理器列表(即中断发给哪些 CPU);
  • 将外设中断 配置为电平敏感型 或 边缘触发型;
  • 将每个中断配置为 Group 0 或 Group 1(安全 / 非安全分组);

GICD Memory-Map    

计算 GICD寄存器的物理地址,以GICD_CTLR寄存器为例根据 GIC 内存映射表:

  1. 分发器(Distributor)的偏移:相对于PERIPHBASE,分发器的基地址偏移为 0x1000(表 8-1 中0x1000-0x1FFF为 Distributor)。

  2. GICD_CTLR 的偏移:在分发器内部,GICD_CTLR 的偏移为 0x00(表 4-1 中 Offset 为0x00

GICD_CTLR 的物理地址 = PERIPHBASE(CBAR寄存器的值) + 0x1000(分发器偏移) + 0x00(GICD_CTLR偏移)

CPU接口(CPU Interface)

每个 CPU 接口模块为连接到 GIC 的处理器提供交互接口,每个 CPU 接口提供以下编程接口功能:

  • 使能 向处理器发送中断请求信号 的功能;
  • 应答中断;
  • 指示中断处理完成;
  • 为处理器设置中断优先级掩码(过滤低优先级中断);
  • 为处理器定义抢占策略(高优先级中断能否打断低优先级);
  • 确定处理器的最高优先级挂起中断(Pending 状态的中断中,优先级最高的那个)

当 CPU 接口使能时,它会为连接的处理器选取最高优先级的挂起中断,并根据 处理器的中断优先级掩码(低于掩码优先级的中断会被过滤)与 处理器的抢占设置(是否允许高优先级中断抢占当前中断)判断该中断的优先级是否足够高,以决定是否向处理器发送中断请求 

当处理器检测到IRQ信号时,处理器通过 读取 CPU 接口的 中断应答寄存器 GICC_IAR应答中断请求,此动作实现两个核心功能:

获取中断 ID

GICC_IAR 返回 当前最高优先级的 Pending 中断的 ID处理器通过此 ID,就能知道 具体要处理哪个中断 ,从而调用对应的中断服务程序(ISR);

触发 GIC 状态变化

读取 GICC_IAR 的动作,会让 GIC 内部的 中断状态 发生转换:

  • 对于 边沿触发中断:中断状态从 Pending → Active(表示处理器已开始处理该中断);

  • 对于 电平触发中断:中断状态从 Pending → Active and Pending(若外设仍保持电平有效,中断会持续挂起;若电平已撤销,则转为 Active);

当处理器的中断处理程序完成中断处理后,需向 CPU 接口写入数据以指示中断完成中断完成分为两个阶段:

  • 优先级下降(priority drop):表示已处理中断的优先级不再阻止向处理器发送新的中断(即允许后续中断抢占,即使优先级更低);
  • 中断去激活(interrupt deactivation):表示分发器会移除该中断的活跃状态(标记为已处理);

GICC Memory-Map

计算 GICC寄存器的物理地址,以GICC_CTLR寄存器为例根据 GIC 内存映射表:

  1. CPU接口(CPU Interface)的偏移:相对于PERIPHBASE,CPU接口的基地址偏移为 0x2000(表 8-1 中0x2000-0x3FFF为CPU接口端)。

  2. GICC_CTLR 的偏移:在CPU接口端内部,GICC_CTLR 的偏移为 0x0000(表 4-2 中 Offset 为 0x0000

GICC_CTLR 的物理地址 = PERIPHBASE(CBAR寄存器的值) + 0x2000(分发器偏移) + 0x0000(GICC_CTLR偏移)

编写IRQ异常处理框架

@startup.s文件(ARM汇编启动文件)
.text
.global _start
_start:@ 1. 安装异常向量表b resetldr pc,=undefine_instructionldr pc,=software_interruptldr pc,=prefetch_abortldr pc,=data_abortldr pc,=not_usedldr pc,=irqldr pc,=fiq@ 2 reset异常
reset:cpsid i  @ 关闭IRQ中断@ 2.1 设置异常向量表的基地址,统一采用加载-修改-写回的方式修改寄存器@ 2.1.1 设置异常向量表基地址选择位为0(SCTLR bit[13])mrc p15,0,r0,c1,c0,0  @系统控制寄存器 (SCTLR) 的值读取到 r0 寄存器中bic r0, r0,#(0x1<<13)mcr p15,0,r0,c1,c0,0  @ 将r0寄存器里修改后的值写回到系统控制寄存器 (SCTLR)@ 2.1.2 ldr r0,=0x87800000    @ 设置异常向量表基地址为0x87800000mcr p15,0,r0,c12,c0,0 @ 将0x8780000写入到VBAR寄存器@2.2 设置系统控制寄存器以关闭MMU,I/D cache,分支预测,对齐检查等mrc p15,0,r0,c1,c0,0bic r0,r0,#(0x1<<0)      @ 关闭MMUbic r0,r0,#(0x1<<1)      @ 关闭内存对齐检查bic r0,r0,#(0x1<<2)      @ 关闭数据缓存bic r0,r0,#(0x1<<10)     @ 禁用SWP指令bic r0,r0,#(0x1<<11)     @ 禁用分支预测bic r0,r0,#(0x1<<12)     @ 关闭I Cachemcr p15,0,r0,c1,c0,0 @2.3 初始化IRQ模式的栈空间,栈空间大小为2Mmrs r0,cpsrbic r0,r0,#0x1F orr r0,r0,#0x12 @ CPSR寄存器IRQ模式取值为10010msr cpsr,r0ldr sp,=0x80600000 @ 栈空间类型为满递减栈@2.3 初始化系统模式栈空间,栈空间大小为1M@ 注:用户模式与系统模式共用同一套寄存器,因此栈顶指针寄存器相同mrs r0,cpsrbic r0,r0,#0x1F orr r0,r0,#0x1F @ CPSR寄存器SYS模式取值为11111msr cpsr,r0ldr sp,=0x80400000@2.4 初始化FIQ模式的栈空间,栈空间大小为1Mmrs r0,cpsrbic r0,r0,#0x1F orr r0,r0,#0x11 @ CPSR寄存器FIQ模式取值为10001msr cpsr,r0ldr sp,=0x80300000@2.5 初始化SVC模式的栈空间,栈空间大小为2Mmrs r0,cpsrbic r0,r0,#0x1F orr r0,r0,#0x13 @ CPSR寄存器SVC模式取值为10011msr cpsr,r0ldr sp,=0x80200000cpsie i         @ 开启IRQ中断@ 2.6  清空bss段ldr r0,=__bss_startldr r1,=__bss_end@ 将r2寄存器的值(0)写入r0所指向的空间,每写一个0,r0地址自动加1mov r2,#0 @ 将寄存器r2中的值存储到r0所指向的内存空间,然后R0的值递增@ IA:先存数据,后增地址@ IB:先增地址,后存数据
loop:stmia r0!,{r2}cmp r0,r1@ r0小于等于r1,继续循环ble loop@ 2.7. 跳入main函数b mainirq:@ 3.1 考虑指令三级流水线的影响,需要修正程序的返回地址sub lr,lr,#4@ 3.2 保存上下文(寄存器内容)到IRQ模式的栈空间stmfd sp!,{r0-r12,lr}@ 3.3 确保中断嵌套可以多级恢复,保存SPSR_irq寄存器mrs r0,spsrstmfd sp!,{r0}@ 3.4 读取GIC控制器的基地址,该地址保存于CBAR寄存器,CRn=c15,op1=4,CRm=c0,op2=0mrc p15,4,r1,c15,c0,0@ 3.5 获取中断ID,传递到上层方便根据中断ID调用具体的中断处理函数add r1,r1,#0x2000 @CPU端口基地址add r1,r1,#0x000c @IAR寄存器地址ldr r0,[r1]stmfd sp!,{r0,r1} @3.6 IRQ模式默认会禁用新的IRQ中断,而SVC模式允许重新启用IRQ,从而支持中断嵌套cps #0x13 @切换到SVC模式stmfd sp!,{lr} @3.7 执行中断处理函数ldr r2,=System_IRQHandlerblx r2@3.8 中断处理函数执行结束,恢复中断处理前的返回地址ldmfd sp!,{lr}@3.9 返回IRQ模式cps #0x12@3.10 写EOIR寄存器以结束中断ldmfd sp!,{r0,r1}str r0,[r1,#0x10]@3.11 恢复程序状态ldmfd sp!,{r0}msr spsr,r0@3.12 恢复上下文ldmfd sp!,{r0-r12,lr}@3.13 恢复中断未发生时的程序状态并自动恢复CPSR movs pc,lrundefine_instruction:b stop
software_interrupt:b stop
prefetch_abort:b stop
data_abort:b stop
not_used:b stop
fiq:b stop
stop:b stop
.end

 欢迎大家批评指正,博主会持续输出优质内容,谢谢各位观众老爷观看,码字画图不易,希望大家给个一键三连支持~ 你的支持是我创作的不竭动力~

http://www.lryc.cn/news/582048.html

相关文章:

  • iOS App抓包工具排查后台唤醒引发请求异常
  • ShortGPT: Layers in Large Language Models are More Redundant Than You Expect
  • DPDK 网络驱动 之 UIO
  • Linux之Shell脚本--遍历数组
  • PostgreSQL中的HASH分区:原理、实现与最佳实践
  • 多模态数据集转换与MMIB模型应用:从图像到文本的跨模态分析
  • AI PPT探秘
  • Microsoft Visual Studio离线安装(以2022/2019为例)
  • 钉钉企业机器人开发技巧:实现单聊消息发送、状态查询与撤回
  • 如何解决微信小程序出现两个下拉刷新样式?
  • 生成 `compile_commands.json`
  • RESTful风格
  • Java学习——MP3SPI介绍
  • 【BTC】比特币系统的具体实现
  • 【机器学习实战】线性回归分析
  • 【redis相关】
  • QML中的Item
  • TCP 事务全面研究:从原理到优化与故障排除
  • 百度开源文心 4.5 系列开源大模型 GitCode 本地化部署,硅基流动:文心 vs. DeepSeek vs. Qwen 3.0 深度测评
  • 剑指offer第2版:动态规划+记忆化搜索
  • 使用make编译ROS2节点
  • 如果让计算机理解人类语言- Word2Vec(Word to Vector,2013)
  • 利用英译法案例演示RNN中的注意力机制(基于PyTorch)
  • 超越存在性检查:掌握Linux中`ls`命令的终极指南
  • .net core mvc部署到win10本地的Ubuntu上
  • 【Linux | 网络】网络基础
  • 多模式编译器——vim的使用
  • FastMCP:用于构建MCP服务器的开源Python框架
  • UE 材质 变体 概念
  • C++11标准库算法:深入理解std::none_of