【中断问题】根据Linux内核的中断处理机制,设计CC2541的中断保护机制

目的需求:

为了防止中断的重入,有时候需要对中断处理过程加以保护。

1、Linux中的中断处理机制

为了保护系统执行,防止被其他中断打断,需要在必要的代码段暂时关闭中断,linux关闭中断分为两种方式

a、disable_irq_nosync

 关闭中断,函数立刻返回,不存在堵塞问题,一般用在中断处理过程中,防止被其他高优先级中断打断

 内核代码:

 /**
  *    disable_irq_nosync - disable an irq without waiting
  *    @irq: Interrupt to disable
  *
  *    Disable the selected interrupt line. Disables and Enables are
  *    nested.
  *    Unlike disable_irq(), this function does not 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);
 }

b、disable_irq

 关闭中断并等待正在执行的中断处理完后才返回,一般用于保护非中断代码,防止过程被中断打断

 /**
  * 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(unsigned int 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(unsigned int 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不同的主要所在. 

 如果在中断处理函数中调用disable_irq,进入中断处理函数前IRQ_INPROGRESS会被__setup_irq设置, 所以程序会陷入死锁中,一直陷在while循环, 而此时内核以经被独占, 会导致系统死掉

2、设计CC2541中断处理机制

a、进入中断后暂时关闭中断

  很多单片机在处理按键程序时会使用这种方式,原则上不会与太大问题。

  #define HAL_ENTER_CRITICAL_SECTION(x)   st( x = EA;  HAL_DISABLE_INTERRUPTS(); )
  #define HAL_EXIT_CRITICAL_SECTION(x)    st( EA = x; )

b、问题点

 由于编译指令的问题,可能会导致响应速度变慢

  /* IAR library uses XCH instruction with EA. It may cause the higher priority interrupt to be
  * locked out, therefore, may increase interrupt latency.  It may also create a lockup condition.
  * This workaround should only be used with 8051 using IAR compiler. When IAR fixes this by
  * removing XCH usage in its library, compile the following macros to null to disable them.
  */
  #define HAL_ENABLE_INTERRUPTS()         st( EA = 1; )
  #define HAL_ENTER_ISR()                 { halIntState_t _isrIntState = EA; HAL_ENABLE_INTERRUPTS();
  #define HAL_EXIT_ISR()                  EA = _isrIntState; }

猜你喜欢

转载自blog.csdn.net/liwei16611/article/details/78458178