arm linux 下中断流程简要分析中断处理流程
_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 =
armlinux中断处 相关文章:
- ARM linux的中断处理过程(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)