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.

CCS/MSP430FR2311: Is it possible to use GPIO interrupts in LPM3.5?

Part Number: MSP430FR2311

Tool/software: Code Composer Studio

I know the GPIO interrupts works in LPM3 and I have tested it. But is there a way to use the GPIO interrupts in LMP3.5?

#include <msp430.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "../inc/rtc.h"
#include "../inc/clock.h"

void initGpio();

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer

    // setup_vloclk(); // setup VLO as main clock
    setup_xt1clk(); // setup XT1 as main clock

    initGpio();

    // First determine whether we are coming out of an LPMx.5 or a regular RESET.
	if (SYSRSTIV == SYSRSTIV_LPM5WU)        // When woken up from LPM3.5, reinit
	{
		// If MCU wakes up from LPM3.5, re-init and then return to LPM3.5 again.

		// Restore P1OUT value from backup RAM memory, keep P1OUT after LPMx.5 reset
		P1OUT = *(unsigned int *)BKMEM_BASE; // if this step is not done, the LED will always be in ON state

		__enable_interrupt();               // The RTC interrupt should trigger now...
	}
	else
	{
		// Configure backup memory
		*(unsigned int *)BKMEM_BASE = 0;

		// Device powered up from a cold start.
		// It configures the device and puts the device into LPM4.5

		P1DIR &= ~BIT4;                     // Configure P1.4 as input direction pin
		P1OUT |= BIT4;                      // Configure P1.4 as pulled-up
		P1REN |= BIT4;                      // P1.4 pull-up register enable
		P1IES |= BIT4;                      // P1.4 Hi/Low edge
		P1IFG = 0;                          // Clear all P1 interrupt flags
		P1IE |= BIT4;                       // P1.4 interrupt enabled

		// Configure required GPIO
		P1OUT &= ~BIT1;                         // Clear P1.1 output latch
		P1DIR |= BIT1;                          // For LED


		// rtcinit(RTC_VLO, 10, RTC_1000); // set VLO as clock source, 10 as init value, 1000 as prescaler
		rtcinit(RTC_XT1, 32*20, RTC_1024); // set XT1 as clock source, 640 (20 sec) as init value, 1024 as prescaler

		// Store P1OUT value in backup memory register before enter LPM3.5
		*(unsigned int *)BKMEM_BASE = P1OUT;
	}

	// Enter LPM3.5 mode with interrupts enabled. Note that this operation does
	// not return. The LPM3.5 will exit through a RESET event, resulting in a
	// re-start of the code.

	PMMCTL0_H = PMMPW_H;                    // Open PMM Registers for write
	PMMCTL0_L |= PMMREGOFF;                 // and set PMMREGOFF

	__bis_SR_register(LPM3_bits | GIE);
	//__no_operation();

	//return 0;

}


void initGpio()
{
    P1DIR = 0xFF; P2DIR = 0xFF;
    P1REN = 0xFF; P2REN = 0xFF;
    P1OUT = 0x00; P2OUT = 0x00;

    // Configure required GPIO
	P1OUT &= ~BIT0;                         // Clear P1.0 output latch
	P1DIR |= BIT0;                          // For LED

    // Disable the GPIO power-on default high-impedance mode
    // to activate previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;
}

// Port 1 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void)
#else
#error Compiler not supported!
#endif
{
    P1IFG &= ~BIT4;                         // Clear P1.4 IFG
	P1OUT ^= BIT1; // Toggle
    //__bic_SR_register_on_exit(LPM3_bits);   // Exit LPM3
}

In the above code, if I comment the line 61 and 62 (LMP3) , GPIO interrupts works fine. If I uncomment those lines (LPM3.5), the GPIO interrupt does not work. 

Also, I was measuring the current while doing this experiment. In LPM3.5, when I press and hold the interrupt switch (P1.4 in the above code), the current consumption spikes to 900uA but the interrupt doesn't work. Why is it happening? 

  • Please read section 1.4.3 and 7.3.3 of the Family User's Guide.  You can use interrupts but P1OUT must be saved in backup memory so that it can be stored upon the BOR caused by the GPIO wakeup event.  You also need P1IE initialization outside of your regular RESET statement.  Please see the following example:

    //******************************************************************************
    //   MSP430FR231x Demo - LPM3.5, Device enters LPM3.5 waiting for a port
    //                       interrupt on P1.1
    //
    //   Description: Download and run the program. Program automatically enters
    //                LPM3.5. Use button S1 (or P1.1) on the LaunchPad to wake the
    //                device up from LPM3.5 and blink LED1 (P1.0)
    //
    //   ACLK = REFO = 32kHz, MCLK = SMCLK = default DCODIV = ~1MHz.
    //
    //            MSP430FR2311
    //         -----------------
    //     /|\|                 |
    //      | |                 |
    //      | |                 |
    //      --|RST              |
    //        |                 |
    //        |             P1.0|-->LED
    //        |                 |
    //        |             P1.1|<---Button
    //
    //   Ryan Brown
    //   Texas Instruments Inc.
    //   October 2017
    //   Built with Code Composer Studio v7.2
    //******************************************************************************
    #include <msp430.h>
    
    void initGpio(void);
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop WDT
    
        // Configure GPIO
        initGpio();
    
        P1IE |= BIT1;                       // P1.1 interrupt enabled
    
        // Determine whether we are coming out of an LPMx.5 or a regular RESET.
        if (SYSRSTIV == SYSRSTIV_LPM5WU)        // MSP430 just woke up from LPMx.5
        {
    
            // Restore P1OUT value from backup RAM memory, keep P1OUT after LPMx.5 reset
            P1OUT = *(unsigned int *)BKMEM_BASE;
    
            __enable_interrupt();               // The GPIO interrupt should trigger now...
        }
        else
        {
            // Device powered up from a cold start.
            // It configures the device and puts the device into LPM3.5
    
            // Configure backup memory
            *(unsigned int *)BKMEM_BASE = 0;
    
            // Enable RTC to simply force LPM3.5
            RTCMOD = 32-1;
            RTCCTL = RTCSS__VLOCLK | RTCSR |RTCPS__1024;
    
            P1IFG = 0;                      // Clear all P1 interrupt flags
    
        }
    
        P1DIR &= ~(BIT1);                   // Configure P1.1 as input direction pin
        P1OUT |= BIT1;                      // Configure P1.1 as pulled-up
        P1REN |= BIT1;                      // P1.1 pull-up register enable
        P1IES |= BIT1;                      // P1.1 Hi/Low edge
    
        PMMCTL0_H = PMMPW_H;                // Open PMM Registers for write
        PMMCTL0_L |= PMMREGOFF;             // and set PMMREGOFF
    
        // Enter LPM3 Note that this operation does not return. The LPM3.5
        // will exit through a RESET event, resulting in a re-start
        // of the code.
        __bis_SR_register(LPM3_bits | GIE);
        while(1);
    }
    
    void initGpio()
    {
        P1DIR = 0xFF; P2DIR = 0xFF;
        P1REN = 0xFF; P2REN = 0xFF;
        P1OUT = 0x00; P2OUT = 0x00;
    
        // Disable the GPIO power-on default high-impedance mode
        // to activate previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
    }
    
    // Port 1 interrupt service routine
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    {
        P1IFG &= ~BIT1;                       // Clear P1.1 IFG
        P1OUT ^= BIT0;                        // P1.0 = toggle
        *(unsigned int *)BKMEM_BASE = P1OUT;
    }

    Regards, Ryan

**Attention** This is a public forum