微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > arm linux 下中断流程简要分析中断处理流程

arm linux 下中断流程简要分析中断处理流程

时间:11-09 来源:互联网 点击:

_exit();

}

该函数的调用desc_handle_irq()来继续处理中断。

include/asm-arm/mach/Irq.h:

/*

* Obsolete inline function for calling irq descriptor handlers.

*/

static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc,

struct pt_regs *regs)

{

desc->handle_irq(irq, desc, regs);

}

调用中断描述符的handler_irq函数来处理该中断,对于IRQ_WDT就是do_edge_IRQ(前面分析过)。

include/asm-arm/mach/Irq.h:

#define do_edge_IRQhandle_edge_irq

kernel/irq/Chip.c:

/

*handle_edge_irq - edge type IRQ handler

*@irq:the interrupt number

*@desc:the interrupt description structure for this irq

*@regs:pointer to a register structure

*

*Interrupt occures on the falling and/or rising edge of a hardware

*signal. The occurence is latched into the irq controller hardware

*and must be acked in order to be reenabled. After the ack another

*interrupt can happen on the same source even before the first one

*is handled by the assosiacted event handler. If this happens it

*might be necessary to disable (mask) the interrupt depending on the

*controller hardware. This requires to reenable the interrupt inside

*of the loop which handles the interrupts which have arrived while

*the handler was running. If all pending interrupts are handled, the

*loop is left.

*/

void fastcall

handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)

{

const unsigned int cpu = smp_processor_id();

spin_lock(&desc->lock);

desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);

/*

* If were currently running this IRQ, or its disabled,

* we shouldnt process the IRQ. Mark it pending, handle

* the necessary masking and go out

*/

/*

*如果该中断正在处理或者该中断被disable掉了的话,就不处理该中断,并清掉pending

*寄存器里的相应位

*/

if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||

!desc->action)) {

desc->status |= (IRQ_PENDING | IRQ_MASKED);

mask_ack_irq(desc, irq);/*mask该中断,清pending标志位*/

goto out_unlock;

}

kstat_cpu(cpu).irqs[irq]++;/*统计中断数量*/

/* Start handling the irq */

/*开始处理中断,先清掉pending标志位*/

desc->chip->ack(irq);

/* Mark the IRQ currently in progress.*/

desc->status |= IRQ_INPROGRESS;/*标上正在处理的标记*/

do {

struct irqaction *action = desc->action;/*获取该中断的action*/

irqreturn_t action_ret;

if (unlikely(!action)) {

desc->chip->mask(irq)/*如果没有注册action,则mask该中断*/;

goto out_unlock;

}

/*

* When another irq arrived while we were handling

* one, we could have masked the irq.

* Renable it, if it was not disabled in meantime.

*/

/*

*如果以前被mask掉的话,在这里把它打开

*/

if (unlikely((desc->status &

(IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==

(IRQ_PENDING | IRQ_MASKED))) {

desc->chip->unmask(irq); /*unmask该中断*/

desc->status &= ~IRQ_MASKED;

}

desc->status &= ~IRQ_PENDING;

spin_unlock(&desc->lock);

action_ret = handle_IRQ_event(irq, regs, action);/*处理中断事件*/

if (!noirqdebug)

note_interrupt(irq, desc, action_ret, regs);

spin_lock(&desc->lock);

/*如果有IRQ_PENDING状态,则说明又有中断产生过,则继续执行*/

} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);

desc->status &= ~IRQ_INPROGRESS;

out_unlock:

spin_unlock(&desc->lock);

}

该函数的大体功能都在函数体内解释出来了,这里我们对调用的每个函数在进行分析。

先看mask_ack_irq

kernel/irq/Chip.c:

static inline void mask_ack_irq(struct irq_desc *desc, int irq)

{

if (desc->chip->mask_ack)/*对于IRQ_WDT, 该函数没定义*/

desc->chip->mask_ack(irq);

else {

desc->chip->mask(irq); /*对于IRQ_WDT,该函数就是s3c_irq_mask*/

desc->chip->ack(irq);/*对于IRQ_WDT,该函数就是s3c_irq_ack*/

}

}

可以看到它调用具体平台相关的mask函数来处理该中断。

我们来看s3c_irq_mask

arch/arm/mach-s3c2410/Irq.c:

static void

s3c_irq_mask(unsigned int irqno)

{

unsigned long mask;

irqno -= IRQ_EINT0;

mask =

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top