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.

EVM430-FR6989: Micro doesn't enter in LPM3

Part Number: EVM430-FR6989
Other Parts Discussed in Thread: MSP430FR6989, UNIFLASH

Dear MSP forum,

I'm having some problems with the Low Power Mode (LPM). I have EVM430FR6989 and I started my code with the base of FLOWESI GUI. I know that code depends on the features you tick on the GUI, but the main in the same one more less.

void main(void) {
	boardConfig();	


	esiConfig();
	startTimer();


	while(1){
		__bis_SR_register(LPM0_bits+GIE);

		serviceInterrupts();
	}

}

Originally the code is in LPM0, witch consumes on standby around 3mA, so I started editing the code and following the workshop i changed to __bis_SR_register(LPM3_bits+GIE); and activate the ULP Advisor and the board still consumes ~3mA. I have also deactivated the LCD to reduce power consumed.

Is there anything else I should check? Something in CCS that it's not enable? I've also tried with __low_power_mode_3(); and nothing works.

Thank you in advance

Best regards

Samuel

  • Hi Samuel,

    A simple way to help isolate the problem is in your main() do the following:

    // 1.  Disable WDT

     WDTCTL = WDTPW | WDTHOLD;

    // 2.  Configure all IO pins as outputs and set them = 0

    I'll let you figure out how to do that...

    // 3. enter LPM3 mode with interrupts disabled.

    __bis_SR_register(LPM3_bits);

    This will get you very close to the minimal current, ~ a few uA, however, if you are doing this with the debugger running you will still see about 15uA so measure the current with debugger disabled.

    Let me know what you see and we will go from there.

  • A clock request from a peripheral for SMCLK will cause you to end up in LMP1 when requesting LPM3.

  • Hi David,

    Yes, excellent point and something Samuel will need to consider.  My suggestion was to help Samuel achieve a very low current as a benchmark, then slowly start putting his code in place to see what causes the current goes up.

  • Hi Dennis and David,

    I've already had that suggestions in the code (FLOWESI GUI generates it), but nothing works. I wanted to start from 0 and I'm checking the examples of the workshop:

    lab_07b_lpm_timer_solution_msp430fr6989 --> Power consumption around 335 uA (uses LPM3), I think is not enough low.

    lab_07c_initPorts_solution_msp430fr6989 --> Power consumption rises to ~3mA when reach the instruction PMM_unlockLPM5();

    I've checked it to my original script and the same happens, after I/O configured I use this instruction because I hear in the workshop that FR family needs to and then power consumption rises 3.1 mA.

    Anything for this? I thought PMM_unlockLPM5(); was mandatory for FR6989.

    Best regards

    Samuel

  • Hi Samuel,

    If you followed my example above and still see high currents, then one of the GPIO pins is causing the issue.  Take a look at the schematic for this board and see if there is a GPIO pin that has a pullup resistor connected to it.  If so, you want to set that GPIO as an input, else you will consume excessive current.

  • Hi Dennis,

    Thank you for your reply, the I2C pull up resistor was the reason, now I'm getting consumptions of 8 uA, but I still can't achieve that 0.4 uA of the datasheet.

  • Hi Samuel,

    8uA is still high, which tells me you have another GPIO pin with a 500k ohm load pulled to VCC, or you have a clock running.  Are there any other devices connected to this MSP430 that might have their GPIO pins connected?

    BTW, how are you measuring the MSP430 current? Current directly into the VCC pin?

    Are you using the ACLK during LPM3, ie. running one of the timers, and if so, what is the source of your ACLK? VLO or 32Khz LFXT?

    I also see in the datasheet a footnote (9) that indicates the RTC is disabled and SVSHE = 0.  Is this true for your setup?

  • Hi Dennis,

    I don't see any 500k ohm on EVM430FR6989.

    I'm measuring the consumption with an OTII power analyzer so I can see current consumption while debugging. It's just connected with the board to VCC and GND.

    ACLK is with 32KHz, don't know exactly how to see if SVSHE = 0, is it applied automatically when you put LPM3?

    My code is the one generated by FLOWESI GUI, I've only changed something with clock wise and anticlockwise interrupts for giving output pulses on pins (I did it on the esiConfig.C as a demo, no worries about it) and set LPM3, I give you my main, maybe you see something wrong that I can't.

    #include "main.h"
    
    // Function Prototypes
    void boardConfig(void);
    void clockSystemConfig(void);
    void lcdInit(void);
    void portConfig(void);
    void serviceInterrupts(void);
    void timerConfig(void);
    void startTimer(void);
    
    
    // Global user defined flags
    extern uint8_t gRecalFlag;
    uint16_t gRecalCounter=TIME_TO_RECAL_REPEAT;
    extern uint8_t gESIStatusFlag;
    
    char Power_measure = 0;
    
    //*****************************************************************************
    //
    //! FlowMeter Low-Level Initialization
    //! _system_pre_init(void)
    //! This function runs before main() and before globals are initialized in RAM
    //! Currently used to halt the watchdog, as the watchdog might time out during
    //! global initialization
    //
    //! \param none
    //
    //! \return 1 to init RAM, 0 to skip RAM init
    //
    //*****************************************************************************
    int _system_pre_init(void)
    {
        //
    	// Disable Watchdog Timer Here
    	// Prevents Timeout During C Init
    	//
        WDT_A_hold(WDT_A_BASE);
    
        //
        // Return 1 (to init segments)
        //
        return 1;
    }
    
    
    
    void main(void) {
    
    /*
        // Stop watchdog timer
        WDT_A_hold( WDT_A_BASE );
    */
    
    	boardConfig();	
    	esiConfig();
    	startTimer();
    
    
    	while(1){
    
    	    __bis_SR_register(LPM3_bits+GIE);
    		serviceInterrupts();
    	}
    
    }
    
    void boardConfig(void){
    	portConfig();
    	clockSystemConfig();
    	timerConfig();
    
    	P1OUT |= BIT6 + BIT7;                // for I2C pull up. For measuring current consumption, remove the physical I2C cable.
    	//lcdInit();
    
    }
    
    void portConfig(void){
    	// Configure all Ports as output and drive all pins low
    	GPIO_setAsOutputPin(GPIO_PORT_P1,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
        /////////Añadido para apagar LCD con botón
    
        P1IES |= BIT2;                              // Set P1.2 as key input
        P1IFG &= ~BIT2;                             // User can press the black button to toggle switch on/off the LCD
        P1IE  |= BIT2;
    
        //////////////////////////////////
    
        //P1DIR &= ~BIT2;
       // P1REN |= BIT2;
       // P1OUT |= BIT2;
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P1,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_P2,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P2,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_P3,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P3,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_P4,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P4,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_P5,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P5,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_P6,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P6,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    
    	GPIO_setAsOutputPin(GPIO_PORT_P7,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P7,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    
    	GPIO_setAsOutputPin(GPIO_PORT_P8,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P8,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    
    	GPIO_setAsOutputPin(GPIO_PORT_P9,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P9,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_P10,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_P10,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setAsOutputPin(GPIO_PORT_PJ,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    	GPIO_setOutputLowOnPin(GPIO_PORT_PJ,
    						GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3 |
    						GPIO_PIN4 | GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7 );
    
    
    	// Set LFXT (low freq crystal pins) to crystal input (rather than GPIO)
        // Since HFXT is not used, we don't need to set these pins. But for the
        // record, they are:
        //              GPIO_PIN6                            // HFXTIN on PJ.6
        //              GPIO_PIN7                            // HFXOUT on PJ.7
    
    	GPIO_setAsPeripheralModuleFunctionInputPin(
    			GPIO_PORT_PJ,
    			GPIO_PIN4 | GPIO_PIN5,                      // LFXIN  on PJ.4, LFXOUT on PJ.5
    			GPIO_PRIMARY_MODULE_FUNCTION
    	);
    
    	//GPIO_setOutputHighOnPin(RECAL_LED_PORT, RECAL_LED_PIN);
    
    	PMM_unlockLPM5();
    
    
    }
    
    void clockSystemConfig(void){
    
    	// Set DCO Frequency to 8 MHz
    	CS_setDCOFreq(CS_DCORSEL_0, CS_DCOFSEL_6);
    
    	//configure MCLK = 8MHz, SMCLK=2MHz to be source by DCOCLK
    	CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);
    	CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
    
    	// ACLK Clock configuration
    
        //Set external clock frequency to ACLK frequency
    	CS_setExternalClockSource(32768,0);
    
    	CS_initClockSignal(CS_ACLK,CS_LFXTCLK_SELECT,CS_CLOCK_DIVIDER_1);
    	CS_turnOnLFXT(CS_LFXT_DRIVE_3);
    
    	// Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
    
        PMM_unlockLPM5();
    }
    
    void timerConfig(void){                          // This is the timer for triggering the run time re-calibration
    		gRecalCounter = TIME_TO_RECAL_REPEAT;    // 2 sec is set for demonstration purpose. The actual timer setting depends on the application.
    
    	Timer_A_initUpModeParam upParams = 
    	{
    		TIMER_RECALIBRATION_CLK_SOURCE,
    		TIMER_A_CLOCKSOURCE_DIVIDER_8,
    		TIME_TO_RECAL,
    		TIMER_A_TAIE_INTERRUPT_DISABLE,
    		TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,
    		TIMER_A_DO_CLEAR,
    		false
    	};
    
    	Timer_A_initUpMode(TIMER_RECALIBRATION_SELECTION, &upParams);
    
    }
    
    void startTimer(void){
    	Timer_A_startCounter(TIMER_RECALIBRATION_SELECTION,
    			TIMER_A_UP_MODE);
    }
    
    
    void lcdInit(void){
    	init_LCD();
    	lcd_display_num(0,1);
    }
    
    
    
    void serviceInterrupts(void){
    	if(gRecalFlag&PERIODIC_AFE2_RECALIBRATION){
    		GPIO_setOutputLowOnPin(RECAL_LED_PORT, RECAL_LED_PIN);
    		gRecalFlag &= ~PERIODIC_AFE2_RECALIBRATION;
    		Timer_A_setCompareValue(TIMER_RECALIBRATION_SELECTION,
    			TIMER_A_CAPTURECOMPARE_REGISTER_0,
    			RECAL_TIME_OUT);
    		Timer_A_startCounter(TIMER_RECALIBRATION_SELECTION,TIMER_A_UP_MODE);
    		ReCalScanIF();
    		gRecalCounter = TIME_TO_RECAL_REPEAT;
    
    	Timer_A_initUpModeParam upParams = 
    	{
    		TIMER_RECALIBRATION_CLK_SOURCE,
    		TIMER_A_CLOCKSOURCE_DIVIDER_8,
    		TIME_TO_RECAL,
    		TIMER_A_TAIE_INTERRUPT_DISABLE,
    		TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE,
    		TIMER_A_DO_CLEAR,
    		true
    	};
    
    	Timer_A_initUpMode(TIMER_RECALIBRATION_SELECTION,
    			&upParams);
    
    		__bic_SR_register(GIE);
    		gRecalCounter = TIME_TO_RECAL_REPEAT;
    		ESI_clearInterrupt(ESI_INTERRUPT_FLAG_Q6_BIT_SET);
    		ESI_enableInterrupt(ESI_INTERRUPT_Q6_BIT_SET);
    		GPIO_setOutputHighOnPin(RECAL_LED_PORT, RECAL_LED_PIN);
    	}
    	__no_operation();
    	/*
    	__bis_SR_register(LPM3_bits);
    	__delay_cycles(1);
    	*/
    }
    
    #pragma vector = RECALIBRATION_TIMER_VECTOR_0
    __interrupt void Recalibration_ISR (void){
    	    if (gRecalFlag & PERIODIC_AFE2_RECALIBRATION){
    		gRecalFlag |= RECALIBRATION_TIMEOUT;
    		// Prevent entering ESI ISR to call an extra
    		// "__low_power_mode_off_on_exit()"
    		ESI_disableInterrupt(ESI_INTERRUPT_ESISTOP | ESI_INTERRUPT_Q6_BIT_SET);
    		__low_power_mode_off_on_exit();
    	    } else {
                gRecalCounter--;
                if(gRecalCounter==0){
                    gRecalFlag |= PERIODIC_AFE2_RECALIBRATION;
                    Timer_A_stop(TIMER_RECALIBRATION_SELECTION);
                }
    	    }
    
    	    /*
    	    _bic_SR_register_on_exit(LPM3_bits); // Añadido
    	    */
    }
    
    
    /////////////////////// Añadido para apagar LCD con boton
    // Port 1 interrupt service routine for push button of the main board
    #pragma vector=PORT1_VECTOR
    __interrupt void PORT1_ISR(void){
    
        P1IFG &= ~BIT2;
        Power_measure ^= BIT0;
    
        if (Power_measure & BIT0) {
            LCDCCTL0 &= ~LCDON;
            ESIINT1 &= ~ESIIE5;       // disable INT of Q6
            TA0CTL &= ~MC0;           // stop the re-calibartion timer
        } else{
            LCDCCTL0 |= LCDON;
            ESIINT1 |= ESIIE5;        // enable INT of Q6
            TA0CTL |= MC0;            // turn on re-calibration timer
        }
    
       //_low_power_mode_off_on_exit();
       //_bic_SR_register_on_exit(LPM3_bits); // Añadido
    }
    ////////////////////////////////////////
    

    Best regards 

    Samuel

  • Hi Samuel,

    You are measuring current while debugging?  What happens if you exit debug mode (cycle power), then measure current?

  • Hi Dennis,

    Well, I've stopped doing that, now I've just flashed the program with Uniflash and use the power analyzer for power it up and measure the consumption, it's around 6.7 uA with the main in the upper reply.

    Best regards

    Samuel

**Attention** This is a public forum