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.

MSP430FR2355: RTC usage one way in LPM3.5 and another in active mode

Part Number: MSP430FR2355

Hello. 

I'm having some difficulty working with the RTC. I'm attempting to manipulate the RTC so that while the main application is active it increases a seconds variable every one second RTCMOD = 32-1. This way I can keep track of time for my sensor reads since power up. This is simple and I have been able to accomplish this aspect.  

However, there will be times that I would like to be able to set the device to LPM3.5, utilizing the RTC, but I would need the device to sleep for say a week. One design is to keep the RTC running at 1hz, however this eats up too much energy from the power source. I want the device to sleep for 1 week, so I thought chance RTCMOD to 604800 * (32-1). Which will wake the device up  in one week.  

 I figured i would be able to switch back to 1hz once I get out of LPM3.5, but it doesn't want to seem to do that. More importantly, I image there is a way better way of managing this. 

Is there any insight as to a recommendation on how to accomplish this?

Michael

  • Hi Michael,

    I'm afraid you can't set the RTCMOD to 604800*(32-1) since the RTCMOD is a 16-bits register which the max value is 65535. So, it is impossible to wake up the device for a week by RTC.

  • Hi Wei, 

    Thanks for getting back to me. Ok, that makes complete sense. I simply overlooked that aspect of my issue. Thank you for bringing that to light. This is my first time working with the device.

    However, my main problem still stands.I can work work with the max sleep time being roughly ~35 min . What I'm looking for is the best way to manage this. As I need to switch back and forth between an increment at 1hz while the device is active, yet still be able to sleep for the designated period. Once it wakes I'll calculate the time slept and add that to my time sense booted. 

    Currently what I'm doing is setting the RTC to 1hz, while I set up all my pins for hardware control, ie sd card, power control module, actuators, pump, etc. I do that by

    void rtc_1hz()
    {
        P2SEL1 |= BIT6 | BIT7;   
        do
        {
    
            CSCTL7 &= ~(XT1OFFG | DCOFFG);
            SFRIFG1 &= ~OFIFG;
        }
        while (SFRIFG1 & OFIFG);            
    
        flash(1,1000);
    
        PM5CTL0 &= ~LOCKLPM5; 
    
        RTCMOD = 32 - 1;
        RTCCTL = RTCSS__XT1CLK | RTCSR | RTCPS__1024 | RTCIE;
    }

    this calls the ISR that increments my time count by 1. 

    once the device is ready to sleep I then call

    void enter_low_power_mode(unsigned int lpt)
    {
            P2SEL1 |= BIT6 | BIT7;      
            do
            {
                CSCTL7 &= ~(XT1OFFG | DCOFFG);    
                SFRIFG1 &= ~OFIFG;
            }
            while (SFRIFG1 & OFIFG);          
            PM5CTL0 &= ~LOCKLPM5; 
                                
    
            RTCMOD = lpt;
            RTCCTL = RTCSS__XT1CLK | RTCSR | RTCPS__1024 | RTCIE;
            _bis_SR_register(LPM3_bits| GIE);   //
    }

    lpt = low power time (time I want the device to sleep)

    This works just fine. once it wakes I add the lpt value to the time since booted incremented value. 

    however, its here where the issue is. I call rtc_1hz() again to set the 1 sec increment. But it doesn't appear to work anymore. It does not trip the ISR at all. Thus, it is no longer incrementing at 1hz. 

    Any suggestions on how I can accomplish what I'm looking to do?

  • Hi Wei,

    so I think I have this figured out. I believe the best solution for me is to use two timers. So I've worked out a way to use both the RTC and Timer_B0. I'll run RTC while I'm sleeping. Timer_B0 will of course be disabled. When I wake from my sleep I'll disable RTC and re-enable Timer_B0. I've done quick test for enabling and disabling with two timers, manipulating two leds on the launchpad. 

    #include <msp430.h>
    
    void initGpio(void);
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;                    // Stop WDT
    
        initGpio();                             // Configure GPIO
    
        // Initialize XT1 32kHz crystal
        P2SEL1 |= BIT6 | BIT7;                  // P2.6~P2.7: crystal pins
        do
        {
            CSCTL7 &= ~(XT1OFFG | DCOFFG);      // Clear XT1 and DCO fault flag
            SFRIFG1 &= ~OFIFG;
        } while (SFRIFG1 & OFIFG);              // Test oscillator fault flag
    
        __enable_interrupt();               // The RTC interrupt should trigger now...
    
        RTCMOD = 10*(32-1);
        RTCCTL = RTCSS__XT1CLK | RTCSR | RTCPS__1024 | RTCIE;
    
        // Configure Timer_A
        TB0CTL = TBSSEL_1 | MC_2 | TBCLR | TBIE;      // ACLK, count mode, clear TBR, enable interrupt
    
        while(1)
        {
           // __bis_SR_register(LPM3_bits | GIE);           // Enter LPM3, enable interrupts
            __no_operation();                             // For debugger
        }
    }
    
    void initGpio(void)
    {
        P1DIR = 0xFF; P2DIR = 0xFF; P6DIR = 0xFF;
        P1REN = 0xFF; P2REN = 0xFF;
        P1OUT = 0x00; P2OUT = 0x00; P6OUT = 0x00;
    
        // Configure GPIO
            P1DIR |= BIT0;
            P1OUT |= BIT0;
            P6DIR |= BIT6;
            P6OUT |= BIT6;
    
        // Disable the GPIO power-on default high-impedance mode
        // to activate previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
    }
    
    // Timer0_B3 Interrupt Vector (TBIV) handler
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void TIMER0_B1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_B1_VECTOR))) TIMER0_B1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch(__even_in_range(TB0IV,TB0IV_TBIFG))
        {
            case TB0IV_NONE:
                break;                               // No interrupt
            case TB0IV_TBCCR1:
                break;                               // CCR1 not used
            case TB0IV_TBCCR2:
                break;                               // CCR2 not used
            case TB0IV_TBIFG:
                P1OUT ^= BIT0;                       // overflow
                break;
            default:
                break;
        }
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = RTC_VECTOR
    __interrupt void RTC_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        switch(__even_in_range(RTCIV, RTCIV_RTCIF))
        {
            case RTCIV_NONE : break;            // No interrupt pending
            case RTCIV_RTCIF:                   // RTC Overflow
                // Toggle LED on P1.0
                P6OUT ^= BIT6;
                TB0CTL ^= TBIE;
    
                // Store P1OUT value in backup memory register
                *(unsigned int *)BKMEM_BASE = P1OUT;
                break;
            default:          break;
        }
    }
    

    in this test. I have the RTC blinking LED2 once every 10 seconds. Timer_B0 will blink LED1 once every 2 seconds ONLY when LED2 is lite. 

  • Hi,

    Sounds good. Please feel free to come back for further technical issue or question.

**Attention** This is a public forum