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: Interrupt Service Routines called twice

Part Number: MSP432P401R

I have found that my ISRs are being called twice unless I order my code correctly.  Below is a simple interrupt based program running on the MSP432 Launchpad.  I have found that the PORT1_IRQHandler:

void PORT1_IRQHandler(void) {
		P1OUT ^= RED; // toggle RED led
		P1IFG = 0; // clear the flag
}

is being called twice for each button press, and it is not the result of contact bounce.  From some online investigation, it appears that clearing the flag uses the advanced peripheral bus (APB) to communicate with the flag register and this can be delayed.  Thus, when the CPU returns from the ISR and sees that the flag isn't cleared yet, it goes right back into the ISR.  From what I've read, the solution is to have an APB read instruction after you clear the flags within the ISR, which ensures that the flag clearing is complete before the ISR completes by "flushing" the bus.

I was able to fix the program below by swapping the order of the two statements in the ISR to:

void PORT1_IRQHandler(void) {
		P1IFG = 0; // clear the flag
		P1OUT ^= RED; // toggle RED led
}

This way there is a read-modify-write of P1OUT following the flag clearing.  

Am I correct in my explanation of the behavior?  Is this documented anywhere?

//***************************************************************************** // Simple Port1 Interrupt example //**************************************************************************** #include "msp.h" #define S1 BIT1 // S1 button connected to P1.1 #define RED BIT0 // red LED connectred to P1.0 void main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer // enable the red LED for output P1OUT &= ~RED; P1DIR |= RED; // set S1 as an input with a pull-up resistance P1DIR &= ~S1; P1REN |= S1; P1OUT |= S1; // enable falling edge interrupt for S1 P1IES |= S1; P1IE |= S1; P1IFG = 0; // enable Port 1 interrupts in NVIC NVIC_EnableIRQ(PORT1_IRQn); // global interrupt enable __enable_interrupts(); while(1) {} } ////////////////////////////////////////////// // port1ISR - Port 1 Interrupt Service routine // Arguments: none // return value: none ////////////////////////////////////////////// void PORT1_IRQHandler(void) { P1OUT ^= RED; // toggle RED led P1IFG = 0; // clear the flag }

**Attention** This is a public forum