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.

MSP430FR5994: Does a legal access to the WDT cause SYSRSTIV_WDTPW to be set?

Part Number: MSP430FR5994

I am using the MSP430FR5994 Launchpad. My application needs to know how main was entered (i.e. WDT timeout, WDT access violation, LPM3 wakeup, etc).. Upon entering main() my test code initializes the GPIO, the clock system, and the UART (for communications).  Button S2 interrupts (which causes a WDT access violation) are then enabled and the WDT is activated to generate a timeout reset every 16sec. My the test I expect a return to main either from the S2 button press (which writes WDTCTL=0 to cause an access violation) or a timeout.  I use a switch statement to find the source of the interrupt.

However, there are things happening I don't understand. 

It appears that any access to the WDT causes the SYSRST_WDTPW word to be set. The macro definitions for WDTPW states "/* WDTPW watchdog password violation */" which leads me to believe this reset code is generated for illegal access (any access without 0xa500 in the high order bits of the word). However, an explicit check for WDTPW violation is ignored when S2 is pressed.

From the datasheet I would expect that a WDTIFG timeout (16h) is higher priority than the WDTPW violation so a timeout should be the first interrupt found in the switch statement. But the switch reports the WDTPW violation instead. I have to explicitly check outside of the switch for the WDTIFG timeout. This doesn't make sense if WDTIFG is higher priority. 

 In addition, the SYSRSTIV_WDTIFG if statement (before the switch)  is never executed. Reading the SYSRSTIV should clear the highest priority interrupt which should have been the WDTIFG and it should have found the WDTPW violation but doesn't when the S2 button is pressed. 

Can anyone explain why WDTPW violation seems to appears when I configure the WDT (I don' think I configured illegally) and why WDTIFG is not caught first by the switch statement? And why the WDTPW isn't caught when S2 is pressed?

Below is the test code followed by ISR handler for the S2 Button.

int main(void){
    __disable_interrupt();
    Init_GPIO();
    Init_Clock();
    Init_UART();
    P5IFG &= ~BIT5; //clear interrupts

    char tm[]={"\n\r\tBack in Main"}; Probe(tm);
    P5IE |= BIT5;
    __enable_interrupt(); 
    WDT_A_initWatchdogTimer(WDT_A_BASE, WDT_A_CLOCKSOURCE_XCLK, WDT_A_CLOCKDIVIDER_512K); //16sec
    SFR_enableInterrupt(SFR_WATCHDOG_INTERVAL_TIMER_INTERRUPT);
    WDT_A_start(WDT_A_BASE); //WDTCTL &= ~WDTHOLD;


   if (SYSRSTIV == SYSRSTIV__WDTIFG){ //WD timeout
           char tm[]={"\n\r\tWDT Time Out"}; Probe(tm);
           SYSRSTIV=0; //reset
           P1DIR |= BIT0 | BIT1; //set as output
           P1OUT |= BIT0 | BIT1; //Red & Grn LED on
       }
   if (SYSRSTIV == SYSRSTIV__WDTPW){ //WD timeout
          char tm[]={"\n\r\tWDTPW VIOLTN"}; Probe(tm);
          P1DIR |= BIT0 | BIT1; //set as output
          P1OUT |= BIT0 | BIT1; //Red & Grn LED on
          }

 char tm0[]={"\n\r\tWDT Time Out "};
 char tm1[]={"\n\r\tWDTPW violation "};
 char tm2[]={"\n\r\tLPM5WU"};
    switch (SYSRSTIV,SYSRSTIV__WDTPW)
    {
    case SYSRSTIV_NONE:
        __no_operation();
        break;
    case SYSRSTIV_BOR:
        __no_operation();
        break;
    case SYSRSTIV_LPM5WU: //LPM5WU
        __no_operation();
         Probe(tm2);
        break;
    case SYSRSTIV_WDTTO: //timeout
        __no_operation();
         Probe(tm0);
        P1DIR |= BIT0 | BIT1; //set as output
        P1OUT |= BIT0 | BIT1; //Red & Grn LED on
        break;
    case SYSRSTIV__WDTPW: //access violation
        __no_operation();
        P5IFG &= ~BIT5;//clear flag
         Probe(tm1);
         SYSRSTIV=0; //reset
        break;

    default: break;

    }

#pragma vector=PORT5_VECTOR
__interrupt void Port_5(void)
{
  //P5IFG &= ~BIT5;                           // Clear P5.5 IFG
  //mode = '0';

  char ms[]={"\n\r\tS2 ISR"};Probe(ms);


  RTC_C_holdClock(RTC_C_BASE);
  rec_calendar=calendar;
 WDTCTL=0; //WD PW violation, generate PUC

}

Here is a screen shot of

  • Well, I found part of the problem. In the Family User Guide there is one sentence that states "If the flag [WDTIFG] is set, the watchdog timer initiated the reset condition, either by timing out or by a password violation". This means that the first If statement (if(SYSRSTIV==SYSRSTIV__WDTIFG){...} catches both the password violation and a timeout as stated in the Family User Guide. Ok so on a WDT timeout event, the flag is set and the WDT is re-initialized causing it to lose the timeout event but see the WDTPW event (and maybe because its a legal access, the WDTIFG is not set (but the WDIFG still shows in the SYSRSTIV vector).
    I will move the SYSRSTIV code before the WDT re-initialization to check
  • Hey James,

    I'm struggling a bit to understand what is happening and what you expect to happen.  It sounds like you are starting the WDT and then you have a button that is supposed to trigger a WDT password violation.  These are two sources that will each cause a PUC, and you are trying to determine the source.  

    Is that correct?

    James Nadir said:
    From the datasheet I would expect that a WDTIFG timeout (16h) is higher priority than the WDTPW violation so a timeout should be the first interrupt found in the switch statement. But the switch reports the WDTPW violation instead. I have to explicitly check outside of the switch for the WDTIFG timeout. This doesn't make sense if WDTIFG is higher priority. 

    I don't understand your question here about priority.  There is only going to be one source of the PUC.  Are you expecting there to be a nest reset interrupts?  

    If the reset is caused by either the password violation or WDT timer expiring, then there should only be 1 source.  

    Thanks,

    JD

  • moving the SYSRSTIV code before the WDT initialization made no difference. The switch statement still thinks everything is an access violation.
  • i realized after my first post that WDTIFG was set for either a PW violation or a timeout event. However, when the WDT times out, the switch (SYSRSTIV== xxxx) statement in my test code returns an access violation instead of a timeout vector. The problem is that I have two sources that cause the program to return to main, one is a WDT timeout and the other is WDT access violation (from the push button) . My problem is that my code is either not reading the SYSRSTIV vector or is changing it (by re-initializing the WDT before reading the SYSRSTIV). I moved the switch statement ahead of the WDT initialization but it made no difference. My understanding is that a PUC does not affect the SYSRSTIV. Any idea what's wrong?

  • As I play with the code, it seems that I am not getting the SYSRSTIV vector value after the PUC. Isn't the SYSRSTIV retained until it is read or overwritten? Also, the SYSRSTIV is not used in pragma ISR (as recommended by another TI app note) it is at the start of main.
  • I found the problem, my switch statement was incorrect. I fixed it and I am now able to determine the source of the WDT interrupt
  • Hey James,

    I just slightly modified our MSP430fr599x_wdt_04.c example below and let the WDT timer reset.  It seems to be working as expected for me. 

    The very first iteration after programming, SYSRSTIV is showing BOR as reset as expected, but each iteration after it's correctly showing 0x0016 for a WDT timeout.  Then, after reading it is cleared.  

    int main(void)
    {
        // Configure GPIO
        P1DIR |= BIT0;                          // Set P1.0 to output - SET BREAKPOINT HERE
        P1OUT ^= BIT0;                          // Toggle P1.0
    
        if (SYSRSTIV == SYSRSTIV__LPM5WU){
            __no_operation();
        }
        __no_operation();
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
    
        while(1);
    //    __bis_SR_register(LPM4_bits | GIE);     // Enter LPM4, Stop all clocks
        __no_operation();                       // For debugger
    }

    Can you try this out on your side?  

    Thanks,

    JD

  • Hey James,

    Great to hear!

**Attention** This is a public forum