I'm working on a key fob that runs off a CR2032 lithium battery and uses the CC430F5133 microcontroller from the MSP430 family. The clock source is an external 32 KHz crystal on XT1.
In normal operation, the current consumption in LPM4 sleep state is 5.5 uA. Every once in a while the sleep current is 8.5 uA.
I have trimmed down the code to the following:
#include <msp430.h> #include <stdint.h> #include "HAL_PMM.h" #define FOB_UBTN0 BIT0 #define FOB_UBTN0_PORT_DIR P1DIR #define FOB_UBTN0_PORT_SEL P1SEL #define FOB_UBTN1 BIT1 #define FOB_UBTN1_PORT_DIR P1DIR #define FOB_UBTN1_PORT_SEL P1SEL #define FOB_UBTN2 BIT7 #define FOB_UBTN2_PORT_DIR P1DIR #define FOB_UBTN2_PORT_SEL P1SEL #define FOB_UBTN3 BIT6 #define FOB_UBTN3_PORT_DIR P2DIR #define FOB_UBTN3_PORT_SEL P2SEL #define FOB_VREF_PIN BIT4 #define FOB_VREF_PORT_DIR P2DIR #define FOB_LED1 BIT4 #define FOB_LED_PORT_DIR P3DIR #define FOB_LED_PORT_OUT P3OUT #define FOB_LED_PORT_SEL P3SEL static void initializePorts(void) { P1SEL = 0x00; P2SEL = 0x00; P3SEL = 0x00; P5SEL = 0x00; P1DIR = 0xFF; P2DIR = 0xFF; P3DIR = 0xFF; P5DIR = 0xFF; PJDIR = 0xFF; P1OUT = 0x00; P2OUT = 0x00; P3OUT = 0x00; P5OUT = 0x00; PJOUT = 0x00; // Set up port 5 for XIN for XOUT P5DS |= BIT0+BIT1; P5OUT |= BIT0+BIT1; P5SEL |= BIT0+BIT1; P5DIR &= ~(BIT0+BIT1); FOB_UBTN0_PORT_DIR &= ~FOB_UBTN0; FOB_UBTN0_PORT_SEL &= ~FOB_UBTN0; FOB_UBTN1_PORT_DIR &= ~FOB_UBTN1; FOB_UBTN1_PORT_SEL &= ~FOB_UBTN1; FOB_UBTN2_PORT_DIR &= ~FOB_UBTN2; FOB_UBTN2_PORT_SEL &= ~FOB_UBTN2; FOB_UBTN3_PORT_DIR &= ~FOB_UBTN3; FOB_UBTN3_PORT_SEL &= ~FOB_UBTN3; FOB_VREF_PORT_DIR &= ~FOB_VREF_PIN; FOB_LED_PORT_OUT &= ~FOB_LED1; FOB_LED_PORT_DIR |= FOB_LED1; FOB_LED_PORT_SEL &= ~FOB_LED1; } void LFXT_Start(uint16_t xtdrive) { UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L; // Highest drive setting for XT1 startup while (SFRIFG1 & OFIFG) { // check OFIFG fault flag UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG); // Clear OSC flaut Flags fault flags SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag } UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) | (xtdrive); // set Drive mode } int main(void) { // Watchdog off WDTCTL = WDTPW + WDTHOLD; SFRIE1 &= ~WDTIE; SetVCore(0); initializePorts(); LFXT_Start(XT1DRIVE_0); // RTC timer on RTCCTL01 = RTCTEV0_H; __bis_SR_register(LPM4_bits); }
The SetVCode(0) function is from the HAL_PMM.c module from the TI example projects. LFXT_Start() which I show above is also taken directly from the TI demo code.
As you can see, there are no interrupt handlers in this trimmed down code. The code just boots and goes right to sleep and stays asleep.
If I cut battery power then reapply battery power, usually waiting 500-1500 msec in between, once in every 10 or 20 power cycles the sleep current is 8.5 uA. In all other cases the sleep current is 5.5 uA.
In the full product source code (before I whittled it down to what you see above), I have buttons on the fob that wake the CPU, do some processing, then go back to LPM4 sleep state. I can repeat this sequence over and over when the fob is in the "bad" mode and it always goes back to sleep at the higher 8.5 uA sleep current.
However, if while the CPU is awake, I execute ONLY the LFXT_Start() call shown above to reinitalize the clock system, the problem goes away and the next sleep cycle goes back to the desired 5.5 uA sleep current and will stay at the correct sleep current after many wake/sleep cycles.
As another clue, it seems that if I comment out the code that starts the RTC timer, that also makes the problem go away (or makes it really, really hard to reproduce). With the RTC off I tested over 150 power cycles and never saw the higher sleep current.
Can anyone offer some guidance on how to debug this?
Thanks,
Bob