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.

MSP430FR5994: LPM3 drawing more than calculated current.

Part Number: MSP430FR5994

I did a comparison between our board and the demo board with different pin configurations. Current measurements are with a martel3001

I loaded the my board's fw on the TI demo board, as a sanity check, and it draws .0240ma -vs- .4009ma on the real card for the same software, full initialization of pins / modules for our custom board done.

FW for Custom pin initialization only, the demo board draws 0.0021ma –vs—0x2715ma on the real card. ().

 TI’s reference for the spec (with the custom sleep function to enable voltage shutdowns). the demo board draws 0.0010 –vs  4.237ma on the real card (not valid as all the  pins are set to logic 0 output and it seems that our card is not happy).

I’ve tried to reconfigure the SPI/UART/i2c pins to “park” them but have not seen any measurable difference, disabled modules/clocks/analog etc .. without a reduction.

Is there any advice for further current reduction? Where is the difference coming from?

*none of the pins are connected to anything on the TI Demo board .

I've attached the modified test code.

testmain.c
//***************************************************************************************
//  MSP430 Blink the LED Demo - Software Toggle P1.0
//
//  Description; Toggle P1.0 by xor'ing P1.0 inside of a software loop.
//  ACLK = n/a, MCLK = SMCLK = default DCO
//
//                MSP430x5xx
//             -----------------
//         /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//            |             P1.0|-->LED
//
//  Texas Instruments, Inc
//  July 2013
//***************************************************************************************
// forward declaration
/*Only use this for the BSL proper*/
static void config_port_pins(void);
void msp430_init(int isbsl);
void inittimer(void);
void delayus(unsigned int delayamt);
void delayms(unsigned int delayamt);
#define TEST_LPM_MODE LPM3_bits
#define DO_WAKE 0

#include <msp430.h>
#include <stdint.h>
#include <cs.h>
#if 0
#define TEST_LPM_MODE LPM3_bits

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
    //PM5CTL0 &= ~LOCKLPM5;
    msp430_init(0);
    inittimer();

    do{
#if DO_WAKE
        delayus(100000);    /* Sleep! */
#else
        __bis_SR_register(TEST_LPM_MODE | GIE);       // Go to sleep -- should be here forever

#endif
    }while(1);

}

#else


void sleep_handler(void);
/**
 * main.c
 */
int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    // enable interface level shifters, "zero bits" 3.4 to enable VCC3V_BAT & 3.7 to release ZYNC reset
    //P3OUT |= (PS_MON_SHDN | ZTEMP_SHDN );
    // Set HIGH
    msp430_init(0); // 1 is test example config  -- .0574mA under debug -- ??? without debugger attached
    //msp430_init(1); // Cogs runtime              -- .1391mA under debug .2780 without debug

    //LPM3;    /* Sleep! */

    /* Unreached.  If this code were reached, the LED would stay
     * continuously lit. */
    inittimer();

    do{
#if DO_WAKE
        delayus(0xFFFF);    /* Sleep! */
#endif
    //P4OUT &= ~(BIT1);
    sleep_handler();
    }while(1);

    return 0;
}
#endif

#define PS_MON_SHDN     BIT0
#define UART_LV_SHDN    BIT2    // Port J
#define DEBUG_SHDN      BIT3    // Port J
#define ZTEMP_SHDN      BIT3
#define BATT_SHDN       BIT4
#define ZYNC_RESET      BIT7
void sleep_handler(void)
{
    uint8_t p3Bits;
    p3Bits = P3OUT;
    p3Bits &= ~(ZTEMP_SHDN  | PS_MON_SHDN ); // disable level shifters
    p3Bits |= (ZYNC_RESET | BATT_SHDN ); // assert ZYNC reset, disable VCC3C_BAT
    P3OUT = p3Bits;
    PJOUT &= ~(UART_LV_SHDN);



    /* enter LPM3 (use macro) */
#if DO_WAKE
    delayus(0xFFFF);    /* Sleep! */
#else
    PM5CTL0 &= ~LOCKLPM5;
    CS_turnOffSMCLK();
    __bis_SR_register(TEST_LPM_MODE | GIE);       // Go to sleep -- should be here forever
#endif
    /* we stay right here until we exit from LPM3 */

    /* WAKEUP - execution will (now) return to receiveByte_UART() */
    p3Bits = P3OUT;
    p3Bits |= (ZTEMP_SHDN  | PS_MON_SHDN); // enable level shifters
    p3Bits &= ~(ZYNC_RESET | BATT_SHDN| BATT_SHDN); // assert ZYNC reset, disable VCC3C_BAT
    P3OUT = p3Bits;
    //PJOUT &= (UART_LV_SHDN);
}


static void config_port_pins(void){

  /* I/O Pin configuration section (setting all relevant bits):
   * this section has been optimized by setting all of the bits in
   * each PxSEL0 / PxSEL1 / PxDIR register with single writes -
   * but we are maintaining the code for doing it explicitly to
   * validate the "correctness" of each pin setting
   */

  /* PORT P1 */
  /* Configure P1.0 as Analog Input (A0) for BAT_DETECT*/
  /* Configure P1.1 as Analog Input (A1) for 12v_DETECT*/
  /* Configure P1.2 as Analog Input (A2) for PCIe 12v_DETECT*/
  /* Configure P1.3 as Analog Input (A2) for PCIe 3.3v_DETECT*/
  /* Configure P1.4 as Digital Input for ACC_INT2 */
  /* Configure P1.5 as Digital Input for ACC_INNT1 */
  /* Configure P1.6 & P1.7 as I2C (UCB0) for LCS_I2C_SDA / LSC_I2C_SCL */
#if 0 // .0552 on
    P1OUT = 0;
    P1DIR = 0xFF;
#else
    P1SEL0 = (BIT0 | BIT1 | BIT2 | BIT3);
    P1SEL1 = (BIT0 | BIT1 | BIT2 | BIT3 | BIT6 | BIT7);
    P1DIR = (0xFF & ~(BIT4 | BIT5));
#endif

  /* PORT P2 */
  /* Configure P2.0 & P2.1 as UART (USCIA0) for MSP_TXD / MSP_RXD */
  /* P2.2 not presently used  - configure as Digital Input */
  /* Configure P2.3 as SPI_CS (GPIO Output) */
  /* Configure P2.4, P2.5 & P2.6 as SPI (UCA1) SPI_CLK1_SCL / SPI_MOSI1_SDA / SPI_MISO1 */
  /* Configure P2.7 as Digital Input for PCIE_SLOTDET */
#if 0
    P2OUT = 0;
    P2DIR = 0xFF;
#else
    P2SEL0 = 0;
    P2SEL1 = (BIT0 | BIT1 | BIT4 | BIT5 | BIT6);
    P2DIR = (0xFF & ~(BIT2 | BIT7));
    P2OUT = BIT3;
#endif
  /* PORT P3 */
  /* Configure P3.0 as Digital Output for PS_MON_SHDN- */
  /* Configure P3.1 as Digital Output for UART_LV_SHDN- HW_REV_1  --- as Digital Output for MODE - HW_REV_2*/
  /* Configure P3.2 as Digital Output for DEBUG_SHDN- HW_REV_1    --- as Digital Output for PROVISION- HW_REV_2*/
  /* Configure P3.3 as Digital Output for ZTEMP_SHDN- */
  /* Configure P3.4 as Digital Output for 3V_BARR_SHDN- */
  /* Configure P3.5 as Digital Input for LC2_INT0 */
  /* Configure P3.6 as Digital Output for ZYNC_CLR_BAT HW_REV_1  --- as Digital Input for TMP108_INT HW_REV_2*/
  /* Configure P3.7 as Digital Output for ZYNC_RESET */
  P3SELC = 0;
  P3IES = 0;
  P3DIR = (0xFF & ~(BIT5 | BIT6 ));
  //P3OUT = ((provisioned == 0x42)? BIT2:0); //signal BSLMODE and keep provisioned status.
  //P3OUT |= (provisioned == 0x42)? BIT1:0 ; // if provisioned
  P3OUT &=  ~(BIT2 | BIT3 | BIT4 | BIT7); // BSL mode
  /* PORT P4 */
  /* Configure P4.0 as Digital Output for LCS_EN0 */
  /* Configure P4.1 as Digital Output for LCS_EN1 */
  /* Configure P4.2 as Digital Output for LCS_EN2 */
  /* Configure P4.3 as Digital Input for UCD_ALERT_MSP (and configure as wake-up interrupt for falling edge UCD_ALERT) */
  /* Configure P4.4 as Digital Input for PWR_FAULT_MSP */
  /* Configure P4.5 as Digital Input for LCS_INT1 */
  /* Configure P4.6 as Digital Input for LCS_INT2 */
  /* Configure P4.7 as Digital Input for MAX20734_SMALERT_MSP */
  P4SELC = 0;
  P4DIR = (BIT0 | BIT1 | BIT2);
  P4OUT = 0x00;
  // enable pull-downs for FLEX_TOP & FLEX_BOTTOM shields
  P4REN |= (BIT5 | BIT6);
  P4OUT &= ~(BIT5 | BIT6);

  /* PORT 5 */
  /* Configure P5.0 as I2C (UCB1) for MON_SDA_MSP */
  /* Configure P5.1 as I2C (UCB1) for MON_SCL_MSP */
  /* Configure P5.2 as Digital Input for PWR_PG   */
  /* Configure P5.3 as digital input for PWR_STAT */
  /* Configure P5.4 as Uart (USCIA2) for MSP430_CONSOLE_TXD */
  /* Configure P5.5 as Uart (USCIA2) for SP430_CONSOLE_RXD */
  /* Configure P5.6 as digital input  for ZYNQ_ALERT- */
  /* Configure P5.7 as digital input  for ZYNQ_OVERT- */
  P5SEL0 = (BIT0 | BIT1 | BIT4 | BIT5);
  P5SEL1 = 0;
  P5DIR = (0xFF & ~(BIT2 | BIT3 | BIT6 | BIT7));
  P5OUT = 0;

  /* PORT P6 -- not populated on 54 pin part
  P6SELC = 0;
  P6DIR = 0;
  P6OUT = 0;
  */
  /* PORT 7 */
  /* Configure P7.0 & P7.1 as I2C (UCB2) for PWR_SDA / PWR_SCL */
  /* Configure P7.2 as Digital Input for WDI_INOUT_MSP or MAX20734_STAT or  VCC0V85_PG_MSP*/
  /* Configure P7.3 as Digital Output for PWR_OTG */
  /* Configure P7.4 as Digital Output for PWR_CE- */
  P7SEL0 = (BIT0 | BIT1);
  P7SEL1 = 0;
  P7DIR = (BIT3 | BIT4);
  P7OUT = (BIT3 | BIT4);

  /* PORT P8 */
  /* Configure P8.0 as Digital Input for PWR_INT */
  P8SELC = 0;
  P8DIR = 0;

  /* PORT PJ - reset all port pins (high impedance) GPIO outputs (ULP 4.1) */
  /* Configure Pj.0  CLR_ZYNQ_BAT  */
  /* Configure Pj.1  Not Connected  */
  /* Configure Pj.2  UART_LVL_SHUTDN  */
  /* Configure Pj.3  DEBUG_SHDN */
  /* Configure Pj.4  LFXIN  32.7Khz */
  /* Configure Pj.5  LFXOUT 32.7Khz*/
  /* Configure Pj.6  HFXIN  24Mhz */
  /* Configure Pj.7  HFXOUT 24Mhz*/

  PJOUT=0;
  PJSELC = 0;
  PJSEL0 = BIT4 | BIT5 | BIT6 | BIT7;     // Initialize LFXT & HFXT pins
  PJSELC &= (~BIT0 | BIT1 | BIT2 | BIT3);  // GPIO
  PJDIR |= ( BIT0 | BIT1 | BIT2 | BIT3);   // Outputs

#if 0 // for debug
  PJSEL0 |= BIT0;            // BIT0 = output SMCLK on PJ.0, else GPIO output for debug
  PJDIR |= BIT0;
#endif

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

void lowest_pin_setting(){
    // Configure GPIO
#if 1
    P1OUT = 0;
    P1DIR = 0xFF;
#else
    P1SEL0 = (BIT0 | BIT1 | BIT2 | BIT3);
    P1SEL1 = (BIT0 | BIT1 | BIT2 | BIT3 | BIT6 | BIT7);
    P1DIR = (0xFF & ~(BIT4 | BIT5));
#endif
    P2OUT = 0;
    P2DIR = 0xFF;

    P3OUT = 0;
    P3DIR = 0xFF;
    P3OUT |= (ZYNC_RESET );

    P4OUT = 0;
    P4DIR = 0xFF;

    P5OUT = 0;
    P5DIR = 0xFF;

    P6OUT = 0;
    P6DIR = 0xFF;

    P7OUT = 0;
    P7DIR = 0xFF;

    P8DIR = 0xFF;
    P8OUT = 0;

    PJOUT = 0;
    PJOUT=0;
    PJSELC = 0;
    PJSEL0 = BIT4 | BIT5 | BIT6 | BIT7;     // Initialize LFXT & HFXT pins
    PJDIR=0xFFFF;
    /* Disable the GPIO power-on default high-impedance mode / activate configured port settings */
    PM5CTL0 &= ~LOCKLPM5;
}



void msp430_init(int isbsl){
  /* The I/O config is normally handled by the bootloader, so in the
   * normal (release build of the) app, all we need do here is
   * to reset the clock frequency to 16MHz and setup the FRAM controller
   * in the DEBUG version the pins need to be configured.
   */
  if(isbsl)
  config_port_pins();
  else
   lowest_pin_setting();

  /* This needs to be checked against
   *http://dev.ti.com/tirex/explore/node?node=ALMKUpgS2sr.Sf-qEyGcAQ__IOGqZri__LATEST
   *and
   * https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/609971?MSP430FR5994-Can-t-get-system-to-work-on-16-MHz
   */
#if 1
  /*Set DCO frequency to 16MHz */
  CS_setDCOFreq(CS_DCORSEL_1, CS_DCOFSEL_4);

  /* select DCO as SMCLK source */
  CS_initClockSignal(CS_SMCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);

  /* select DCO as MCLK source */
  CS_initClockSignal(CS_MCLK,CS_DCOCLK_SELECT,CS_CLOCK_DIVIDER_1);
#endif
#if 0
  /*Set FRAM wait state to 1 */
  FRAMCtl_A_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);
  FRAMCtl_A_clearInterrupt(0x00FF);
#endif
#if 1
  // Configure LFXT 32kHz crystal
  CSCTL0_H = CSKEY_H;                     // Unlock CS registers
  CSCTL4 &= ~LFXTOFF;                     // Enable LFXT
  CSCTL4 |= VLOOFF;
  do
  {
    CSCTL5 &= ~LFXTOFFG;                  // Clear LFXT fault flag
    SFRIFG1 &= ~OFIFG;
  } while (SFRIFG1 & OFIFG);              // Test oscillator fault flag
  CSCTL0_H = 0;                           // Lock CS registers
  /* select LFXT as ACLK source */
  CS_initClockSignal(CS_ACLK,CS_LFXTCLK_SELECT,CS_CLOCK_DIVIDER_1);
#endif
}


void inittimer(void){
    // Initialize Timer0 for a replacement of __delay_cycles once interrupts are enabled
    TA0EX0 = 0x0001; // Divide by 2
    TA0CTL = TASSEL_2 + MC_0 + TACLR + ID_3; // SMCLK, count up to TA0CCR0, Timer clear, Divide by 8
    TA0CCTL0 = CCIE; // TACCR0 interrupt enabled but no effect until Timer0 is running
    __bis_SR_register(GIE); // Enable all interrupts

}
void delayus(unsigned int delayamt)
{

    // Delay is 0-65535 usec; already initialized to use SMCLK, divide by 16 so timer increments once/usec; upon reaching delayamt, one interrupt is given and the delay is over
        TA0CCR0 = delayamt;                     // Interrupt when up-count to this value
        TA0CTL |= (MC_1 | TACLR);
      __bis_SR_register(TEST_LPM_MODE | GIE);       // Go to sleep. Timer0 ISR will wake us up when proper time has elapsed
}
void delayms(unsigned int delayamt)
{

    // Delay is 0-65535 usec; already initialized to use SMCLK, divide by 16 so timer increments once/usec; upon reaching delayamt, one interrupt is given and the delay is over
        TA0CCR0 = 100;                     // Interrupt when up-count to this value
        TA0CTL |= (MC_1 | TACLR);
        while(delayamt > 0){
      __bis_SR_register(TEST_LPM_MODE | GIE);       // Go to sleep. Timer0 ISR will wake us up when proper time has elapsed
        delayamt--;
        }
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
    TA0CTL |= MC_0;                             // Stop Timer0
    // __bic_SR_register_on_exit(LPM0_bits);       // Wakeup from LPM0 and continue after the Delayus function
     __bic_SR_register_on_exit(TEST_LPM_MODE);       // Wakeup from LPM0 and continue after the Delayus function
}

  • The Launchpads don't provide anything "special" to lower power. I routinely get the same results with a breakout board with nothing but the MCU (and a few passives) on it.

    Is it possible your pin configuration is setting up a bus conflict on your board? If you can show us a schematic, maybe someone will see something.

  • I'm using the launchpad as a reference, figuring with our pinout running on the msp430 that's the "worst" case for the controller only. I'll see what I can do for the schematic, this is a subsystem on the board.

    I was wondering about the i2c and spi lines sinking current from the pullups.

    There's no "bus conflict", just the LPM3 state of the io pins for spi/uart/i2c. I'm assuming that entering LPM3 will idle the modules to the lowest power state with the usage in mind.  

  • The comments say, e.g., that P5.0/1 are connected to an I2C bus. It looks as though one of the first things this program does is:

    >P5OUT = 0;
    >P5DIR = 0xFF;

    which would drive low against the bus pullups, which I would call a bus conflict. (It probably isn't making your slave(s) very happy either.) Setting P5SEL (to give the pins to the I2C) would counteract this, but I don't see this program doing that (the "msp430_init(1)" is commented out).

    More generally: LPM3 has no direct effect on peripherals. It does turn off SMCLK, which may have some small secondary effect, but mostly the peripherals don't know that this has happened.  

  • Hi dtyree,

    Were you able to get the low currents?

  • Yeah, A little whack-a-mole, but got it down close enough to the "theoretical calculated" consumption rate. 

**Attention** This is a public forum