3
votes

Our group is using a custom driver to interface four MAX3107 UARTs on a shared I2C bus. The interrupts of the four MAX3107's are connected (i.e. shared interrupt via logic or'ing)) to a GPIO pin on the ARM9 processor (LPC3180 module). When one or more of these devices interrupt, they pull the GPIO line, which is configured as a level-sensitive interrupt, low. My question concerns the need, or not, to disable the specific interrupt line in the handler code. (I should add that we are running Linux 2.6.10).

Based on my reading of several ARM-specific app notes on interrupts, it seems that when the ARM processor receives an interrupt, it automatically disables (masks?) the corresponding interrupt line (in our case this would seem to be the line corresponding to the GPIO pin we selected). If this is true, then it seems that we should not have to disable interrupts for this GPIO pin in our interrupt handler code as doing so would seem redundant (though it seems to work okay). Stated differently, it seems to me that if the ARM processor automatically disables the GPIO interrupt upon an interrupt occurring, then if anything, our interrupt handler code should only have to re-enable the interrupt once the device is serviced.

The interrupt handler code that we are using includes disable_irq_nosync(irqno); at the very beginning of the handler and a corresponding enable_irq() at the end of the handler. If the ARM processor has already disabled the interrupt line (in hardware), what is the effect of these calls (i.e. a call to disable_irq_nosync() followed by a call to enable(irq())?

1
I have never found myself explicitly re-enabling interrupts on a GPIO source in the past when I've used them - the kernel's primary interrupt handler should be taking care of clearing and re-enabling the source on the interrupt controller so that there is no danger of getting an interrupt whilst still processing the first. The only thing I can think of is that the handler was written to be attached to multiple lines at once. I don't think you should need any of these calls.marko

1 Answers

6
votes

From the Arm Information Center Documentation:

On entry to an exception (interrupt):

  • interrupt requests (IRQs) are disabled for all exceptions

  • fast interrupt requests (FIQs) are disabled for FIQ and Reset exceptions.

It then goes on to say:

Handling an FIQ causes IRQs and subsequent FIQs to be disabled, preventing them from being handled until after the FIQ handler enables them. This is usually done by restoring the CPSR from the SPSR at the end of the handler.

So you do not have to worry about disabling them, but you do have to worry about re-enabling them.

You will need to include enable_irq() at the end of your routine, but you shouldn't need to disable anything at the beginning. I wouldn't think that calling disable_irq_nosync(irqno) in software after it has been called in hardware would effect anything. Since the hardware call is most definitely called before the software call has a chance to take over. But it's probably better to remove it from the code to follow convention and not confuse the next programmer who takes a look at it.

More info here:

Arm Information Center