Linux驱动学习day22(interrupt子系统)
一、中断和异常的概念
中断属于一种异常。
二、ARM对异常(中断)的处理流程
1、初始化中断:a. 设置中断源,让它可以产生中断。b. 设置中断控制器(屏蔽、优先级)。c. 设置CPU总开关(使能中断)。
2、执行程序。
3、产生中断(按下按键-->中断控制器-->cpu,cpu每执行完一段指令都会检查有无异常产生-->有异常开始处理,对于不同的异常cpu会跳去不同的地址执行程序(这些地址上只是一条跳转指令,跳去执行其他指令)(这些地址是一块的,叫做异常向量))
3、 跳转到的函数处理中断:保存现场(各种寄存器),分辨中断,处理异常(中断),恢复现场。
2.1 中断处理流程图
2.2 进程、线程、中断的核心是栈
ARM芯片属于精简指令集计算机(RISC:ReducedInstructionSetComputing),它所用的指令比较简单,有如下特点:
①对内存只有读、写指令
②对于数据的运算是在CPU内部实现
③使用RISC指令的CPU复杂度小一点,易于设计
很多内容与之前的(博客重复了,Linux驱动学习day9(异常与中断处理)-CSDN博客),这里不再赘述。只记录新内容。
2.3 设备树中使用中断号
2.4 设备树中指定中断控制器
三、GIC介绍分析
ARM体系结构定义了通用中断控制器(GIC),该控制器包括一组用于管理单核或多核系统中的中断的硬件资源。GIC提供了内存映射寄存器,可用于管理中断源和行为,以及(在多核系统中)用于将中断路由到各个CPU核。它使软件能够屏蔽,启用和禁用来自各个中断源的中断,以(在硬件中)对各个中断源进行优先级排序和生成软件触发中断。它还提供对TrustZone安全性扩展的支持。GIC接受系统级别中断的产生,并可以发信号通知给它所连接的每个内核,从而有可能导致IRQ或FIQ异常发生。
3.1 GIC主要功能和模块
distributor(分发器):各种中断发送到GIC中,由 distributor判断优先级最高的中断发送到CPU interface中再发给CPU。CPU之间的通信也要经过该模块,CPU0发出SGI(软件产生的中断)信号,由GIC发送给另一个CPU。
GIC可以处理多种中断,比如PPI各个GPU自己私有的外部设备中断,SGI软件产生的中断(用于CPU之间的通信),SPI共享外部设备发出的中断(可以到达任意CPU)。GIC给每个中断分配了各个中断号,SPI范围是32-1019等等。
3.2 中断的状态
① 非活动状态(Inactive)-这意味着该中断未触发。
② 挂起(Pending)-这意味着中断源已被触发,但正在等待CPU核处理。待处理的中断要通过转发到CPU接口单元,然后再由CPU接口单元转发到内核。
③ 活动(Active)-描述了一个已被内核接收并正在处理的中断。
④ 活动和挂起(Active and pending)-描述了一种情况,其中CPU核正在为中断服务,而GIC又收到来自同一源的中断。
中断的优先级和可接收中断的核都在分发器(distributor)中配置。外设发给分发器的中断将标记为pending状态(或ActiveandPending状态,如触发时果状态是active)。distributor确定可以传递给CPU核的优先级最高的pending中断,并将其转发给内核的CPU interface。通过CPUinterface,该中断又向CPU核发出信号,此时CPU核将触发FIQ或IRQ异常。
作为响应,CPU核执行异常处理程序。异常处理程序必须从CPUinterface寄存器查询中断ID,并开始为中断源提供服务。完成后,处理程序必须写入CPUinterface寄存器以报告处理结束。然后CPUinterface准备转发distributor发给它的下一个中断。在处理中断时,中断的状态开始pending,active,结束时变成inactive。中断状态保存在distributor寄存器中。
3.3 中断发生和处理过程
3.4 异常向量表初始化和映射
3.5 GIC驱动程序对中断的处理流程
3.5.1 老版本内核
3.5.2 新版本内核
3.5.2.1 一级中断处理流程
在新版本内核中,不像老的版本内核,对于虚拟中断号是用到时分配,比如说GIC32硬件中断号上挂了一个UART模块,当uart产生中断,会去寻找没有使用的irq_desc,如下图所示16号是空的,所以16号irq被注册成uart中断,建立hwirq和virirq的映射关系(32 , 16)保存到GIC 中的irq_domain中。当32号产生中断由GIC发送给CPU,CPU会来读GIC的寄存器确定是哪一个中断号产生的中断,读寄存器发现是32号产生的中断于是去irq_domain找到映射关系找到irq_desc虚拟中断号的结构体,调用GIC_handle函数屏蔽其他中断,调用该函数提供的中断处理函数,之后清除中断。
3.5.2.2 二级中断处理流程
当在33号硬件中断下挂有GPIO模块,系统会在irq_desc数组中找到空的irq_desc存放这个GPIO中断的结构体,并将虚拟中断号和硬件中断号的联系放入GIC irq_domain中,由于GPIO模块中含有4个引脚,因此也会为4个引脚设置vir中断号,并记录在GPIO irq_domain(GPIO模块也是一个中断控制器)中。
按键2产生了中断,会有GPIO发送给GIC然后GIC发送给CPU,CPU跳到异常向量表中的irq指令,去读取GIC的寄存器,发现是33号硬件中断,找到domain中虚拟中断和硬件中断的关系,发现是17号虚拟中断,于是执行17号irq_desc中的handle函数,该函数去屏蔽33号硬件中断,读取GPIO控制器中的寄存器,发现是2号硬件中断,从 GPIO irq_domain找到其虚拟中断号,调用102个irq_disc函数中的handle函数(屏蔽中断,执行funckey函数,清除中断),最后清除中断。
四、GIC中的重要数据结构
GIC的功能主要是:可以使能、屏蔽中断,发生中断时可以从GIC里判断是哪个中断。
在内核中使用gic_chip_data结构体表示GIC。
借助下面这张图来理解结构体里面的内容:
a、当发生UART中断的时候,GIC发送中断给CPU,CPU跳到异常向量表中的跳转指令去使用handle函数来读取GIC寄存器,该函数由GIC提供。
b、知道是32号硬件中断产生的中断,会从GIC_domain中取出硬件中断和虚拟中断号的关系,得到虚拟中断号。该结构体也由GIC提供。
c、从GIC_domain得到关系之后,可以去到相应的虚拟中断号的irq_desc结构体中执行handle函数屏蔽中断,调用中断处理函数irqaction(用户提供),清理中断。handle函数由GIC提供,并且屏蔽中断和清理中断的函数在irq_data中的irq_chip中,也由GIC提供。
先更新到这,后天继续加油!