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.

MSP430FR2676: Timer interrupt executes after watchdog reset

Part Number: MSP430FR2676

I have an application that makes use of a lot of peripherals, including a timer that calls a handler at periodic intervals.  If there is no watchdog reset, everything runs as expected.

If I comment out the code to feed the watchdog, the rest occurs after the expected delay, but the MSP430 does not appear to really be doing a "full" reset of the timer peripheral.  After the watchdog reset, TA0_TA0CCTL0 contains a value of 0x01.  This indicates that the timer interrupt (TAIE) flag has properly been cleared, like it should, but the interrupt flag (TAIFG) is set, indicating a pending interrupt!

What can I do to clear all interrupts that could have been pending/active before the watchdog reset, so that my interrupt handlers cannot execute before application initialization?

Pseudocode:

void main()
{
    // (Never reaches here after a watchdog reset)

    // Initialize application data (pointer initialization, heap allocation, etc...)

    // Initialize watchdog
    ROM_WDT_A_initWatchdogTimer(WDT_A_BASE, WDT_A_CLOCKSOURCE_SMCLK, WDT_A_CLOCKDIVIDER_8192K);
    ROM_WDT_A_start(WDT_A_BASE);

    // Initialize other peripherals, including a hardware timer

    for (;;)
    {
        // Feed watchdog
        ROM_WDT_A_resetTimer(WDT_A_BASE);
    }
}

void timerInterruptHandler()
{
    // Accesses application data, which must be initialized before this is called, or the application crashes
}

  • TAIE is the timer interrupt enable. If that bit is cleared during reset and never reconfigured, your timer will no longer service interrupts. If you're not in continuous counting mode, the timer will count up or down to its specified value, set TAIFG to indicate that, and then do nothing.

    I would start by making sure you configure interrupts properly after coming back from a reset.

  • >  If that bit is cleared during reset and never reconfigured, your timer will no longer service interrupts.

    That's not what I'm seeing.  With only TAIFG set, the timer handler is getting called continuously, before my timer initialization code is reached.

    My initialization sequence is awkward, because I'm also using LPM3.5.  On startup, there is some minimal initialization and servicing of the real-time clock, that needs to be done with minimal power draw.  If it decides it needs to wake up to continue running the application, then more peripherals are initialized, including this hardware timer.

    This means that I'm enabling interrupts to service the real-time clock, before explicitly configuring the timer.  This, combined with TAIFG still being set after the watchdog reset, seems to be creating this problem.

    So back to my original question:  What can I do to clear all interrupts that could have been pending/active before the watchdog reset, so that my interrupt handlers cannot execute before application initialization?

    Is there a convenient way for me to clear all pending interrupts (for all peripherals), or do I have to explicitly clear each pending interrupt flag in the system, before interrupts are enabled?

  • Without knowing more about the code and startup sequence, it's hard to tell what's causing the problem. Which clock interrupts are you enabling in your startup and how are you enabling them?

    As I'm sure you know, you can enable/disable all interrupts at once, but I'm not aware of any way to clear every interrupt pending flag in every peripheral controll register all at once.

    In my application I want interrupts for UART but not for SPI. To do this, I set the interrupt enable within that peripheral's control registers. If you're using something more general like 

    __bis_SR_register(LPM3_bits | GIE);

    then the behavior might be different, but I really wouldn't expect an interrupt to occur in any peripheral unless that control register explicitly enables it.

    The only other idea that comes to mind is if the type of reset triggered by a wdt timeout does not clear the register config for the peripherals. That could potentially explain why the you're still getting timer interrupts. I'm not as familiar with resets and LPMs so I can't really speak on that.

  • The documentation on the watchdog (in the user guide and datasheet) is incredibly light, especially compared to what I was used to for the Tiva devices.  I am surprised by the behavior I am seeing, but am not sure what it is really expected/designed to do.

    Explicitly clearing the control register for each peripheral on startup (something like the line below, but repeated for every peripheral) does seem to work, but is what I was hoping to avoid.  I assumed there must be some better way, or that I was setting up the watchdog incorrectly.

    HWREG16(TIMER_A0_BASE + OFS_TAxCTL) = 0;

    It seems that the ultimate answer to my initial question is probably "no".  There is no convenient way to put the MSP430 back into an "initial" state after a watchdog reset, and special steps need to be taken to explicitly set the configuration to the desired state on startup, in case that happens.

    Anyway, thanks for trying to help.

  • CCIFG is not reset by PUC, only by POR. [Ref User Guide (SLAU445I) Figure 13-18.] That's actually true of most of the Timer A registers.

    The key is in User Guide Table 0-1, where the parentheses mean "set this way by POR" and by implication not by PUC.

    Dealing with this means having your device initialization put the device into a known state, and have initialization happen before setting GIE. You needn't do this exhaustively, only do this with things your code already works with, since the others were dealt with at the last POR. 

    Among other things, always clear (stale) IFGs before setting their respective IEs. For TA0CCTL1 this just means using "=" rather than "|=".

**Attention** This is a public forum