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/MSP432P401R: Entering/Using low power mode 3

Part Number: MSP432P401R

Tool/software: Code Composer Studio

Hi,

I am trying to enter low power mode 3 (LPM3) using the msp432 P401R launchpad (red) and have had little success. 

I have changed the my clock to low frequency, turned off the supply voltage supervisor and monitor, turned on the force entry bit, and changed the watchdog timer to an interval timer to wake up from deep sleep. 

I would like to make an application which goes into deep sleep mode for long periods of time and only turns on for short bursts. The code I have now is down to the barebones, to see if I can get an estimated battery life of over 2 months. The example in the resource center results in estimated battery life upwards of 2 months. 

My current code only reaches 5-12 days. 

What am I missing?

Thanks

 * This test code is for testing entering into low power mode
 * Entry into low power mode 3 will be performed
 * Verification will be done using the Energy trace tool within code composer studio
 *
 * with WDT_A_CTL_IS_7 I got about 15 days
 */

#include "msp.h"


#define INT_WDT_BIT (1<<3)


void GPIO_Init(void);
void set_WDT(void);
void low_PWR(void);
void set_CLK(void);
void set_PSS(void);

void main(void)
{
	WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;		// stop watchdog timer
	set_WDT(); // change WDT to interval timer
	GPIO_Init();
	set_CLK(); // set clock to low freq, 32ish khz
	set_PSS();
	low_PWR(); // set low power mode for LPM3

    __enable_interrupt(); // enable interrupts. should wake when WDT interval completes
    __WFI(); // put system to sleep

    while(1)
    {
        // will loop in here, do nothing.
        // when WDT triggers, will wake up and then interrupt will put system back to sleep.
        __WFI(); // put system to sleep

    }

}


void GPIO_Init(void)
{
    // enables pull-up/down resistor on all ports
    /*
    PA -> REN |= 0xFF;
    PB -> REN |= 0xFF;
    PC -> REN |= 0xFF;
    PD -> REN |= 0xFF;
    */

    // sets direction of ports to outputs
    PA -> DIR |= 0xFF;
    PB -> DIR |= 0xFF;
    PC -> DIR |= 0xFF;
    PD -> DIR |= 0xFF;
    // sets all ports to use pull-down resistor
    PA -> OUT &= 0x00;
    PB -> OUT &= 0x00;
    PC -> OUT &= 0x00;
    PD -> OUT &= 0x00;
}

void set_CLK(void)
{
    // enable
    PJ->SEL0 |= 0x03; // PJ only found by accident. Pg 8 of tech ref
    PJ->SEL1 &= ~0x03;
    CS->KEY = CS_KEY_VAL;   // enter key to allow for clk change. Cannot bitmask
    CS->CTL1 = 0; // set everything to 0, which makes lfxtclk the source. Check this reg is 0 after writing to it.
    CS->CTL2 = 0; // Lowest drive strength and current consumption LFXT oscillator
    CS->CTL2 |= (1 << 8); // set enable low freq clk
    CS->CLKEN &= (0<<0) | (0<<1) | (0<<2) | (0<<3); // shuts off clocks ACLK,MCLK,HSMCLK,SMCLK

    // sometimes doesn't work. Need to stabalize
while(CS->IFG & (1 << 0)) // loop until the low freq clock is stable
    {
        CS->CLRIFG |= (1 << 0);
    }
    CS->KEY = 0; // stop making clock changes
}

void set_WDT(void)
{
    // sets WDT to wakeup from sleep mode
    // WDT_A_CTL_IS_1 1 day and change
    // WDT_A_CTL_IS_2 4 min 16 sec
    // WDT_A_CTL_IS_4 1 sec
    // WDT_A_CTL_IS_7 1.95 ms

    WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_IS_1 | WDT_A_CTL_TMSEL;
    NVIC->ISER[0] |= INT_WDT_BIT;
}
void WDT_A_IRQHandler (void)
{
    // what happens when the watchdog timer triggers

}

void low_PWR(void)
{
    // sets upt low power mode 3 LPM3
    //PCMCTL0 -> CTL0
    /////// Core 0
    SCB -> SCR |= (1 << 2);  // sleep bit to premp
    // PCM->CTL0 = PCM_CTL0_KEY_VAL | (1 << 8) | (1 << 0); not needed
    PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR__AM_LF_VCORE0; // set to low power mode 3
    PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_LPMR__LPM3; // set to low power mode 3
    PCM->CTL1 = PCM_CTL1_KEY_VAL | (1 << 2); // force entry to LPM3
}

void set_PSS(void)
{
    PSS ->KEY = PSS_KEY_KEY_VAL; // opens access to PSS
    PSS ->CTL0 |= PSS_CTL0_SVSMHOFF; // Turns off SVSM
    PSS ->KEY = 1; // closes access to PSS
}

  • Hi Adrian,

    What example are you referring to? Which version of the SDK are you using?

    Thanks,

    Alexis

  • Hi Alexis,

    I am using the example pcm_go_to_lpm3 under the DriverLib folder. The SDK I'm using is SimpleLink MSP432P4 SDK - v:3.20.00.06

    I was able to get a few extra days, up into the mid to high teens by changing the clock setting until after I change the power mode requests. 

    Thanks,

    Adrian

  • Hi Adrian,

    So just to clarify, you're saying that with the SDK example as is you can get over 2 months of battery life, but with your modifications you're getting much less? 

    Thanks,

    Alexis

  • Hi Alex, 

    Yes, with the SDK example which uses the TI APIs I was getting over two months of battery life. With my original code I was getting much less. I wanted to do it by using the registers.

    I finally figured out the issue yesterday. I did not set all the gpio pins to conserve power. 

    /*
     * Fixed 8/8/2019
     * Issue stemmed from GPIO pins not set to conserve power.
     *
     * After build, testing while in free run mode yields 2 months and 26 days of battery life
     * - build code
     * - open debug session
     * - run menu -> click restart
     * - run menu -> free run
     *
     * Close debug session and use energy trace (icon next to flashlight) and run
     * - results more than 5 years of battery life
     *
     * Changing to use VLO instead of LFXT changes battery life to years!
     */
    
    #include "msp.h"
    
    #define INT_WDT_BIT (1<<3) // used to turn on WDT interrupt
    void GPIO_Init(void);
    void set_WDT(void);
    void low_PWR(void);
    void set_CLK(void);
    void set_PSS(void);
    void set_AM(void);
    
    void main(void)
    {
    	WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_HOLD;		// stop watchdog timer
    	set_WDT(); // change WDT to interval timer, which will wake at end of timer run and repeat
    	GPIO_Init(); // turns off all gpio to save power
    	set_PSS(); // turn off SVSM
    	set_AM();  // set active mode to low freq and vcore 0
    	low_PWR(); // set low power mode for LPM3
    	set_CLK(); // set clock to low freq, 32ish khz
    
        __enable_interrupt(); // enable interrupts. should wake when WDT interval completes
    
        while(1)
        {
            // will loop in here, do nothing.
            // when WDT triggers, will wake up and then interrupt will put system back to sleep.
            __WFI(); // put system to sleep
        }
    }
    
    void GPIO_Init(void) // turns off all gpio
    {
        // This works. 16 bits total per register.
        // PA is P1 & P2 which is 8 bits a piece, and PB is P3 & P4, etc. This code now works.
        // enables pull-up/down resistor on all ports
        PA -> REN |= 0xFFFF;
        PB -> REN |= 0xFFFF;
        PC -> REN |= 0xFFFF;
        PD -> REN |= 0xFFFF;
        PE -> REN |= 0xFFFF;
        // sets direction of ports to outputs
        PA -> DIR |= 0xFFFF;
        PB -> DIR |= 0xFFFF;
        PC -> DIR |= 0xFFFF;
        PD -> DIR |= 0xFFFF;
        PE -> REN |= 0xFFFF;
        // sets all ports to use pull-down resistor
        PA -> OUT &= 0x0000;
        PB -> OUT &= 0x0000;
        PC -> OUT &= 0x0000;
        PD -> OUT &= 0x0000;
        PE -> OUT &= 0x0000;
    }
    
    void set_CLK(void) // sets up LFXTCLK
    {
        // PJ needs to be enabled to use LFXTCLK
        PJ->SEL0 |= 0x03; // PJ only found by accident. Pg 8 of tech ref
        PJ->SEL1 &= ~0x03;
        CS->KEY = CS_KEY_VAL;   // enter key to allow for clk change. Cannot bitmask
        CS->CTL1 = 0; // set everything to 0, which makes lfxtclk the source. Check this reg is 0 after writing to it.
        CS->CTL2 = 0; // Lowest drive strength and current consumption LFXT oscillator
        CS->CTL2 |= (1 << 8); // set enable low freq clk
        CS->CLKEN &= (0<<0) | (0<<1) | (0<<2) | (0<<3); // shuts off clocks ACLK,MCLK,HSMCLK,SMCLK
    
        // sometimes doesn't work. Need to stabalize
    while(CS->IFG & (1 << 0)) // loop until the low freq clock is stable
        {
            CS->CLRIFG |= (1 << 0);
        }
        CS->KEY = 0; // stop making clock changes
    }
    
    void set_WDT(void) // sets up WDT to interval mode for use in LPM3. This will wake up from LPM3 when timer loops
    {
        // sets WDT to wakeup from sleep mode
        // WDT_A_CTL_IS_1 1 hour and 8ish minutes
        // WDT_A_CTL_IS_2 4 min 16 sec
        // WDT_A_CTL_IS_4 1 sec
        // WDT_A_CTL_IS_7 1.95 ms
        WDT_A->CTL = WDT_A_CTL_PW | WDT_A_CTL_IS_1 | WDT_A_CTL_TMSEL;
        NVIC->ISER[0] |= INT_WDT_BIT;
    }
    void WDT_A_IRQHandler (void)
    {
        // what happens when the watchdog timer triggers
    }
    
    void low_PWR(void)
    {
        // sets up low power mode 3 LPM3
        /////// Core 0
        SCB -> SCR |= (1 << 2);  // sleep bit to premp
        PCM->CTL1 = PCM_CTL1_KEY_VAL | (1 << 2); // force entry to LPM3
        // PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR__AM_LF_VCORE0; // set to low power mode 3
        PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_LPMR__LPM3; // set to low power mode 3
        // PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR__AM_LF_VCORE0 | PCM_CTL0_LPMR__LPM3;
        while(PCM->CTL1 & 0x00000100) //makes sure PCM is not busy
        {
            // wait to stabilize
        }
    }
    
    void set_PSS(void) // turns off SVSM
    {
        PSS ->KEY = PSS_KEY_KEY_VAL; // opens access to PSS
        PSS ->CTL0 |= PSS_CTL0_SVSMHOFF; // Turns off SVSM
        PSS ->KEY = 1; // closes access to PSS
    }
    
    void set_AM(void) // sets active mode to low freq and vcore 0
    {
        PCM->CTL0 = PCM_CTL0_KEY_VAL | PCM_CTL0_AMR__AM_LF_VCORE0;
        while(PCM->IFG & (1 << 2)) // makes sure active mode does trigger a flag.
        {
            PCM->CLRIFG |= (1 << 2);
        }
        while(PCM->CTL1 & 0x00000100) // makes sure PCM is not busy after active mode change.
        {
            // wait to stabilize
        }
    }
    

**Attention** This is a public forum