3 years, 7 months ago.

How do I re-enable a pin interrupt at the end of an ISR?

OK, I have read countless discussions of how to use a statement such as: InterruptIn IRQ_pin(p12); to let a pin on an mbed module accept a logic-level change that causes the MCU to jump to the interrupt-service routine (ISR). That works fine as shown in the snippet below:

void RB0ISR()
{    
    IRQ_led = 1;     //Turn on LED4 on mbed board      
}
 
main()
{
    IRQ_pin.mode(PullUp);              //Set pullup on pin 12
    IRQ_pin.fall(&RB0ISR);               //Set the IRQ_pin to detect a falling edge of pulse
    IRQ_led = 0;                                 //Turn off LED4 on mbed board

     while(1)
     {
        myled = 1;                       //LED-blink code to show program working
        wait(0.1);
        myled = 0;
        wait(0.1);
      }
}

Grounding pin 12 causes LED4 to turn on. So far, so good. I understand from other questions and comments that the statement IRQ_pin.fall(NULL); will disable the pin-12 interrupt. In a real ISR I must turn off the interrupt input so no other interrupt signal at pin-12 cause an interrupt during the ISR. Then at the end of the ISR I must re-enable the interrupt sensing at pin 12. First, how do I do that? And second, suppose the input at pin 12 remains a logic 0, when the pin-12 interrupt gets re-enabled will it detect this logic-0 state as another interrupt or will the pin-12 interrupt ONLY detect another falling edge? Thanks for your help understanding interrupts.

1 Answer

3 years, 7 months ago.

In general there are two types of interrupt, edge triggered and level triggered. As the names imply edge triggered require a change in the input signal, level triggered only require the signal be at the correct logic level.

Level triggered interrupts would re-trigger as you are worried about and for this reason are avoided whenever possible. While some of the supported hardware platforms may offer level triggered interrupts the mbed library only supports edge triggered interrupts. Unless you start messing around with the underlying CPU registers it's safe to assume that an edge will be required in order to generate an interrupt.

For your other concerns the answer is that you don't need to worry about it, the arm interrupt controller handles all of this.

Each interrupt has a priority level. If during an ISR a higher priority interrupt arrives then the system will jump to that, handle it and then return to the lower priority ISR it was in the middle of. If an interrupt with the same or lower priority arrives then it will be queued up and be triggered once the current ISR is finished.

You can disable interrupts and re-enable them with the commands

__disable_irq(); 
[your code]
__enable_irq();

but it would be very odd to need that during an ISR, normally you could solve any potential issues by setting the priorities.

In mbed the default is that all interrupts are the same priority, unless you change things ISRs will never interrupt each other.

The interrupt flag in the CPU is automatically cleared which will re-enable the interrupt so your code above will trigger on all falling edges not just the first one. If you only want to trigger on the first edge then you need to include IRQ_pin.fall(NULL); in the ISR.

There are a couple of possible oddities. What happens if you get a second falling edge while in the ISR for the falling edge. I'm not sure if the interrupt will get called a second time or not, it depends upon when the interrupt flag is cleared by the library, whether it's on entry or on exit of user ISR. That could even be platform specific, I have no idea. If critical it should be easy to test by creating an ISR with a long wait in it. There is a short delay jumping to an ISR, In theory a very short pulse could cause the interrupt to trigger and the the pin could go high again before the ISR has a chance to do anything. This could cause some odd results if the ISR then checked the state of the pin.

These are both highly unlikely situations unless the system is busy handling a lot of other ISRs but in theory they are possible.

If you look at a serial port ISR it will often include a while loop checking whether there is any data ready to read, this is to catch the situation where a second byte arrives while the first byte is being processed. Even if the interrupt would have been called a second time it's more efficient to handle it all at once.