This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432 GPIO Interrupt priority problem



Hi,

i declared two GPIOs to handle interrupt:

MAP_GPIO_setAsInputPin(GPIO_PORT_P4, GPIO_PIN1);
MAP_GPIO_setAsInputPin(GPIO_PORT_P5, GPIO_PIN1);

MAP_GPIO_clearInterruptFlag(GPIO_PORT_P4, GPIO_PIN1);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN1);

MAP_GPIO_enableInterrupt(GPIO_PORT_P4, GPIO_PIN1);
MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN1);

MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P4, GPIO_PIN1,GPIO_HIGH_TO_LOW_TRANSITION);
MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P5, GPIO_PIN1,GPIO_HIGH_TO_LOW_TRANSITION);

MAP_Interrupt_setPriority(INT_PORT4, 0x20);
MAP_Interrupt_setPriority(INT_PORT5, 0x40);
MAP_Interrupt_enableInterrupt(INT_PORT4);
MAP_Interrupt_enableInterrupt(INT_PORT5);

The problem i am facing is that when the Interrupt occurs at the same time the lower priority one is no been handled.

When the lower priority interrupt  is not handled, the slave device stops to opperate and no interrupt is send out. 

Do i have to implement something else on my code? Does the nested vectored interrupt handles multiple interrupt automatically?

  • From your description, it sounds as though one (or both) of your ISRs blocks. If so, this is the fundamental flaw. An ISR should do what it has to do and get out. Long-running/blocking operations should happen in main(), with interrupts enabled.

    Nesting interrupts (between same/lower priority ISRs) is not particularly difficult to accomplish, but generally difficult to get right.

    If there are truly interactions between your two ISRs, it is (or at least used to be) possible to use the same ISR for both interrupts ("#pragma vector=PORT4_VECTOR,PORT5_VECTOR" or some such). In the ISR you can check the IFG bits in whatever order you choose.

  • Hi Bruce,

    on the interrupr service routine the mcu only set a flag and leaves it.
    Everything else will be doing on main.
    I thought that nested interrupt does automatically and choose the one with higher priority first and than handles the one with lower.
    I didnt think i have to deal with it.

    I went and tryied first to set both on the same Port, say GPIO_PORT_5 for example and GPIO_PIN0 was one and GPIO_PIN1 was the other.
    On the ISR i have asked if it was PIN0 and then after PIN1. But it handled only PIN0 and not PIN1.
    PIN 0 in this case has higher priority as PIN 1, i have read this somewhere on the user guide.
    So here i have the same issue.

    Michael
  • on the interrupr service routine the mcu only set a flag and leaves it.

    It would probably be helpful to post some of this code here - if possible.

    And second, there exists an errata for Cortex M4 cores, which TI inherits from ARM. The clearing of an interrupt flag should not be the very last instruction of the interrupt routine. Due to the pipelined architecture, the reset of the flag may take effect only after the return from interrupt. In turn, that causes an immediately interrupt reentry. Check out ARM's infocenter website for details and documents.

  • Here is my code for the ISR:

    void gpio_4_interrupt(void)
    {
    uint_fast16_t status = GPIO_getEnabledInterruptStatus(GPIO_PORT_P4);
    GPIO_clearInterruptFlag(GPIO_PORT_P4, status);

    if(status & GPIO_PIN0)
    {
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN0);
    Set_Flag_R = 1;
    }
    }

    void gpio_5_interrupt(void)
    {
    uint_fast16_t status = GPIO_getEnabledInterruptStatus(GPIO_PORT_P5);
    GPIO_clearInterruptFlag(GPIO_PORT_P5, status);

    if(status & GPIO_PIN0)
    {
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN0);
    Set_Flag_L = 1;
    }
    }

    I set a flag that means something only for the main(). This is done very quick i think.
  • If neither ISR blocks, I'm not sure I see how one would exclude the other. Once the higher-priority ISR exits, the lower-priority ISR should execute.

    Yes, on the Cortex some nesting happens all the time. The canonical hazard with nesting is shared data/mutual exclusion. This isn't usually a problem when the ISRs are scattered around and work with their own private data. The nesting crossover point is when an ISR re-enables its own IRQ -- at that point it's implicitly sharing data with itself, ergo the hazard. You also implied that the two ISRs interact, which again suggests shared data.

    I'm not quite understanding your second paragraph. The IFGs are not prioritized, only the IRQs, so the high-priority ISR should still see the low-priority ISR's IFG bits (if the events happen simultaneously).

    As I recall, the ISR has to explicitly clear the relevant IFG bits, or the IRQ keeps firing. Are you doing that?

    If you can post your ISR code, maybe things will be more clear.
  • It looks as though, in response to a P4.0 interrupt, you're clearing the P5.0 IFG. That doesn't look quite right, and might produce a symptom similar to what you're describing.
  • Hi Bruce,

    My ISR code is posted above.
    i am using the driverlib as based and not programming directly to the register.
    When an interrupt is triggered it will be handled on the ISR function and then it clears the flag.
    The MCU will only come back to the ISR if an external INT happends at this two pins. Its not firing the hole time.
  • Our replies seem to be crossing in the, um, mail:


    >>It looks as though, in response to a P4.0 interrupt, you're clearing the P5.0 IFG. That doesn't look quite right, and might produce a symptom similar to what you're describing.
  • What do you mean by clearing the P5.0 IFG?
  • Michael Liesenberg85 said:
    What do you mean by clearing the P5.0 IFG?

    Michael Liesenberg85 said:
    void gpio_4_interrupt( void )
    {
      uint_fast16_t status = GPIO_getEnabledInterruptStatus( GPIO_PORT_P4 );
      GPIO_clearInterruptFlag( GPIO_PORT_P4, status );
    
      if( status & GPIO_PIN0 )
      {
        MAP_GPIO_clearInterruptFlag( GPIO_PORT_P5, GPIO_PIN0 );
        Set_Flag_R = 1;
      }
    }

    Look at line 8.

    If you do not clear the interrupt flag that caused the interrupt, the interrupt will be invoked over and over again, resulting in a locked program that can only be interrupted by higher priority interrupts.

    Dennis

  • Yes i am doing that already.
    My problem is that if two INT with different priority happens at same time, the one with less priority, in this case GPIO_PORT_5
    , will not be handled.
    Why is this port not been handled?
  • Did you check if the ISR is left or if it is executed over and over again?
  • Hi Dennis,

    so i set a pin outup to toogle and measured it with an oscilloscope.
    When it enters the ISR the pin gets High and when it clears it gets Low.
    It is not repeating the hole time, it only comes when it receives an Interrupt.
    So this is working. My problem is why is it not handling two interrupts at same time.

    Michael
  • Well, at the same time will never be the case. One is handled after the other.
  • yes this is what i would expect too.
    I will keep measuring it by toogling and see if i find something
  • found the problem.
    I was lazy enougth to copy my code on the forum one from the other.
    On the GPIO_PORT_5 ISR i wasnt clearing the status flag:

    uint_fast16_t status = GPIO_getEnabledInterruptStatus(GPIO_PORT_P5);
    GPIO_clearInterruptFlag(GPIO_PORT_P5, status);<-----------------------------------------this was missing

    Now it handles two INT if this happens at same time.

**Attention** This is a public forum