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.

Problems clearing watchdog interrupt on the TM4C129X

I'm having problems clearing the watchdog interrupt on the TM4C129x - 

I have the watchdog interrupt hooked up to a general purpose Fault handler.     The FH does a register capture and then ID's the IRQ source and executes this code:


	switch ( get_ipsr() ) {
		case 0x22: // ----------------------- WDT Faults ----------------------
			if ( !FHandlerState.wdt_fired ) {
				WatchdogIntClear(WATCHDOG0_BASE);
				IntDisable(INT_WATCHDOG);
				FHandlerState.wdt_fired = 1;
				
				scram_message_out_string(DUMP_TO_BOTH," Watchdog Timeout");
				p->motw = motw_type_wdttimeout;
				while ( IntIsEnabled(INT_WATCHDOG) ) { ; } // Spin loop until it clears.
				IntPendClear(INT_WATCHDOG);
				}
			break;

The intent is the the WDT interrupt will clear and the fault handler will go on about its business cleaning up and making reports.   After about a second, I should get a hard reset.   What I see is that I keep getting WDT interrupts, and then I blow out the stack and start getting hard faults.

This seems pretty simple.   Why do I get two watchdog interrupts?

- Robert





I have been unable to

  • Hello Robert,

    What is the configuration of the WatchDog and where is it done?

    Regards
    Amit
  • Whoops.   Thats important.   The watchdog is setup early -

    /// Initialize the watchdog
    void watchdog_init() { 
        // Check to see if the registers are locked, and if so, unlock them.
        if(WatchdogLockState(WATCHDOG0_BASE) == true)    {
            WatchdogUnlock(WATCHDOG0_BASE);
        }
        WatchdogStallEnable(WATCHDOG0_BASE);
        
        // Initialize the watchdog timer to an initial value of 10s
        WatchdogReloadSet(WATCHDOG0_BASE, INITIAL_WDT_TIMEOUT);
        WatchdogResetEnable(WATCHDOG0_BASE);
        WatchdogIntEnable(WATCHDOG0_BASE);
        WatchdogEnable(WATCHDOG0_BASE);
        WatchdogLock(WATCHDOG0_BASE);
            }
    
    
    

    And then its refreshed at roughly 10Hz by a user thread:

    static void watchdog_refresh_raw(int ticks) {
                WatchdogUnlock(WATCHDOG0_BASE);
                    WatchdogReloadSet(WATCHDOG0_BASE,ticks);
                    WatchdogIntClear(WATCHDOG0_BASE);
                WatchdogLock(WATCHDOG0_BASE);       
                    }
    

  • Hello Robert,

    You have cleared the WatchDog Interrupt which causes the next Timeout to generate an interrupt as well. Only if you do not clear the interrupt shall it generate a reset on the next time out. To do so, just disable the interrupt in NVIC using IntDisable API.

    Regards
    Amit
  • This is all happening immediately after the first pass through the fault handler.

    I get two back-to-back interrupts. If you take a look at the code above, you'll see that I'm using IntDisable(). For some reason it doesn't take effect, or the WDT interrupt clear isn't taking effect. I even do a read back of the register (instead of a barrier instruction), so I know that the NVIC write is taking effect.

    The complicating factor here is that the repeated tripping of the fault handler prevents invocation of PendSV, so my network stack can't get any cycles to send out a failure report while I wait for the WDT reset.

    On closer reading of the data sheet, I see that this can all be simpler (which I'll do), but it -should- work.
  • Heres some updated, cleaner code - 

    I stopped locking the watchdog.   No changes.   I get another interrupt ~ 30ms after clearing  the WDT interrupt.   Most of that time is taken up by UART output which happens after the WDT clear.   

    	switch ( get_ipsr() ) {
    		case 0x22: // ----------------------- WDT Faults ----------------------
    			if ( !FHandlerState.wdt_fired ) {
    				WatchdogIntClear(WATCHDOG0_BASE);
    				IntDisable(INT_WATCHDOG);
    				FHandlerState.wdt_fired = 1;
    				
    				scram_message_out_string(DUMP_TO_BOTH," Watchdog Timeout");
    				p->motw = motw_type_wdttimeout;
    				}
    				 
    			break;
    
    
    
    /// Initialize the watchdog
    void watchdog_init() { 
    	wdt_unlock();
    
        // Check to see if the registers are locked, and if so, unlock them.
         // Turn on stalling so the debugger doesn't reset the board.
        WatchdogStallEnable(WATCHDOG0_BASE);
        
        // Initialize the watchdog timer to an initial value of 10s
        WatchdogReloadSet(WATCHDOG0_BASE, INITIAL_WDT_TIMEOUT);
        WatchdogResetEnable(WATCHDOG0_BASE);  // Enable the reset.
        WatchdogIntEnable(WATCHDOG0_BASE);    // Enable the interrupt
        WatchdogEnable(WATCHDOG0_BASE);    // Enable the watchdog timer.
    	}
    
    	
    /// Refresh the watchdog.  Note that the values are hard-coded, so as to prevent
    /// RAM Corruption from screwing this up.
    static void watchdog_refresh_raw(int ticks) {
    	WatchdogReloadSet(WATCHDOG0_BASE,ticks);	
    	}
    
    void watchdog_refresh() {
    	watchdog_refresh_raw(PRIMARY_WDT_TIMEOUT);
    	}
    
    

  • Fixed. The watchdog is functioning as expected. The root cause was a usage fault (blx instead of bl) in the hander. That would prevent proper return from the fault handler.
  • Hello Robert,

    Glad that you found the issue. If you could let us know which handler was the issue?

    Regards
    Amit
  • The issue wasn't the handler, it was a bit of support code that was causing a hard fault when called by the handler.

    The CPU was going into hard fault, and as a result the handler was never performing exception return. The pended hard fault was actually triggering the common handler. I'm not sure why the IFSR was still showing the vector number for the watchdog interrupt.
  • Hello Robert,

    Thanks for the explanation. I was wondering which handler is being talked about!!

    Regards
    Amit