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.
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.
//*************************************************************************************** // 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.
Yeah, A little whack-a-mole, but got it down close enough to the "theoretical calculated" consumption rate.
**Attention** This is a public forum