edge中断分析

目前正在调试msix中断,在测试过程中发现会概率性的丢失中断。Msix中断默认是edge触发的中断,edge触发的中断是在中断对应pin发生电平信号跳变的时候,会发出一个中断请求。因为跳变是一瞬间的,不会像level触发中断那样一直保持电平不变,这样就可能会漏掉某一个跳变的瞬间,表现就是丢失了一个中断。

内核中处理edge触发中断的函数为handle_edge_irq,此函数有do_IRQ函数调用而来。


void handle_edge_irq(unsigned int irq, struct irq_desc *desc)

{

raw_spin_lock(&desc->lock);

/*因为接收到中断,所以清除下面两个标志*/

desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);

/*IRQ是否被禁止,或者正在处理中,或者没有挂接中断处理函数*/

if (unlikely(irqd_irq_disabled(&desc->irq_data) ||

irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {

if (!irq_check_poll(desc)) {

desc->istate |= IRQS_PENDING;  /*设置irq处于挂起状态*/

mask_ack_irq(desc);  /*向硬件发ACK,屏蔽中断*/

goto  out_unlock;

}

}

kstat_incr_irqs_this_cpu(irq, desc); /*process/interrupts中对应irq计算加1*/

/*cpu对此IRQ的回应,表示准备接收此IRQ的下一个中断*/

desc->irq_data.chip->irq_ack(&desc->irq_data);

do {

if (unlikely(!desc->action)) { /*没有挂接中断处理函数*/

mask_irq(desc);    /*屏蔽IRQ*/

goto  out_unlock;

}

/*IRQ处于中断挂起状态*/

if (unlikely(desc->istate & IRQS_PENDING)) {

if (!irqd_irq_disabled(&desc->irq_data) &&

irqd_irq_masked(&desc->irq_data))

unmask_irq(desc);

}

/*处理中断*/

handle_irq_event(desc);

}  while ((desc->istate & IRQS_PENDING) &&    /*有挂起的中断需要处理*/

!irqd_irq_disabled(&desc->irq_data));   /*irq没有禁止*/

istate成员刚开始在irq_desc结构体中没找到,其实它的定义如下

#define istate core_internal_state__do_not_mess_with_it

istate对应的是core_internal_state__do_not_mess_with_it成员。

IRQS_REPLAY标志是用来挽救丢失的中断。此标志在check_irq_resend函数中设置,通过中断控制器APIC上的中断信号重新向cpu发中断,而不是通过外设硬件来重发中断。这里进入到了handle_edge_irq函数表示已经收到了中断,不需要重发,所以清除此标志。

IRQS_WAITING标志表示中断的到来,这里收到了中断,因此也清除此标志。此标志在handle_xxx_irq函数的开始都会清除掉。

如果<1>当前irq被禁止,<2>当前irq正在处理中,<3>当前irq没有挂接处理函数,则我们不处理接收到的此IRQ。如果满足上面的条件,我们就设置此IRQ为IRQS_PENDING挂起状态,并屏蔽中断,然后返回。放弃中断的处理过程,留给正在处理此IRQ中断的cpu来处理此次pending的中断。

irq_ack函数的底层实现是写eoi寄存器,是cpu对此IRQ的回应,表示irq希望清除此IRQ的pending状态(用于清除APIC IRR的pending位),准备接收下一个中断。这样其他的cpu就可以接收此IRQ进行处理了。

程序接下来是一个while循环,循环的条件是此IRQ没有被禁止并且有pending的待处理的中断。因为在处理中断的过程中,因为ack了,可能其他的cpu又接收到了此IRQ新的中断。

如果此IRQ没有挂接中断处理函数,就直接屏蔽此IRQ,返回。

如果irq处于IRQS_PENDING状态,中断没有被禁止但是被屏蔽的情况下,调用unmask_irq取消屏蔽。想想为什么会处于IRQS_PENDING状态,并这样处理?前面讲到当此IRQ正在处理中,新接收到的中断,就会设置IRQS_PENDING状态,并屏蔽此IRQ。

Edge触发方式的中断容易丢中断,因此在处理中断时候不能长时间的屏蔽IRQ。在handle_edge_irq函数一上来就判断在irq没用被禁止,没用正在处理的情况下,只是ack回应了硬件,没用屏蔽irq,表示另外的cpu可以接收此IRQ的中断。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-28 19:02:41

edge中断分析的相关文章

中断分析

MINIX3 中断机制源码分析 下面我们来探讨下 MINIX 中断处理函数的具体处理流程: 由前面的章节知道,MINIX 的架构是标准的微内核结构,除了时钟中断处理程 序可以直接在内核态进行,其他的都只能从用户态,用户态像内核态发送消息. 假设我们是一个内核设计者,怎么能够将这种机制实现呢?我们会在系统任务里 设置一个中断注册调用,通过那个调用,我们能够将用户需要的中断处理函数挂 15 到相应的地方并且以后能够被用户识别. 现在继续往下面分析:我们现在又 16 根通用的中断地址,但是这是不够的,

LINUX-内核-中断分析-中断向量表(3)-arm【转】

转自:http://blog.csdn.net/haolianglh/article/details/51986987 arm中断概念 在<ARM体系结构与编程>第9章中说到,ARM 中有个概念叫做“异常中断”,也就是包括外部中断在内的各种异常.显然,ARM体系的“异常中断”概念更加接近MIPS体系中的“异常”概念. 既然更类似MIPS体系,那么自然的ARM体系就存在“异常中断入口”和“异常中断向量表”的概念. arm的异常中断向量表 非向量化中断 ARM体系定义了7种异常中断,在<AR

逻辑中断分析

一.逻辑与&& 使用格式:条件A&&条件B 运算过程: 先判断条件A是否成立 如果条件A成立,则接着再判断条件B是否成立,如果条件B成立"条件A&&条件B"的结果为1即真,如果条件B不成立,结果为0,即为假 如果条件A不成立,就不会去判断条件B是否成立,因为条件A已经不成立了,不管条件B是否成立,"条件A&&条件B"的结果肯定是0,也就是假 这样就执行不了条件B,提高了运行的性能 例如: /Volume

非常好!!!Linux源代码阅读——中断【转】

Linux源代码阅读——中断 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/2_int.html 目录 为什么要有中断 中断的作用 中断的处理原则 Linux 中断机制 中断控制器 中断描述符 中断数据结构 中断的初始化 内核接口 中断处理过程 CPU 的中断处理流程 保存中断信息 处理中断 从中断中返回 编写中断处理程序 软中断.tasklet与工作队列 上半部与下半部 软中断 tasklet 工作队列 1 为什么要有中断 1.1 中

Java Core和HeapDump

什么是Java Core和Heap Dump Java程序运行时,有时会产生Java Core及Heap Dump文件,它一般发生于Java程序遇到致命问题的情况下. 发生致命问题后,Java进程有时可以继续运行,但有时会挂掉. 为了能够保留Java应用发生致命错误前的运行状态,JVM在死掉前产生两个文件,分别为JavaCore及HeapDump文件. JavaCore和Heap Dump的区别 l JavaCore是关于CPU的 JavaCore文件主要保存的是Java应用各线程在某一时刻的运

5.Longest Palindromic Substring (String; DP)

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 思路:KMP,一种字符串匹配方法. 首先在字符串的每个字符间加上#号.For example: S = “abaaba”, T = “#a#b#a#a

ucosii任务切换OS_TASK_SW()

stm32F103中任务切换定义 1 //任务切换宏,由汇编实现. 2 #define OS_TASK_SW() OSCtxSw() os_cpu_a.asm中任务切换函数的定义 1 NVIC_INT_CTRL EQU 0xE000ED04 ; 中断控制寄存器 2 NVIC_SYSPRI2 EQU 0xE000ED20 ; 系统优先级寄存器(2) 3 NVIC_PENDSV_PRI EQU 0xFFFF0000 ; PendSV中断和系统节拍中断 4 ; (都为最低,0xff). 5 NVIC_

TensorFlow的图切割模块——Graph Partitioner

背景 [作者:DeepLearningStack,阿里巴巴算法工程师] 在经过TensorFlow的Placer策略模块调整之后,下一步就是根据Placement信息对Graph做切割,然后分发到不同的Device上去执行的过程了.在对Graph做切割时,为了保证跨Device执行的逻辑与切割前一致并保证原图中Node节点之间的依赖关系不受到破坏,不但需要插入Send.Recv通信节点对,还需要维护相对复杂的Control Edge.这些功能被设计在了TensorFlow的Graph Parti

6.分析request_irq和free_irq函数如何注册注销中断

上一节讲了如何实现运行中断,这些都是系统给做好的,当我们想自己写个中断处理程序,去执行自己的代码,就需要写irq_desc->action->handler,然后通过request_irq()来向内核申请注册中断 本节目标:      分析request_irq()如何申请注册中断,free_irq()如何注销中断 1.request_irq()位于kernel/irq/ manage .c,函数原型如下: int request_irq(unsigned int irq, irq_handl