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.

MSP430F5419A: LPM3_EXIT in timer0 B1 interrupt function invoked, but system not recovered from LPM3 mode

Part Number: MSP430F5419A

These days we've encountered a problem on timer0 B1 interrupt process. We're using IAR MSP430 7.20.1 as the development environment. And we're using ACLK from VLO 9.4KHz clock as the clock source of timer 0 B1 in LPM3 mode. We uses continuous mode, ID /8, TBSSEL ACLK and TBIE enabled in TB0CTL initialization and TBIDEX /2 in TB0EX0. So the timer B interrupt occurs every 3569.6s, about 59.5minute, we uses the time as about 1 hour. And we need the system keeps in LPM3 sleep mode until about 3 hours arrives and then it's waken up. So we implemented the interrupt as following:

static U_WORD timeoutCounter = 0U;

#pragma vector = TIMER0_B1_VECTOR
static __interrupt void timerBInt( void ) {
    switch(TB0IV) {
        case TB0IV_TBIFG:
            timeoutCounter++;
            break;
        default:
            break;
    }

    if(timeoutCounter >= 3) {
        LPM3_EXIT;
    }
}

void ctrlHostSupplyEnterSleepMode( void ) {

        ...
        LPM3;
        __no_operation();

        drvDioCurMeasSetOn(HIGH);

        ...

}

But the system doesn't work as we expected. When the timeoutCounter arrives 3 in the 3rd timeout interrupt, it do invoked LMP3_EXIT, but the system is not waken up and break at the breakpoint on drvDioCurMeasSetOn(HIGH) line after LPM3 line in ctrlHostSupplyEnterSleepMode() function in debugger mode(We're sure LPM3 line already invoked and it's in LPM3 mode in the whole test. We tested with dozens of times and added breakpoints in other later lines to avoid there's maybe some code optimization problem to skipped the breakpoint.). So we started to track this issue. After debugging dozens times, we finally found if we remove the if(timeoutCounter >= 3) line and exactly let the interrupt of timerBInt() to invoke LPM3_EXIT before exit. The drvDioCurMeasSetOn(HIGH) line break occurs and the system is waken up. So that mean only the 1st interrupt to invoke LPM3_EXIT will wakeup the system. Code Modified like this:

#pragma vector = TIMER0_B1_VECTOR
static __interrupt void timerBInt( void ) {
    switch(TB0IV) {
        case TB0IV_TBIFG:
            timeoutCounter++;
            break;
        default:
            break;
    }

    LPM3_EXIT;
}

So we're confused with this because it’s really strange. So now I’d like to inform this issue to your side if anyone of you had met with similar issues like this and give us some suggestions. Thanks!

  • Hi Gong Qiqi,

    I'll look into this and get back to you tomorrow.

    Regards,

    Evan

  • Hi Gong Qiqi,

    Can you confirm that TB0IV_TBIFG is firing and that timeoutCounter is getting incremented? The only way I can explain the behavior you have described is that another timer interrupt is firing. If that isn't the issue please provide your timer configuration code so I can try to reproduce on my end.

    Thanks,

    Evan

  • Hi Evan,

    Thank you for your reply. Yes, the TB0IV_TBIFG is firing and the timeoutCounter is getting incremented. Here I'll attach the code. I've tide up the code because the original code is too complicated. The code can also reproduce this issue:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #define _SYS_CTRL_C
    /* ====================================================================================
    * INCLUDE FILES
    ==================================================================================== */
    #include "msp430.h"
    #include "cdefs.h"
    #include "boardDef.h"
    /* ====================================================================================
    * LOCAL DEFINITIONS
    ==================================================================================== */
    #define DRV_INT_MASK_WAKEUP_AC 0x0020
    #define DRV_INT_MASK_START_BUTTON 0x0040
    /* RESERVED 0x0080*/
    /* RESERVED 0x1000*/
    /* RESERVED 0x2000*/
    #define DRV_INT_MASK_SYS_TIME 0x4000U
    #define DRV_INT_MASK_GLOBAL_INT 0x8000U
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #ifndef UTILS_CDEFS_H_
    #define UTILS_CDEFS_H_
    /* ====================================================================================
    * GLOBAL DEFINITIONS
    ==================================================================================== */
    #define TRUE ((BOOL)(1==1)) /* Boolean true */
    #define FALSE ((BOOL)(0==1)) /* Boolean false */
    #define OK ( 0 ) /* regular return value */
    #define ERROR ( -1 )
    #ifndef NULL
    #define NULL ((void *) 0)
    #endif
    typedef enum {
    DISABLE = 0U,
    ENABLE = 1U,
    } EnableState;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #ifndef UTILS_BOARDDEF_H_
    #define UTILS_BOARDDEF_H_
    /* =================================================================
    * GLOBAL INCLUDES
    ================================================================= */
    #include "msp430.h"
    /* =================================================================
    * GLOBAL TYPES
    ================================================================= */
    /* =================================================================
    * GLOBAL DEFINITIONS
    ================================================================= */
    /* =================================================================
    * PIN DEFINITIONS
    ================================================================= */
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Thanks for sharing. I'll try to reproduce later today and get back to you.

  • Hi Gong Qiqi,

    Apologies it is going to be more challenging than I thought to reproduce your code since I'm working with slightly different hardware.

    In the meantime, can you try something for me. Can you place a trap in the ISR (see below) to confirm all the surrounding code is working as expected?

    static __interrupt void timerBInt( void ) {
        switch(TB0IV) {
            case TB0IV_TBIFG:
                timeoutCounter++;
                break;
            default:
                break;
        }

        if(timeoutCounter >= DEFAULT_AUX_TIMEOUT) {

            while(1);
            //LPM3_EXIT;
        }
    }

    Thanks,

    Evan

  • I put together an even simpler version of your code to test on my end. I wasn't able to reproduce your problem. When ii==3, the device exits LPM3 and lands on the while(1) in the main().

    Can you run this code on your end and see if you have the same behavior?

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <msp430.h>
    unsigned int ii = 0;
    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    UCSCTL1 = DCORSEL_2; /* select DCO range of 0.75 MHz to 7.68 MHz */
    UCSCTL2 = FLLD__4 | 31; /* CLOCKDIV 4, FLLN 31 */
    UCSCTL3 = SELREF__REFOCLK | FLLREFDIV__1; /* select 32768 ref clk, divide by 1 */
    /* source SMCLK from DCOCLKDIV, MCLK from DCO, ACLK from VLO (9.4Hz typical) */
    UCSCTL4 = SELS__DCOCLKDIV | SELM__DCOCLK | SELA__VLOCLK;
    //UCSCTL5 = DIVM__1 | DIVA__32 | DIVS__1 ;
    UCSCTL5 = DIVM__1 | DIVA__2 | DIVS__1 ;
    do
    {
    UCSCTL7 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG);
    SFRIFG1 &= ~OFIFG;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • The code is rather convoluted so it is not apparent to me how timeoutCounter gets reset after waking up from LPM3. I only see it being cleared in the timer start and stop code. Without being reset, it would be greater than 3 and cause a wakeup most every interrupt.

    I would structure this a bit differently with the timer ISR just incrementing the counter and exiting LPM3. The foreground code would look at the counter and decide what to do: go back to sleep, or reset the counter and execute the time out tasks.

  • Hi Evan,

    I've tested with the code you provided. The behavior is just as same as my code as I described previously. You can see some detail debug information here:

    Debug screen

    If it's OK on your side, is it possible the issue is caused by IAR or my debugger? I'm using IAR MSP430 7.20.1 and the debugger is TI MSP430 USB-Debug-Interface MSP-FET430UIF.

    And also I added the remaining include files' code in my previous reply.

    Best regards,

    Gong Qiqi

  • Hi David,

    Thank you for your concerning on it!

    In fact, the code I showed is not the original code. I tided up the code and removed all the unnecessary files and lines. So this code is just to reproduce this issue. To make things simple, you can also try with Evan's code. I've reproduced this issue on his code.

    Thanks a lot!

    Qiqi

  • Hi Gong Qiqi,

    Could you try my example in CCS and see if it has the same behavior?

    Thanks,

    Evan

  • Hi Evan,

    I've tried your code in CCS and the same behavior occurred. And it seems it will occur in the case that we pause the running program in LPM3 mode in debug. If there're any pause operations after the 1st timer 0 B1 ISR had occurred, this issue will occur.

    Thanks,

    Gong Qiqi

  • Hi Gong Qiqi,

    Thanks for the follow-up. I'm also able to create some bad behavior in the example code I gave you by repeatedly pausing and resuming the debugger during the operation of the program. I don't understand the root cause exactly, but the debugger is invasive and can create unexpected behavior.

    Regards,

    Evan

**Attention** This is a public forum