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.

MSP432P401R: GPIO interrupt still triggers although all interrupts are disabled using Interrupt_disableMaster();

Part Number: MSP432P401R

Hello 

I have a simple program that tests GPIO Interrupts. I followed the steps of interrupt enable sequence suggested by MSPWare code examples. Basically 1) start a critical section and disable all interrupts within, 2) configure GPIO interrupt port, pin, and edge select, 3) NVIC setup and finally 4) enable master interrupt to end the critical section. 

My code function is simple, when switch 1 button is pressed this will toggle LED1 in the ISR. 

The question is basically regarding Interrupt_enableMaster(); I tried to comment out this line to see the effect of it. I was expecting that by commenting it out pressing the switch1 button will have no effect since all interrupts are disabled using (Interrupt_disableMaster();) without re-enabling because (Interrupt_enableMaster();)  is commented out?

I am really confused because of them and really question that idea of critical section.

My code is bellow here:

/******************************************************************************
 * This program toggle LED1 when switch s1 is pressed (Red). While it toggles LED2 when Switch 2 is pressed (Blue)
 * When both switches are pressed LED2 (Purple) toggles
*******************************************************************************/

#include "driverlib.h"

void LED1_Initialization(){
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); // set P1.0 as output (P1.0 is connected to low power LED1)
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0); // initially off
};

void SW1_Initialization(){
    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1); //Pin1.1 is connected to SW1
};

int main(void)
{

    WDT_A_holdTimer();

    LED1_Initialization();
    SW1_Initialization();

    // 7 steps of GPIO interrupt setup
    // 1- start critical section by disable all interrupts
    Interrupt_disableMaster();
//--------------------------------- start critical section --------------------------------------------------//
    // 2- Edge Select. In our case when any button is pressed low voltage will be input (falling edge)
    GPIO_interruptEdgeSelect (GPIO_PORT_P1, GPIO_PIN1, GPIO_HIGH_TO_LOW_TRANSITION);

    // 3- clear interrupt flag
    GPIO_clearInterruptFlag (GPIO_PORT_P1, GPIO_PIN1);

    // 4- enable the GPIO interrupt
    GPIO_enableInterrupt (GPIO_PORT_P1, GPIO_PIN1);

    // 5- Set priority
    Interrupt_setPriority (INT_PORT1, 0); // SW1 is linked to P1.1, and 0 is highest priority

    // 6- enable the interrupt in NVIC on port 1
    Interrupt_enableInterrupt(INT_PORT1);

    // 7- end of critical section, Enable interrupts that are already enabled
    //Interrupt_enableMaster(); /*Here is the problem. Even if this line is commented, pressing switch1 button still invokes interrupts and toggles LED1*/
//--------------------------------- end critical section --------------------------------------------------//
    while(1)
    {
        PCM_gotoLPM0InterruptSafe(); // put MC in sleep until interrupt happens
    }
}


void PORT1_IRQHandler(void)
{
    MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
    GPIO_clearInterruptFlag (GPIO_PORT_P1, GPIO_PIN1);
}

 

  • Here's PCM_gotoLPM0InterruptSafe. You'll notice it briefly enables, then disables  interrupts.

    I understand why they did it, though in retrospect it could be considered surprising. If you replace that call with "__WFI();" you'll get the result you're looking for. (You'll get a wakeup but the ISR won't be called.)

    bool PCM_gotoLPM0InterruptSafe(void)
    {
        bool slHappenedCorrect;
    
        /* Disabling master interrupts. In Cortex M, if an interrupt is enabled but
         master interrupts are disabled and a WFI happens the WFI will
         immediately exit. */
        Interrupt_disableMaster();
    
        slHappenedCorrect = PCM_gotoLPM0();
    
        /* Enabling and Disabling Interrupts very quickly so that the
         processor catches any pending interrupts */
        Interrupt_enableMaster();
        Interrupt_disableMaster();
    
        return slHappenedCorrect;
    }

  • Thanks Bruce, __WFT(); works!

    does __WFT(); also put the MC in to sleep like PCM_gotoLPM0InterruptSafe()?

  • A bare __WFI() is approximately LPM0. To get higher LPM-s you need to fiddle some other registers that driverlib knows about (and I always have to look up).

    I'm supposing that the LPM questions are just part of your test, since one wouldn't ordinarily go into LPM in a critical section.

**Attention** This is a public forum