Linux中断处理流程

一、 中断系统硬件架构:

ARM cortex-A9,A15上的中断控制器为GIC400(低版本有GIC390,PL190等),硬件的逻辑图为




EXTINT0-EXTINT2:分别设置EINT0—EINT7、EINT8—EINT15、EINT16—EINT23的触发方式(高电平触发、低电平触发、下降沿触发、上升沿触发)。

EINTPEND:这个是中断挂起寄存器,清除时要写1,后面还有几个是写1清除。当一个外部中断(EINT4-EINT23)发生后,那么相应的位会被置1。为什么没有EINT0-EINT3,因为它们分别由SRCPND寄存器的后4位控制。

EINTMASK:这个简单,是屏蔽中断用的,也就是说位为1时,此次中断无效。

内部中断有8个寄存器:

SUBSRCPND:当一个中断发生后,那么相应的位会被置1,表示一个中断发生了。

INTSUBMSK:与上一个是一伙的,中断屏蔽寄存器。

SRCPND:当一个中断发生后,那么相应的位会被置1,表示一个或一类中断发生了。

INTMSK:用来屏蔽SRCPND寄存器所标识的中断。但只能屏蔽IRQ中断,不能屏蔽FIQ中断。

INTMOD:当INTMOD中某位被设置为1时,它对应的中断被设为FIQ,CPU将进入快速中断模式。

PRIORITY:用于设置IRQ中断的优先级。

INTPND:中断优先级仲裁器选出优先级最高中断后,这个中断在INTPND寄存器中的相应位被置1,随后,CPU进入中断模式处理它。同一时间内,此寄存器只有一位被置1。

INTOFFSET:用来表示INTPND寄存器中哪位被置1了,即记录INTPND中位[x]为1的位x的值。清除INTPND、SRCPND时自动清除。

以上寄存器描述摘自论坛帖子,源作者不详。


二、中断系统软件抽象架构

1)下图为Linux内核中断系统相关数据结构的关系图, 在《深入linux内核架构》中将中断系统分为三个层次:

High-level Interrupt Service routine:设备驱动的中断处理程序,对应图中的irqacton。

Interrupt Flow Handling:中断流程控制(原书翻译为中断电流控制,我认为不准,虽然该部分和信号源状态有关,例如边沿触发的中断或者电平触发的中断,但它主要负责仍是:何时调用硬件操作的mask、ack等流程上的控制)。

Chip-Level hardware Encapsulation:硬件设备层,mask、ack等中断系统硬件寄存器的操作,对应到图中的irq_chip。


ARM Linux中断机制之中断的初始化 - 尘 - 学习点滴


2)irq_desc:是一个全局数组,每个中断源对应一个descriptor。


3)handle_irq:它为每个不同类型中断源的处理函数入口,调用路径为:asm_do_IRQ->handle_irq->generic_handle_irq->generic_handle_irq_desc-> handle_irq。不同类型中断源使用不同的处理方式,在该中断子系统初始化时使用函数irq_set_handler进行设置或直接给函数指针赋值。

irq_chip:它替代了老版本hw_interrupt_type,该结构体内的函数集为对应中断源硬件操作的mask、unmask、应答ack、mask_ack等,在该中断子系统初始化时使用函数irq_set_chip进行设置。

handle_level_irq处理电平信号触发的中断源类型,该函数会调用chip的irq_mask、irq_ack来mask并ack(告诉中断控制器,已经有人响应该中断了,可以继续产生下一个新中断了)这个中断信号源,否则该中断会被重复处理;

handle_egde_irq处理边沿信号触发的中断源类型,只ack就可以,不需要mask,下一个新的该类型中断可以pending到SRCPEND寄存器

对于多核 CPU,如果其他核正在处理该中断,可以通过函数irqd_irq_inprogress检测 irq_desc ->irq_data->state_use_accessors状态是否为IRQD_IRQ_INPROGRESS来识别。

handle_irq(=handle_level_irq or handle_egde_irq or ...)会通过handle_irq_event->handle_irq_event_percpu(2.6版本为handle_IRQ_event)调用真正的设备中断处理函数action->handler。


4)irqaction:它对应具体设备的中断描述,handler为具体isr中断服务函数,dev_id用来区别共享中断中的不同设备,next指针指向同一个中断源(共享中断)下一个设备的irqaction,当中断发生,共享中断的设备isr都将被调用,因此各个设备的isr内要有能力判断该中断是不是本设备发出的。关于共享中断《Linux设备驱动》的一段话:“无论何时 2 个或多个驱动在共享中断线, 并且硬件中断在这条线上中断处理器, 内核为这个中断调用每个注册的处理者, 传递它的 dev_id 给每个. 因此, 一个共享的处理者必须能够识别它自己的中断并且应当快速退出当它自己的设备没有被中断时.”我认为这个说法是错误的,首先中断信号只是io上的一个电信号,不可能传递dev_id信息给cpu,那么内核也不知道是哪个设备发出的中断信号;再者如果真的有了已知的dev_id,也就不需要调用所有的共享中断的isr了。

因此,要每个设备的isr来判断该中断是不是自己发出的,需要硬件支持,比如通过简单的check一个设备的标志寄存器来完成,不是本设备的,立刻退出中断。

另外,在处理共享中断时不能单独在某个设备内进行disable、enable irq的动作,这样会影响其他共享中断的设备。


三、中断的软件处理流程






文章中的图片均来自《深入linux内核架构》一书。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值