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.

MSP430F5219 trouble getting into LPM4.5 mode

Expert 1570 points
Other Parts Discussed in Thread: MSP430F5219

Hi,
    I have a custom board using the MSP430F5219, and I'm trying to get the LPM4.5 mode working.  The code I'm using to enter and exit is below.  When it calls goToLPM4_5(), it does seem to stop running, but I don't believe it is actually going to LPM4.5 mode because the Vcore voltage doesn't drop (it stays at ~1.94V), and I need to actually include the ISR that calls main() in order for the pin interrupt to bring it back to main().  My understanding is that the Vcore should drop to 0V and the ISR isn't needed since the pin interrupt in LPM4.5 will cause a BOR.

    The HAL_ConfigureHardware() function is called from main() right after disabling the watchdog.  (This code is based on the Bluetopia SPPLE stack demo application, and I added the goToLPM4_5() function and some lines to the HAL_ConfigureHardware() function.)

    When it does wake up (from whatever low power mode it was in), it doesn't behave as it does from a normal power-on reset.  Things run much slower (~1/10th speed) and just don't behave properly.

    I tried disabling as many peripherals and interrupts as I could think of, even if they aren't being used (to my knowledge), like RTC, but I still can't seem to get it into LPM4.5 mode.  I suspect it's related to the clocks, and I'm not sure I've set those correctly before entering sleep mode.

    Any thoughts or suggestions are appreciated.

Thanks
Angelo



void goToLPM4_5() {
	UCSCTL4 = SELA_1;

	//reset all GPIOs
	P1OUT = 0x00;P2OUT = 0x00;P3OUT = 0x00;P4OUT = 0x00;P5OUT = 0x00;P6OUT = 0x00;P7OUT = 0x00;PJOUT = 0x00;
	P1DIR = 0xFE;P2DIR = 0xFF;P3DIR = 0xFF;P4DIR = 0xFF;P5DIR = 0xFF;P6DIR = 0xFF;P7DIR = 0xFF;PJDIR = 0xFF;


	//enable Port1 interrupt
	P1IE |= (BIT4);
	//interrupt on falling edge
	P1IES |= (BIT4);
	//clear interrupt flag
	P1IFG &= ~(BIT4);


	//disable other interrupts to prevent it from waking up right after going to sleep
	P2IE = 0;
	TA2CCTL0 = 0;
		
		
	//set GIE in case there any pending flags to service
	__enable_interrupt();					//enable interrupts
	
		
      //Enable LPM4.5 mode

	// Disable SVS
	PMMCTL0_H = PMMPW_H;                	// PMM Password
	SVSMHCTL &= ~(SVMHE+SVSHE);         	// Disable High side SVS
	SVSMLCTL &= ~(SVMLE+SVSLE);         	// Disable Low side SVS

	//this turns off the PMM to allow for LPM4.5
	PMMCTL0_L |= PMMREGOFF;                   // set Flag to enter LPM4.5 with LPM4 request

	//Enter LPM4.5 mode
	LPM4;
}


#pragma vector=PORT1_VECTOR
__interrupt void Port1_ISR(void) 
{
	//this should not run, since LPM4.5 will just RST uC
	LPM4_EXIT;
	main();
}


void HAL_ConfigureHardware(void)
{
	long int i;
	
	/* Configure the default board setup.                                */
	ConfigureBoardDefaults();

	//check PMMLPM5IFG flag to see if RST from LPM4.5
	if (PMMLPM5IFG & PMMIFG) {
		//if exited from LPM4.5, unlock IO
		PMMCTL0_H = PMMPW_H;
		PM5CTL0 &= ~(LOCKLPM5);
	}

	/* Call the MSP430F5438 Experimentor Board Hardware Abstraction Layer*/
	/* to setup the system clock.                                        */
	StartCrystalOscillator();
	SetSystemClock(BT_CPU_FREQ);
	
	/* Configure the scheduler timer.                                    */
	ConfigureTimer();
	
	//show that we came out of reset
	setOutput (GREEN_LED, 1);
	for (i=0;i<10000;i++) asm("nop");
	setOutput (BLUE_LED, 1);
	for (i=0;i<10000;i++) asm("nop");
	setOutput (GREEN_LED, 0);
	for (i=0;i<10000;i++) asm("nop");
	setOutput (BLUE_LED, 0);
	for (i=0;i<10000;i++) asm("nop");
}

  • Spread across different (but linked) locations, the users guide gives some more requirements for LPMx.5:
    XT1OFF and XT2OFF must be 1 (oscillators must be off) or the device won’t enter LPMx.5 (note 1 to table 5-1: Cock Request System and Power Modes). Referred to by point 3 in chapter 1.4.1

    PMMLPM5IFG needs to be cleared before entering LPMx.5. Your test function only checks it. This will prevent wakeup from LMPx.5 (once successfully entered).

  • Thanks for your reply.  I added the two lines below before LPM4, but the behavior didn't change.  Does it look OK?

            //Enable LPM4.5 mode
    
    	// Disable SVS
    	PMMCTL0_H = PMMPW_H;                	// PMM Password
    	SVSMHCTL &= ~(SVMHE+SVSHE);         	// Disable High side SVS
    	SVSMLCTL &= ~(SVMLE+SVSLE);         	// Disable Low side SVS
    
    	//this turns off the PMM to allow for LPM4.5
    	PMMCTL0_L |= PMMREGOFF;                   // set Flag to enter LPM4.5 with LPM4 request
    
    	PMMIFG &= ~PMMLPM5IFG;						//clear flag to allow wakeup from LPM4.5
    
    	UCSCTL6 |= XT1OFF | XT2OFF;					//turn off oscillators
    
    	//Enter LPM4.5 mode
    	LPM4;
    }

  • I don’t have much field experience with LPMs, especially the .5 modes.
    I would set PWMREGOFF right before entering LPM4. Else it might be that the CPU crashes due to lack of supply voltage before it actually enters LPM4. (and therefore the peripherals are still running)
    It might also be necessary to switch SMCLK and ACLK to a different clock source (like VLO), or even manually put active components like timers or UART into sleep.

    The LPM4 command is no master switch. You might need to turn off the lights in every room manually, before setting the CPU into coma.

  • Hi Jens-Michael, thanks again for your help.  I've been fighting this issue for months and don't seem to be making any progress.

    If I call PMMIFG &= ~PMMLPM5IFG; before setting PMMREGOFF, it resets immediately.  If I can trust the debugger, it doesn't even get past this line to the LPM4 line.

    I also moved the XTnOFF line before setting PMMREGOFF but that didn't seem to make a difference.

    I also tried changing the clock settings.  I'm not sure I did it right, but this is what I added (before enabling interrupts):

    	UCSCTL4 &=  ~(SELM_7 | SELS_7);
    	UCSCTL4 |= (SELM__VLOCLK | SELS__VLOCLK);
    

    Is that all that I need?

    I am able to get it to stop, but as I mentioned, I don't believe it's in LPM4.5 mode, because the Vcore voltage does not drop.  Is this a valid assumption, that I should see the voltage on the Vcore pin drop when going into LPM4.5?

  • The very moment you set PMMREGOFF, you switch off the internal CPU power supply. Form this moment on, the CPU runs from the remaining charge in the 470nF cap on VCORE. Which will deplete with a rate of 2V/ms (@1mA current). You can imagine how fast the CPU won’t work anymore. If you single-step with the debugger over this instruction, the CPU is immediately dead and won’t proceed to the LPM4 instruction.
    After setting PMMREGOFF, the very next thing should be entering LPM4. With no disturbance, no interrupts in-between (clear GIE before initiating the sequence, it will be set with the LPM4 intrinsic anyway), no single-stepping, no breakpoints, nothing.

  • Hi, thanks for your reply.

    Sorry, I wasn't very clear in my last post.  I wasn't talking about stepping past the PMMREGOFF line, but the PMMIFG &= ~PMMLPM5IFG line.  If I have this line after shutting off the PMM REG, it has no effect, but if I have it executed earlier, it doesn't get past that line and doesn't reach the PMMREGOFF line.  

    The full code is below.  As it is shown here, the device resets immediately, and if I step through this function, it stops stepping at the PMMIFG &= ~PMMLPM5IFG line.  If I remove this line, the device stops running when this function is called, but Vcore doesn't drop.  Is there something wrong with the syntax of that line, or the register and flag used?  The header file has these defines:

    #define  PMMIFG_               (0x012Cu)  /* PMM Interrupt Flag */
    DEFCW(   PMMIFG              , PMMIFG_)

    #define PMMLPM5IFG          (0x8000u)  /* LPM5 indication Flag */


    Also, you mentioned that the LPM4 intrinsic is supposed to enable the interrupts, but if I don't enable the interrupts first, the device doesn't wake up when the interrupt pin is triggered.  So I'm not sure LPM4 is even being executed then, or it's not the right macro.  Do I need a bigger cap on Vcore, or maybe the 470nF I have is not connected properly?  (I can't imagine the device would work properly in run mode if it wasn't though.)

    void goToLPM4_5() {
        UCSCTL4 = SELA_1;
    
        //reset all GPIOs
        P1OUT = 0x00;P2OUT = 0x00;P3OUT = 0x00;P4OUT = 0x00;P5OUT = 0x00;P6OUT = 0x00;P7OUT = 0x00;PJOUT = 0x00;
        P1DIR = 0xFE;P2DIR = 0xFF;P3DIR = 0xFF;P4DIR = 0xFF;P5DIR = 0xFF;P6DIR = 0xFF;P7DIR = 0xFF;PJDIR = 0xFF;
    
        //enable Port1 interrupt
        P1IE |= (BIT4);
        //interrupt on falling edge
        P1IES |= (BIT4);
        //clear interrupt flag
        P1IFG &= ~(BIT4);
    
        //disable other interrupts to prevent it from waking up right after going to sleep
        P2IE = 0;
    	TA0CCTL0 = 0;		//no effect
    	TA1CCTL0 = 0;		//no effect
    	TA2CCTL0 = 0;		//drops Vcore voltage slightly
    
    	RTCCTL0 = 0;		//no effect
    		
    	//clear flags before enabling interrupts
    	TA0CTL = 0;			//clear interrupt flag		//no effect
    	TA1CTL = 0;			//clear interrupt flag		//no effect
    	TA2CTL = 0;			//clear interrupt flag		//no effect
    	TBCTL = 0;			//clear interrupt flag		//no effect
    
    	
    	PMMIFG &= ~PMMLPM5IFG;				//clear flag to allow wakeup from LPM4.5 - if this is done before PMMREGOFF, the MCU immediately resets
    
    	//change clock sources for SMCLK and ACLK to VLO
    	UCSCTL4 &=  ~(SELM_7 | SELS_7);
    	UCSCTL4 |= (SELM__VLOCLK | SELS__VLOCLK);
    
    	UCSCTL6 |= XT1OFF | XT2OFF;			//turn off oscillators		//no effect?
    	
        __enable_interrupt();
        
        //Enable LPM4.5 mode
        // Disable SVS
        PMMCTL0_H = PMMPW_H;                    // PMM Password
        SVSMHCTL &= ~(SVMHE+SVSHE);             // Disable High side SVS
        SVSMLCTL &= ~(SVMLE+SVSLE);             // Disable Low side SVS
    	
        //this turns off the PMM to allow for LPM4.5
        PMMCTL0_L |= PMMREGOFF;                   // set Flag to enter LPM4.5 with LPM4 request
    	
        //Enter LPM4.5 mode
        LPM4;
    } 

  • I figured out why LPM4 doesn't enable interrupts.  The macro for this (in msp430f5219.h) doesn't set the GIE bit.  Instead I'm now using the __low_power_mode_4() macro from intrinsics.h, which is the same as LPM4 but also sets the GIE bit.


    Now the device comes out of whatever state it's in when the pin interrupt is triggered, without having to enable the interrupts manually, but it still behaves the same way as I described before.  I.e. if I use the PMMIFG &= ~PMMLPM5IFG; line, it resets immediately.


    I even tried calling just that line alone, right from run mode with no other shutdown steps done, and this also causes an immediate reset.

  • Yes, the LPMx macros do not set GIE. Apparently it is assumed that interrupts have been already enabled. As it makes no sense going into LPM when GIE is clear, it should be added. And except if you want to shut down the device and have no ISRs executed too, it wouldn’t be a problem doing so.
    Adding GIE to the LPMx_exit macros, however may or may not be useful. In most cases, it won’t.

    I never used these macros myself, but it reminds me of the simple rule: know what you’re doing. This includes looking at macro definitions before using them :)

     About the reset: did you set the PMM password before writing to PMMIFG?

  • No!  Thank you for reminding me.  I forgot that this is needed to unlock all PMM registers, not only the SVS ones.  I will try this, but I'm encouraged this will work.


    Do I need to lock and unlock the registers between clearing the flag and setting PMMREGOFF?  Or can I just unlock once and do all the final steps?

    Thanks again.

  • Unfortunately that didn't help.  Vcore is still 1.92V.  These are now the final statements before going to LPM4.5:

    PMMCTL0_H = PMMPW_H;                	// PMM Password
    SVSMHCTL &= ~(SVMHE+SVSHE);         	// Disable High side SVS
    SVSMLCTL &= ~(SVMLE+SVSLE);         	// Disable Low side SVS
    
    PMMIFG &= ~PMMLPM5IFG;			//clear flag to allow wakeup from LPM4.5
    
    //this turns off the PMM to allow for LPM4.5
    PMMCTL0_L |= PMMREGOFF;                   // set Flag to enter LPM4.5 with LPM4 request
    
    __low_power_mode_4();

  • I loaded the project code that comes with the http://www.ti.com/lit/an/slaa424/slaa424.pdf app note onto the device.  I made a few minor changes to remap the I/O used in the project to the LEDs and buttons on my board, but otherwise it is unchanged.  The project does seem to allow the board to go into low power mode (I can see the Vcore voltage drop on the oscilloscope), but it quickly (after about 10ms) returns to run mode.  This might have something to do with the changes I made, but at least the Vcore drops, which I don't see happening with the SPPLE project.

        With the SPPLE project, the voltage stays high at the time that it should be going to low power mode.  I have tried turning off timers, and all other peripherals, and cleared flags, but I still can't seem to get it to work.  I'm not sure if I'm not stopping peripherals in the correct way, or if there is some other step that I'm not preforming correctly (or at all).

  • I’m not sure whether it makes a difference, but in a different thread, we just discovered that LMP4 macro does not set the GIE bit. It could make a difference. Maybe your macro does not too. (or does, while it shouldn’t ?)

    Try an explicit __bis_SR_register(LPM4_bits|GIE);

    Well, Vcore of 1.92V seems a bit high even for normal operation. Did you raise core voltage previously? On default PMMCOREV=0 (for up to 8MHz operation) it should be ~1.4V

     And, well, AFAIK, it is sufficient to unlock the PMM once. IIRC, the only unlock that times out is that of the port mapping controller.

    When the new (apparently partly working) code enters LPM and then exits it again, it might be that it is triggered by an active interrupt and starts up again. Check all your interrupt sources.

  • Hi Jens-Michael,

      Actually it was in this thread that I figured out about the LPM4 macro.

      The 1.92V is apparently being set by the standard Bluetopia SPPLE project code.  When I run the LPM4_5 example project provided for SLAA424, the voltage runs at about 1.4V.


      But the example project wakes up again immediately, even when I disable the button interrupt to wake it up.  This is very simple code.  No extra timers or peripherals are enabled.  Currently I only enable one button interrupt to put it to sleep, and before going to sleep that interrupt is disabled.  The Vcore voltage drops to zero for a short time, (it varies between 1-4ms), and then comes back on.

      This behavior I described was observed on a custom board as well as the MSP-EXP430F5529 board.  I again remapped the I/O used in the project to the buttons and LEDs on the dev board and I see the exact same behavior.  Pressing the button causes the LED to turn on Vcore to drop for ~2ms, and then Vcore goes back up to 1.4V and the LED turns off again.  This happens whether the interrupt for the 'wake up' button is enabled or disabled.

      I just now figured out that the programmer connection was causing it to come out of reset.  The "Release JTAG on Go" option described in the App note is not available to me, perhaps because I'm using Spy-Bi-Wire.  But if I disconnect the programmer connection, the chip stays in LP mode!  So I know the hardware is fine for both the EXP board and my custom board, and that there is just something missing in my SPPLE project.

      When I program the modified SPPLE into the device and remove the programmer, it doesn't go to LPM mode, not even for the brief ~1ms time that the other project does.  So it seems to me there is still some interrupt preventing it from going to LPM.  I tried to disable the interrupts (as mentioned above), but apparently there is something else enabled  that I missed or am not aware of.

  • Can you check SYSRSTIV value after it comes up again? Maybe something caused a reset and then the MSP is simply rebooting. What about the watchdog?
    Is (in this partly working code) the SVS (low side) disabled? Else it might trigger a POR.
    If switching the MSP off has an impact on the supply, a fast rising VCC (transient) may also trigger a BOR under some circumstances.

    The 1.92V are required for maximum CPU speed operation (PMMCOREV=3) while for up to 8MHz operation, only 1.4V are required (PMMCOREV=0, default)

  • Hi Jens-Michael,

    I included this switch statement copied from the LPM4.5 example project:

       switch (__even_in_range(SYSRSTIV,SYSRSTIV_PMMKEY))

    and it appears the value is 0 (no interrupt pending). Would that make sense considering I used a port interrupt to wake it up? It appears the code is working since if I cycle power I get a brownout reset (2).

    As for SVS, (I believe) I'm disabling the low side SVS and SVM like this before entering LPM:

       SVSMLCTL &= ~(SVMLE+SVSLE); // Disable Low side SVS

    Also I turned off the watchdog timer before going to LPM to be sure, but there was no change.

  • Port interrupt or not, once LPMx.5 was entered, the CPU runs through its startup code after wakeup, so SYSRSTIV should contain 0x08 on first read (wakeup from LPMx.5).
    However, IIRC, the C startup code of the latest CCS(?) reads the register and places its value somewhere else. Since the value is erased by the readout, the register will likely show 0 then. I can’t remember at which place this info is stored by the startup code. Some linker-generated symbol. Maybe you can discover when you take a look at the symbol list in the map file (needs to be enable din the linker setting)
    If, however, SYSRSTIV really doesn’t contain 0x08 after waking up, then you never entered LPMx.5 at all.

  • Hi Jens-Michael,

      Would this apply only when the debugger is connected?  I'm using IAR, and I did find having the programmer connected caused it to come out of reset, so I've been mainly testing with that disconnected.  I have it blinking an LED a certain number of times based on the SYSRSTIV value on power-up.  I only ever see it show the SYSRSTIV_BOR flag.

    Angelo

  • If the debugger software is attached, LPMs are mostly limited to LPM0. However, the reading of SYSRSTIV in the said startup code happens independently of debugger or not. (and when I read about it, I doubted the relevance of doing it). I don’t remember whether it was CCS or IAR. And which compiler version. Maybe a forum search for SYSRSTIF reveals the thread.

    Nevertheless, SYSRSTIV_BOR should only appear once, after power-up. Once read, the flag is gone. Subsequent reads when returning from LPMx.5 shouldn’t show it. Unless supply voltage did fall below brownout level.
    Note that the SYSRSTIV register will show multiple values if since last readout multiple resets (due to different reset reasons) happened. So if after power-up another reset happens (like access violation or vacant memory fetch) before you read SYSRSTIF, you’ll see all of them appearing one after another in SYSRSTIV. Each time the one with the highest priority that you didn’t read so far.

  • I have the device blinking each SYSRSTIV value it gets from repeated executions of:

            switch (__even_in_range(SYSRSTIV,SYSRSTIV_PMMKEY))

    On the first time powering up, it shows me that the case SYSRSTIV_BOR was found, and no others.  After executing the goToLPM4_5() function which should put it into LPM4.5 mode, and then triggering the interrupt, I get the SYSRSTIV_NONE case immediately, with no other case matching.  I didn't think this was possible (to have no identified wakeup cause).

    But I still think the main issue is that it's not properly going into LPM4.5.  The wake up works, with the only exception being that the clock seems to be running about 100 times slower after reset.

**Attention** This is a public forum