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 Launchpad, waking up from LPM3

Hello,

I think I am able to enter LPM3 successfully but I noticed whenever I wake up the MCU with the pushbutton using edge interrupt, the MCU wakes up but the clock does not return to the original state before it entered LPM3. Before entering LPM3, I my MCLK was HFXT 48MHz / 4 = 12MHz. I tried various waits. I had a while loop to wait if the clock is ready and to wait if the CM mode is at AM LDO VCORE0 and still, my clock would never return to 12 MHz even after the while loops.. I know because my LED blink timing was way off. To solve the problem, this is what I did,

void PORT1_IRQHandler(void)
{
 volatile uint32_t pressCount, notPressCount;
 
 if(DeepSleepFlag == 1)
 {
  Configure_MCLK_12MHz();
  Enable_LFXT_32768KHz();
  SCB->SCR &= 0xFFFFFFE9;
  DeepSleepFlag = 0;  
 }//end if(DeepSleepFlag == 1)

......

}

Notice in the beginning of my interrupt handler, I initialize my clocks again. After doing this, everything was back to normal. But I was under the impression that waking up from LPM3 would return you back to the state you were before entering. Any thoughts? Previously I had a while loop checking if the clocks were ready instead of Configure MCLK and Enable LFXT, but that didn't work.

Here is my code before entering LPM3

   WDTCTL = WDTPW | WDTHOLD;
   Configure_Deep_Sleep_Parameters();
   SCB->SCR |= 0x00000004;
   __wfi();

void Configure_Unused_Ports(void)
{
 P1DIR |= 0xED;
 P2DIR = 0xFF;
 PBDIR = 0xFFFF;
 PCDIR = 0xFFFF;
 PDDIR = 0xFFFF;
 PEDIR = 0xFFFF;
 P1OUT &= 0x12;
 P2OUT = 0x00;
 PBOUT = 0x0000;
 PCOUT = 0x0000;
 PDOUT = 0x0000;
 PEOUT = 0x0000; 
}//end void Configure_Unused_Ports(void)
/***********************************************/
void Configure_Deep_Sleep_Parameters(void)
{
 Configure_Unused_Ports();
 
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
 
 PCM->CTL1 = (PCM->CTL1 & 0x0000FFF8) | 0x695A0000 | 0x00000004; //enable LPM3 force entry
 PCM->CTL0 = (PCM->CTL0 & 0x0000FF0F) | 0x695A0000 | 0x00000000; //request for LPM3
 
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
}//end void Configure_Deep_Sleep_Parameters(void)
/***********************************************/

Below is my code when I initialized my clocks:

void Configure_MCLK_12MHz(void)

 //This section is necessary to ensure VCORE level supports 48MHz crystal
 //by requesting AM LDO VCORE1
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
 
 PCM->CTL0 = (PCM->CTL0 & 0x0000FFF0) | 0x695A0000 | 0x00000001; //request AM LDO VCORE1
 while((PCM->CTL0 & 0x00003F00) != 0x00000100)
 {
  //wait until CPM = 1, current pwer mode = AM LDO VCORE1
 }//end while((PCM->CTL0 & 0x00003F00) != 0x00000100)
 
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
 /***********************************************/
 //This section enables HFXT and sets MCLK = 12MHz, HSMCLK = 6MHz, SMCLK = 3MHz
 //ACLK and BCLK sourced by REFO_CLK at 32.768KHz
 PJSEL0 |= 0x0C; //PJ.3 is HF out, PJ.2 is HF in
 PJSEL1 &= 0xF3; 
 
 CS->KEY = 0x0000695A; //unlock clock system registers
 
 while((CS->STAT & 0x1F000000) != 0x1F000000)
 {
  //wait until clocks are ready
 }//end while((CS->STAT & 0x1F000000) != 0x1F000000)
 

 CS->CTL2 = (CS->CTL2 & 0xFDE9FC03) | 0x01610000;
 
 while((CS->IFG & 0x00000002) == 0x00000002) //HFXT fault
 {
  CS->CLRIFG = 0x00000002; //continue clearing the fault flags until clock have stabilized.
 }//end while(CS->IFG & 0x00000002)
 CS->CLRIFG = 0x00000200; //clear HFXT start fault counter
  
 
 CS->CTL1 = (CS->CTL1 & 0xC8BAFADD) | 0x40321255;
 
 while((CS->STAT & 0x1F000000) != 0x1F000000)
 {
  //wait until clocks are ready
 }//end while((CS->STAT & 0x1F000000) != 0x1F000000)
 
 CS->KEY = 0; //lock clock system registers
 /***********************************************/
 //This section switches power mode back to AM LDO VCORE0
 //AM LDO VCORE0 supports 12MHz
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
 
 PCM->CTL0 = (PCM->CTL0 & 0x0000FFF0) | 0x695A0000 | 0x00000000; //request AM LDO VCORE0
 
 while((PCM->CTL0 & 0x00003F00) != 0x00000000)
 {
  //wait until CPM = 0, current pwer mode = AM LDO VCORE0
 }//end while((PCM->CTL0 & 0x00003F00) != 0x00000000)
 
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
}//end void Set_MOSC_12MHz(void)
/***********************************************/
void Enable_LFXT_32768KHz(void)
{
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
 
 PJSEL0 |= 0x03; //PJ.1 is LF out, PJ.0 is LF in
 PJSEL1 &= 0xFC; 
 
 CS->KEY = 0x0000695A; //unlock clock system registers
 
 while((CS->STAT & 0x1F000000) != 0x1F000000)
 {
  //wait until clocks are ready
 }//end while((CS->STAT & 0x1F000000) != 0x1F000000)
 
 CS->CTL2 = (CS->CTL2 & 0xFDE9FD00) | 0x00000100;
 
 while((CS->IFG & 0x00000001) == 0x00000001) //LFXT fault
 {
  CS->CLRIFG = 0x00000001; //continue clearing the fault flags until clocks have stabilized.
 }
 CS->CLRIFG = 0x00000100; //continue clearing the fault flags until clocks have stabilized.
 
 CS->CTL1 &= 0xC8BAE8DD; //BCLK, ACLK source is LFXT
 
 while((CS->STAT & 0x1F000000) != 0x1F000000)
 {
  //wait until clocks are ready
 }//end while((CS->STAT & 0x1F000000) != 0x1F000000)
 
 CS->KEY = 0; //lock clock system registers
 
 while((PCM->CTL1 & 0x00000100) == 0x00000100)
 {
  //wait until PMR_BUSY = 0 to signal PCMTL0 and CS ready
 }//end while(PCM->CTL1 & 0x00000100)
}//end void Enable_LFXT_32768KHz(void)
/***********************************************/

Thanks

AJ

  • AJ,

       I have gone through some of the documentation and this does not appear to be clear.  During LPM3 the HFXT is disabled and must be restarted when returning to active mode.  I ran a quick test and found that the HFXTIFG was set indicating a fault and that the MCLK is sourced from SYSOSC as a failsafe.  Please find the attached example where I simply clear the fault within the ISR. Please let me know if you have any questions.

    Chris

    Please refer to a later post in this thread for the example.

  • AJ,

    You may also find this thread useful - e2e.ti.com/.../1947196

    Regards,

    David
  • /*
     * -------------------------------------------
     *    MSP432 DriverLib - v3_21_00_05 
     * -------------------------------------------
     *
     * --COPYRIGHT--,BSD,BSD
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    /*******************************************************************************
     * MSP432 PCM - Going to LPM3
     *
     * Description: In this very simple example, the use of the PCM API to go to
     * LPM3 is demonstrated. The device is configured for GPIO interrupt
     * (to wake the device up when the user presses the button on P1.1) and then
     * the device is put into LPM3 using the PCM_gotoLPM3 function. Furthermore,
     * the device is configured in a manner to minimize power consumption and
     * achieve datasheet specifications with regard to power consumption.
     *
     *                MSP432P401
     *             ------------------
     *         /|\|                  |
     *          | |                  |
     *          --|RST         P1.0  |---> P1.0 LED
     *            |                  |
     *            |            P1.1  |<--Toggle Switch
     *            |                  |
     *            |                  |
     *
     * Author: Timothy Logan
     ******************************************************************************/
    /* DriverLib Includes */
    #include "driverlib.h"
    
    /* Standard Includes */
    #include <stdint.h>
    
    #include <stdbool.h>
    
    int main(void)
    {
    	uint16_t ii;
        /* Halting the Watchdog */
        MAP_WDT_A_holdTimer();
    
        /* Terminating all remaining pins to minimize power consumption. This is
            done by register accesses for simplicity and to minimize branching API
            calls */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_PA, PIN_ALL16);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_PB, PIN_ALL16);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_PC, PIN_ALL16);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_PD, PIN_ALL16);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_PE, PIN_ALL16);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PA, PIN_ALL16);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PB, PIN_ALL16);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PC, PIN_ALL16);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PD, PIN_ALL16);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PE, PIN_ALL16);
    
        /* Configuring P1.0 as output and P1.1 (switch) as input */
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
        /* Configuring P1.1 as an input and enabling interrupts */
        MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
        MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
        MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);
        MAP_Interrupt_enableInterrupt(INT_PORT1);
        MAP_Interrupt_disableSleepOnIsrExit();
    
        /* Configuring pins for peripheral/crystal usage and LED for output */
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
                GPIO_PIN3 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    
        /*
         * Starting LFXT and sourcing ACLK and BCLK from it
         */
        MAP_CS_setExternalClockSourceFrequency(32000,48000000);
    
        CS_startHFXT(false);
    
        MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
                GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_CS_startLFXT(false);
        MAP_CS_initClockSignal(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
        MAP_CS_initClockSignal(CS_BCLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
    
        /* Initializing MCLK to HFXT (effectively 48MHz) */
        MAP_CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_4);
    
        /* Disabling high side voltage monitor/supervisor */
        MAP_PSS_disableHighSide();
    
        /* Enabling "rude" mode which forces device to go to sleep regardless of
         * outstanding clock requests
         */
        MAP_PCM_enableRudeMode();
    
        /* Enabling MASTER interrupts */
        MAP_Interrupt_enableMaster();
    
        /* Going to LPM3 */
        while (1)
        {
            for(ii=0;ii<10;ii++)
            {
            	P2->OUT ^= BIT0;
            	__delay_cycles(3000000);
            }
            P2->OUT &= ~BIT0;
            /* Note that while this examples just goes to LPM3, LPM4 is essentially
                just LPM3 with WDT_A/RTC_C disabled. For convenience, the user can 
                use the MAP_PCM_gotoLPM4() function if they want the API to handle
                the disabling of these components */
            MAP_PCM_gotoLPM3();
            // Toggle GPIO
        }
    }
    
    /* GPIO ISR */
    void PORT1_IRQHandler(void)
    {
        uint32_t status;
    
        status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
        MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);
    
        /* Toggling the output on the LED */
        if(status & GPIO_PIN1)
        {
            MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
            CS->KEY = CS_KEY;
            while(CS->IFG & CS_IFG_HFXTIFG)
            {
                CS->CLRIFG |= CS_CLRIFG_CLR_HFXTIFG;
            }
            CS->KEY = 0;
        }
    }
    
    

    AJ,

       I found that in this example that I did not properly configure all of Port 1 so the current consumption is a little high for LPM3.  I have modified (and removed attachement from the previous).

    Regards,

    Chris

  • Hi David and Chris,

    Thanks for the response.

    Regards,
    AJ

**Attention** This is a public forum