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.

MSP430F5529: Board Freezes on __bis_SR_register(GIE)

Part Number: MSP430F5529
Other Parts Discussed in Thread: MSP-EXP430F5529LP

I am trying to write a basic interrupt code using interrupts from Button S2 (Port 1.1) to toggle LED1 (Port P1.0).

I have gotten polling to register button presses but my interrupt code does not appear to be working. Specifically, using the debugger, it appears the code is not passing the __bis_SR_register(GIE) statement.

Does anyone know why this code is not working to use interrupts to toggle an LED?

My code is:

#include <msp430f5529.h>


#define RED_LED BIT0
#define BUTTON BIT1

int main() {
    P1DIR |= RED_LED;
    P1OUT &= ~RED_LED;

    // Set as input pin
    P1DIR &= ~BUTTON;

    // Set pullup resistor
    P1REN |= BUTTON;
    P1OUT |= BUTTON;

    // Interrupt Edge Select
    P1IES &= ~BUTTON;

    // Clear Interrupt Flag
    P1IFG &= ~BUTTON;

    // Set as interrupt pin
    P1IE |= BUTTON;

    __bis_SR_register(GIE);

    while(1) {
        
    }
}

#pragma vector=PORT1_VECTOR
__interrupt void port1_isr(void) {
    P1OUT ^= RED_LED;
    P1IFG &= ~BUTTON;
}

  • This could be an illusion introduced by the debugger: Your while() loop is only a single instruction, so the PC would always point there.

    You could try putting something in the loop ( __NOP() or something equally innocuous) and see if it looks different.

    I see no obvious cause for a stray interrupt.

    Unsolicited: You'll probably observe some switch bounce. If it bounces an even number of times (50:50 chance), the LED won't (visibly) change. Keep trying, or google "ganssle debounce".
  • Thank you for the quick response.

    Putting a "__nop()" call in the while loop did fix the debugger appearing to never pass the __bis_SR_register(GIE) call. It now properly steps through the while loop.

    However, the interrupt still seems to not be called. I simplified my code slightly so that the LED starts in the low position, and if the interrupt is ever called, it will turn to high. (I think this should elimate the possibility that the ISR is called but because of switch bounce I don't realize).

    Still, the LED never switches to on which seems to mean the ISR is never called.

    My code is now:

    #include <msp430.h>
    
    
    #define RED_LED BIT0
    #define BUTTON BIT1
    
    int main() {
        P1DIR |= RED_LED;
        P1OUT &= ~RED_LED;
    
        // Set as input pin
        P1DIR &= ~BUTTON;
    
        // Set pullup resistor
        P1REN |= BUTTON;
        P1OUT |= BUTTON;
    
        // Interrupt Edge Select
        P1IES &= ~BUTTON;
    
        // Clear Interrupt Flag
        P1IFG &= ~BUTTON;
    
        // Set as interrupt pin
        P1IE |= BUTTON;
    
        //__bis_SR_register(GIE);
        __enable_interrupt();
    
        while(1) {
            __nop();
        }
    }
    
    #pragma vector=PORT1_VECTOR
    __interrupt void port1_isr(void) {
        P1OUT |= RED_LED;
        P1IFG &= ~BUTTON;
    }

  • You need:
    WDTCTL = WDTPW+WDTHOLD;

    Sample code (linked from the product page) to the rescue. This stuff is easy to forget.
  • Hi,

    I placed this code as the first line of the main function, but it seems that disabling the watchdog is unfortunately not changing anything either.

  • Hm. I added that line, and pushing the P1.1 button turned on the LED (Rev 1.5 Launchpad).

    1) Have you tried setting a breakpoint in the ISR?
    2) Is the jumper next to the LED installed?
    3) One curiosity: I had to explicitly add:
    #define __nop() do {asm volatile(" nop");}while(0)
    to get it to build. (intrinsics.h has _nop(), with one underbar.) Apparently you were getting it from elsewhere(?). Maybe try adding that line or change the function name to _nop().

    [Edit: Added a blank to the nop instruction; results are unchanged.]

  • Hello,

    I tried putting a breakpoint on the line where I call __nop() and also on the first line in my ISR.
    When I call next in GDB, I hit the breakpoint in the while loop, but I never hit the breakpoint
    in the interrupt routine even if i click the button.

    The jumper next to the LED (betweeen LED on P4.7 and the LED on P1.0) is installed.

    I tried both changing __nop to _NOP and using your definition of __nop(), but neither changed anything.

    My board is an MSP-EXP430F5529LP, Rev 1.6
  • Today I borrowed a Rev 1.6 Launchpad, and it behaves the same as my Rev 1.5, i.e. it operates as expected.

    Are you always using "next" or are you letting it free-run as well? I vaguely recall that GDB's "next" (as well as "step") command had a somewhat tenuous relationship with interrupts -- I recall having to set a breakpoint at the next statement and "continue".

    I regret that I have run out of suggestions. Your code can work, and there's something (that I'm not thinking of) different between what you and I are doing.
  • Hi,

    Thank you for all the help.

    I have found the problem with my code.

    It seems to define the interrupt I needed to be using __attribute ((interrupt(PORT1_VECTOR))) instead of #pragma vector=PORT1_VECTOR  __interrupt

    My final code that works is (note: this does not include button debouncing):

    #include <msp430f5529.h>
    
    #define RED_LED BIT0
    #define BUTTON BIT1
    
    int main() {
        WDTCTL = WDTPW + WDTHOLD;
    
        // Set LED1, P1.0, as output
        P1DIR |= RED_LED;
    
        // Set LED1, P1.1, to low
        P1OUT &= ~RED_LED;
    
        // Set as input pin
        P1DIR &= ~BUTTON;
    
        // Set pullup resistor
        P1REN |= BUTTON;
        P1OUT |= BUTTON;
    
        // Interrupt Edge Select
        P1IES &= ~BUTTON;
    
        // Clear Interrupt Flag
        P1IFG &= ~BUTTON;
    
        // Set as interrupt pin
        P1IE |= BUTTON;
    
        // Enter Low Power Mode 0 and enable maskable interrupts 
        __bis_SR_register(LPM0_bits + GIE);
    }
    
    void __attribute__ ((interrupt(PORT1_VECTOR))) port1_isr(void) {
    
        // Switch LED1
        P1OUT ^= RED_LED;
    
        // Clear port 1 interrupt flag
        P1IFG &= ~BUTTON;
    }

**Attention** This is a public forum