中断处理函数中不用disable_irq而用disable_irq_nosync原因【转】

简介:

转自:http://blog.csdn.net/beyondioi/article/details/9201695

今天在写触摸屏驱动时在中断处理函数中使用disable_irq关中断发现在进入中断处理后内核就挂掉了,于是研究了一下才发现disable_irq关闭中断并等待中断处理完后返回, 而disable_irq_nosync立即返回. 在中断处理程序中应该使用disable_irq_nosync来关闭中断

 
先看一下disable_irq_nosync,内核代码中是这样解释的:

/**
*    disable_irq_nosync - disable an irq without waiting
*    @irq: Interrupt to disable
*
*    Disable the selected interrupt line. Disablesand Enables are
*    nested.
*    Unlike disable_irq(),this function doesnot ensure existing
*    instances of the IRQ handler have completed before returning.
*
*    This function may be called from IRQ context.
*/
void disable_irq_nosync(unsigned int irq)
{
    struct irq_desc *desc = irq_to_desc(irq);
    unsigned long flags;

    if (!desc)
        return;

    chip_bus_lock(irq, desc);
    spin_lock_irqsave(&desc->lock, flags);
    __disable_irq(desc, irq, false);
    spin_unlock_irqrestore(&desc->lock, flags);
    chip_bus_sync_unlock(irq, desc);
}

关闭中断后程序返回, 如果在中断处理程序中, 那么会继续将中断处理程序执行完.


/**
* disable_irq - disable an irq and wait for completion
* @irq: Interrupt to disable
*
* Disable the selected interrupt line. Enables and Disables are
* nested.
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
* holding a resource the IRQ handler may need you will deadlock.
*
* This function may be called - with care - from IRQ context.
*/
void disable_irq(unsignedint irq)
{
        struct irq_desc *desc = irq_desc + irq;
        if (irq>= NR_IRQS)
                return;
        disable_irq_nosync(irq);
        if (desc->action)
                synchronize_irq(irq);
}

关闭中断并等待中断处理完后返回.从代码中可以看到, disable_irq先是调用了disable_irq_nosync, 然后检测desc->action是否为1. 在中断处理程序中, action是置1的, 所以进入synchronize_irq函数中.


/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
* @irq: interrupt number to wait for
*
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
* holding a resource the IRQ handler may need you will deadlock.
*
* This function may be called - with care - from IRQ context.
*/
void synchronize_irq(unsignedint irq)
{
struct irq_desc *desc= irq_to_desc(irq);
unsigned int status;
if (!desc)
  return;
do {
  unsigned long flags;
  /*
   * Wait until we're out of the critical section. This might
   * give the wrong answer due to the lack of memory barriers.
   */
  while (desc->status& IRQ_INPROGRESS)
   cpu_relax();
  /* Ok, that indicated we're done: double-check carefully. */
  spin_lock_irqsave(&desc->lock, flags);
  status = desc->status;
  spin_unlock_irqrestore(&desc->lock, flags);
  /* Oops, that failed? */
} while (status & IRQ_INPROGRESS);
/*
  * We made sure that no hardirq handler is running. Now verify
  * that no threaded handlers are active.
  */
wait_event(desc->wait_for_threads,!atomic_read(&desc->threads_active));
}


注释中说明该函数是在等待中断处理程序的结束, 这也是disable_irq与disable_irq_nosync不同的主要所在. 但是在中断处理函数中调用会发生什么情况呢? 进入中断处理函数前IRQ_INPROGRESS会被__setup_irq设置, 所以程序会一直陷在while循环中, 而此时内核以经被独占, 这就导致系统死掉.
 
总结:
由于在disable_irq中会调用synchronize_irq函数等待中断返回, 所以在中断处理程序中不能使用disable_irq, 否则会导致cpu被synchronize_irq独占而发生系统崩溃.

来源:http://blog.csdn.net/skyflying2012/article/details/8265869















本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/5404629.html,如需转载请自行联系原作者

相关文章
|
传感器 开发工具 C语言
EXTI外部中断介绍(内置1.中断系统+2.中断执行流程+3.STM32中断+4.NVIC基本结构+5.NVIC优先级分组+6.EXTI简介+7.EXTI基本结构...)
EXTI外部中断介绍(内置1.中断系统+2.中断执行流程+3.STM32中断+4.NVIC基本结构+5.NVIC优先级分组+6.EXTI简介+7.EXTI基本结构...)
323 0
EXTI外部中断介绍(内置1.中断系统+2.中断执行流程+3.STM32中断+4.NVIC基本结构+5.NVIC优先级分组+6.EXTI简介+7.EXTI基本结构...)
|
3月前
crash命令 —— irq
crash命令 —— irq
|
7月前
看看FIQ和IRQ
看看FIQ和IRQ
127 0
|
7月前
|
芯片
ARM hint instruction-WFI(Wait For Interrupt)指令的一些笔记
ARM hint instruction-WFI(Wait For Interrupt)指令的一些笔记
414 0
|
芯片
stm32-HAL使用stop模式后DMA初始化的问题
stm32-HAL使用stop模式后DMA初始化的问题
276 1
stm32-HAL使用stop模式后DMA初始化的问题