现在的位置: 首页 > 综合 > 正文

重读uclinux-2008r1-rc8(bf561)内核的中断处理(4):特定处理函数

2013年09月13日 ⁄ 综合 ⁄ 共 2268字 ⁄ 字号 评论关闭
 

对于不同中断源的默认处理函数(irq_desc结构体中的handle_irq),内核将之分成了3类。除了PF0-PF47的中断和IRQ_PROG0_INTA、IRQ_PROG1_INTA、IRQ_PROG2_INTA这三个由PF口共享的中断外对于其它的中断源则使用handle_simple_irq进行处理。
handle_simple_irq函数位于kernel/irq/chip.c:
/**
 *   handle_simple_irq - Simple and software-decoded IRQs.
 *   @irq:    the interrupt number
 *   @desc:   the interrupt description structure for this irq
 *
 *   Simple interrupts are either sent from a demultiplexing interrupt
 *   handler or come from hardware, where no interrupt hardware control
 *   is necessary.
 *
 *   Note: The caller is expected to handle the ack, clear, mask and
 *   unmask issues if necessary.
 */
void fastcall
handle_simple_irq(unsigned int irq, struct irq_desc *desc)
{
     struct irqaction *action;
     irqreturn_t action_ret;
     const unsigned int cpu = smp_processor_id();
 
     spin_lock(&desc->lock);
 
     if (unlikely(desc->status & IRQ_INPROGRESS))
         goto out_unlock;
     kstat_cpu(cpu).irqs[irq]++;
 
     action = desc->action;
     if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
         if (desc->chip->mask)
              desc->chip->mask(irq);
         desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
         desc->status |= IRQ_PENDING;
         goto out_unlock;
     }
 
     desc->status &= ~(IRQ_REPLAY | IRQ_WAITING | IRQ_PENDING);
     desc->status |= IRQ_INPROGRESS;
     spin_unlock(&desc->lock);
 
     action_ret = handle_IRQ_event(irq, action);
     if (!noirqdebug)
         note_interrupt(irq, desc, action_ret);
 
     spin_lock(&desc->lock);
     desc->status &= ~IRQ_INPROGRESS;
out_unlock:
     spin_unlock(&desc->lock);
}
从这个函数的代码可以看出,这个函数的作用就是调用handle_IRQ_event,并更新desc中的状态。在中断初始化完成的时候,除了EVT_TMR之外,其它的中断源的action都为NULL,因此对大部分中断源造成的中断此函数将直接返回。
下面看看handle_IRQ_event的实现:
/**
 * handle_IRQ_event - irq action chain handler
 * @irq: the interrupt number
 * @action:   the interrupt action chain for this irq
 *
 * Handles the action chain of an irq event
 */
irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{
     irqreturn_t ret, retval = IRQ_NONE;
     unsigned int status = 0;
 
     handle_dynamic_tick(action);
 
     if (!(action->flags & IRQF_DISABLED))
         local_irq_enable_in_hardirq();
 
     do {
         ret = action->handler(irq, action->dev_id);
         if (ret == IRQ_HANDLED)
              status |= action->flags;
         retval |= ret;
         action = action->next;
     } while (action);
 
     local_irq_disable();
 
     return retval;
}
很简单,就是按顺序调用action链表中的处理函数。
 
 
 

抱歉!评论已关闭.