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.

TM4C129ENCPDT: Watchdog timer is not working

Other Parts Discussed in Thread: TM4C129ENCPDT, SYSCONFIG, SYSBIOS

My code for watchdogtimer0 is (header file inc/tm4c129encpdt.h is included) -

SYSCTL_RCGCWD_R = 0x1; // enable and provide clock to watchdog timer, system clock which is 120Mhz
WATCHDOG0_LOAD_R = 0xffffffff; // full scale value given to counter gives timout around 35sec
WATCHDOG0_CTL_R = 0x02; // enable the reset
while(1);

When I am running this code, at first the device gets resets just after it executes this line-
WATCHDOG0_CTL_R = 0x02; // enable the reset

And in the second run after reset, it sticks into while(1) loop for sometimes and goes somewhere else. But watchdog is not working.
I am calling this code into some task created by me which has a low priority than other tasks. I am sure the code is executing these lines and then after that the task gets preempted when I enter into while loop.

Is my code write for watchdog timer 0?


Thanks
akhi

  • Hello Akhilesh,

    You need to enable the Watchdog timer through SysConfig. The Watchdog is supported in TI-RTOS for Tiva-C natively so there is no reason to use direct register calls to activate it. I suspect what is occurring is that the BIOS does not expect the Watchdog to be running as it is not configured in SysConfig and therefore when it triggers it is causing unexpected behavior.

  • Hi,

    How to do that through sysconfig? Can you guide with some examples?

    Thanks

  • Hello Akhilesh,

    I stand slightly corrected about the SysConfig piece in that you don't need to explicitly enable it there. But what you do need to do is call the API's to create and enable to the Watchdog through the BIOS.

    We have a Watchdog example as part of the TI-RTOS for Tiva-C example project offerings so I would recommend starting there. It will show you all the calls used to initialize the watchdog and register the callback function to handle feeding the watchdog. I think that should give you everything you need as the Watchdog is rather simple to setup.

    You can find it here:

  • Hi,

    I got this. But I am a bit confused about a timeout in watchdog. I seeing my watchdog interrupt callback is called every second. It means the timeout is set for 1 sec. But my system clock is 120MHz and I know watchdog timer count is of 32bit register. So I must get around 35 sec of timeout. How to change the timeout ?

    Thanks

  • Hello Akhilesh,

    The Watchdog_setReload API can be used to adjust the interval of the Watchdog. If it is running at 1 second right now, the value loaded was then 120000000. You can adjust that value to get more or less time for the interval. You would pass watchdogHandle as your handle and then the new count for the timeout as the value.

  • Hi Jacobi,

    I got it working. The only issue left when I set it for reset and the callback function is provided, instead of getting reset. the device is going into the callback function. If reset is on and the callback is not provided, the device is just not getting stopped, neither reset.

    I am assuming it should get reset. But that's not working.

    Thanks

     

  • Hello Akhilesh,

    Can you post the code for your Callback function?

  • Hi,

    This is the code. Also, I am not able to use print statements inside the callback and I think that is a valid part. 

    void watchdogCallback(uintptr_t unused)
    {
        /* Clear watchdog interrupt flag */
        Watchdog_clear(watchdogHandle);
        static int count1 = 0;
        countArray[count1++] = Seconds_get();
        if(count1 > 1000) count1 = 0;
       // rebootToRestore();
      //  print("inside watchdog callback\n");flush();
    }
    

    Thanks

  • Hello Akhilesh,

    Okay that is how I suspected your callback would be configured.

    To get the system to reset, you need to not clear the Watchdog interrupt flag during a callback. Then the next time the Watchdog interrupt fires, it will reset the system.

    So you would put the Watchdog_clear(watchdogHandle); API inside of a conditional that will be true until you want a system reset to occur. Then the system will run until that conditional statement is not entered when you are trying to trigger the Watchdog reset.

    I usually use printf and not print by the way, maybe try that?

  • HI Jacobi,

    I tried that. I tried removing the watchdog_clear from the callback. After this, at first, the watchdog is taking 36 seconds to come into the callback. After this, it is going into callback again and again very frequently. It should reset. I read from the datasheet that if you don't clear the interrupt, on the second countdown to zero, the device will get reset. But it is not happening.

    void watchdogCallback(uintptr_t unused)
    {

    }

    Thanks

    akhi

  • Hello Akhilesh,

    I've not tried using a blank callback before... it could be the compiler or the RTOS isn't sure how to handle that. I would suggest doing something simple like having a variable that starts at zero and increments, on your first entry if the value is 0, clear the watchdog. Then on your second entry if the value is non-zero (which it should be), don't clear the watchdog and see what happens.

  • Hi Jacobi

    I tried that too. The moment watchdog is not getting clear, it is keep coming into callback

  • Hello Akhilesh,

    Alright so it looks like the example put together for the Watchdog is rather poor. I changed how it functions to get it to work.

    First off, I think maybe what you need in your program is to change params.resetMode to be equal to Watchdog_RESET_ON. Without this change, the system reset does not occur.

    Now to make the TI-RTOS example work as I expect for Watchdog reset I did the following:

    1) Removed the Watchdog_clear from taskFxn.

    2) Adjusted the Callback to work as follows:

     /*
     *  ======== watchdogCallback ========
     *  Watchdog interrupt callback function. It toggles and LED, and if a button
     *  has not been pressed, clears the watchdog interrupt flag.
     */
    void watchdogCallback(uintptr_t unused)
    {
        /* Clear watchdog interrupt flag */
        /* Prevent Watchdog ISR trigger if button was pushed */
        if (!flag) {
            Watchdog_clear(watchdogHandle);
        }
        GPIO_toggle(Board_LED0);
    }
    

    With this, when I press the SW1 button, the LED blink stalls and then resumes after reset and the debugger is not connected to the CPU anymore indicating it successfully reset.

    See if this information gets the Watchdog working correctly for your system.

  • Hi Jacobi,

    I am pasting my complete code. I am doing the same thing but I don't have button as it is custom board. 

        Board_initWatchdog(); // akhilesh
    	Watchdog_Params watchdog_params;
    	Watchdog_Params_init(&watchdog_params);
    	watchdog_params.resetMode = Watchdog_RESET_ON;
    	watchdog_params.callbackFxn = (Watchdog_Callback)watchdogCallback;
    	watchdogHandle = Watchdog_open(Board_WATCHDOG0, &watchdog_params);
    	if (watchdogHandle == NULL) {
    		logg("watchdog failed", __FUNCTION__);
    	}
    	Watchdog_setReload(watchdogHandle, 0xffffffff);
    
    void watchdogCallback(uintptr_t unused)
    {
        static int count1 = 0;
        countArray[count1++] = Seconds_get();
    
        if(count1 > 1000) count1 = 0;
    }
    
    

    This must work but after first ISR, it is keep coming into callback again and again very freq. It should reset on the second callback after 36 sec. But second callback is called immediate after the first callback and it goes on. 

    Thanks

  • Hello Akhilesh,

    I was able to re-create the behavior you are seeing and it looks to be related to the lack of clearing the Watchdog ever.

    If I add in this line immediately after the setReload, then the Watchdog operates as expected:

    Watchdog_clear(watchdogHandle);

    Again ideally you should be making such calls in your Watchdog handler and I am not sure why you don't have that inside of it, but if this works for your purpose then you can make the call after setReload and the Watchdog will trigger the system reset. It just takes a long time but after two cycles of the Watchdog timer I get the message: CORTEX_M4_0: Trouble Halting Target CPU which indicates the Watchdog restarted the system.

  • Hi Jacobi,

    I don't know what I am doing wrong. I tried everything but the system rest is not happening. If I am not clearing the watchdog, then it keeps coming inside callback very frequently even if I do setReload. Also, I tried to first let it come inside watchdog callback, then clear the interrupt, set the reload, then on the next time, I am not clearing the watchdog but I set the reload ( I tried with not to set also) and it should reset this time. Again, the same behavior.

    Also, is it maskable interrupt? Because from the datasheet, if it is non-maskable, then it has a higher priority than exceptions which is the need. I want this watchdog to make it non-maskable. How to do that?

    Thanks

  • Hello Akhilesh,

    Can you export your CCS project to a .zip file and attach it onto your next reply? I can try and run it myself and make any modifications to make it work if I observe the same behaviors.

    AKhilesh Gangwar said:
    Also, is it maskable interrupt? Because from the datasheet, if it is non-maskable, then it has a higher priority than exceptions which is the need. I want this watchdog to make it non-maskable. How to do that?

    It doesn't look like this is well supported in TI-RTOS. For starters I think you will need to make a direct TivaWare call for WatchdogIntTypeSet to configure that.

    However then it gets murkier because I could not find much reference to use NMI with TI-RTOS for Tiva-C. This post has some details but that is all I was able to find so far: https://e2e.ti.com/support/legacy_forums/embedded/tirtos/f/355/t/375721

    Are you sure that you can't just bump up the priority on the Watchdog timer? I haven't really come across any case that anyone needed the Watchdog to be used as an NMI before... it feels like overkill for me. This post by a community member walks through the real impact of an NMI and why using one must be done with care: https://e2e.ti.com/support/microcontrollers/other/f/908/p/389894/1379105#1379105

  • Hi Jacobi,

    I was able to get 

    CORTEX_M4_0: GEL Output:
    Memory Map Initialization Complete
    CORTEX_M4_0: Error: Stat [ JLINKARM_IsHalted() call ] failed! 

    which I am assuming is reset when my debugger was connected. I commented the code 

    watchdog_params.callbackFxn = (Watchdog_Callback)watchdogCallback;

    Now it is not going into that callback. My timeout is set to 36 seconds and after 72 sec, I am getting the above message.

    Now few doubt arises.

    1. Shouldn't if the callback is defined, I must get the same behavior as I am getting now. Because now also, there is no watchdog clear is happening, and previously also was the same.

    2. If it is resetting the system, my code executing must go to the start of the program and from there, it must execute the code. Why am I getting this error?

    3. On NMI, let me check your links, and then I'll come back.

    Thanks for your support

    Regards

    akhi

  • Hello Akhilesh,

    That is one way to get to reset I suppose but that isn't a good one because with the callback setup your system is doomed to restart every 72 seconds with no way to stop it.

    AKhilesh Gangwar said:
    2. If it is resetting the system, my code executing must go to the start of the program and from there, it must execute the code. Why am I getting this error?

    On the restart of the system, the debug connection is severed and so you must reconnect to the target with your JTAG probe.

  • Hi Jacobi,

    I can not send the whole project. I am pasting my watchdog code. Let me know other dependencies, I can send you those as well.

    I am using ti rtos 2.16.01.14,  xdc tools 3.32.00.06,  ccsv6

    void watchdogCallback(uintptr_t unused)
    {
    
        static int count1 = 0;
        countArray[count1++] = Seconds_get();
    
    
        if(count1 < 3){
            Watchdog_clear(watchdogHandle);
    
        }
    //    Watchdog_setReload(watchdogHandle, 0xefffffff);
    //    Watchdog_clear(watchdogHandle);
    //  //  print("inside watchdog callback\n");flush();
    //  //  GPIO_toggle(Board_LED0);
    }
    
    
    // inside main function
        Board_initWatchdog(); // akhilesh
    	Watchdog_Params watchdog_params;
    	Watchdog_Params_init(&watchdog_params);
    	watchdog_params.resetMode = Watchdog_RESET_ON;
    	watchdog_params.callbackFxn = (Watchdog_Callback)watchdogCallback;
    	watchdogHandle = Watchdog_open(Board_WATCHDOG0, &watchdog_params);
    	if (watchdogHandle == NULL) {
    		logg("watchdog failed", __FUNCTION__);
    	}
    	Watchdog_setReload(watchdogHandle, 0xfffffff);
    	// Watchdog_clear(watchdogHandle);
    

    Thanks

  • Hello Akhilesh,

    I implemented your code in my example project and it is working fine for me. I get to count1 = 1, clear Watchdog, count1 = 2, clear Watchdog, and then I don't get into that if statement and the system resets as expected.

  • Hi,

    I am attaching the minimum working project on which I had tested and got the same behavior as previously. If I removed the callback, it is working fine.

    PFA

    petromo-tgt-wifi.zip

    Thanks

  • Hello Akhilesh,

    I was unable to get the actual project you had working due to a large number of build errors. Even after a couple hours of trying to work through them I ended up at a point where I did not know how else to fix it.

    That said, I took the code from your main.c file and replaced my watchdog project with it, added the required sysbios modules, and I got the following result:

    38176:Starting Main
    inside task... sleeping
    inside task... sleeping
    inside task... sleeping
    inside task... sleeping
    FSR = 0x0000
    HFSR = 0x40000000
    DFSR = 0x0000000b
    MMAR = 0xe000ed34
    BFAR = 0xe000ed38
    AFSR = 0x00000000
    Terminating execution...

    So that code is working as expected as well.

  • Hi Jacobi,

    That is the exception you got, not reset. If you see inside the callback, I am incrementing the count1 variable to infinity but not making it zero as the array, countArray has the size limit of 1024. if you put this line into callback,

    if(count1 >= 1023) count1 = 0;

    you will not see that exception. 

    Also, as you said you are getting build errors, did you change the paths from compiler settings and project path and for ti rtos and xdc tools, because those may be the build error you got.

    Thanks

  • Hello Akhilesh,

    Alright so I did some further investigation into this after observing your point about the exception being hit rather than the Watchdog occurring.

    First of, couple points I found:

    1) If the Watchdog is loaded to the standard 1 second rate, then the issue does not occur and the watchdog reset is triggered properly.

    2) If I use an if statement to reset the count1 variable to 2 when it would overflow, then the issue does not occur and the watchdog reset is triggered properly.

    I think the issue you are seeing is due to a mix of the long time period of the watchdog plus the way the RTOS kernel works, but I am not certain. I am not deeply familiar with the RTOS kernel but I believe what is happening is that on every tick of the system, the watchdogCallback is being entered and executed by the BIOS because it is not cleared. But the hardware for the TM4C is not trying to access it and therefore a reset is not triggered. Eventually the hardware then will try and trigger the Watchdog and that provides the reset. Why that repeated access of the watchdogCallback is occurring is something that I am not really certain of however.

    From digging into the Watchdog code provided, the watchdogClear function only serves to call the TivaWare WatchdogIntClear API. I don't see anything else being done to it. It may be a bug in the implementation that hasn't been observed because of the excessively long and unusual timeout window you are trying to use here.

    I would suggest you use the watchdog as intended which is with a narrower timeout value and then you should not see any issues.

  • Hi Jacobi,

    It is not working if I use other than standard timeout which is 1sec. I think this is a bug because the watchdog counter register is a 32bit and I am using the value 0xffffffff which the max value. 

    Is there any other way to do that? You said it is working fine in your project. How were you using it? Did you set the timeout other than 1 sec, with a reset on and callback defined??

    Thanks

  • Hello AKhilesh,

    AKhilesh Gangwar said:
    It is not working if I use other than standard timeout which is 1sec. I think this is a bug because the watchdog counter register is a 32bit and I am using the value 0xffffffff which the max value. 

    Well if you don't have an array that overflows and are only using the Watchdog for it's purpose of resetting the CPU with the only code inside being clearing the flag based on a condition then there may not be harm if the Watchdog is entered on every cycle.

    Honestly I was thinking through this further and here is what I think happens:

    1) Watchdog is configured in Hardware and in BIOS, and the Hardware will interrupt a X internal based on your definition.

    2) When the hardware interrupt occurs, and the Flag is not cleared so the next interrupt would trigger the Watchdog.

    3) The BIOS on the System Tick looks through for interrupts and sees the Watchdog interrupt has been triggered and enters it. This continues until the timer runs out so the Hardware is aware.

    So the biggest issue is the lack of efficiency you'd have in the system or if you have a situation where entering every tick causes an overflow.

    AKhilesh Gangwar said:
    Is there any other way to do that? You said it is working fine in your project. How were you using it? Did you set the timeout other than 1 sec, with a reset on and callback defined??

    I did not have an array that could overflow in the Watchdog handler, so the system was entering every tick but did nothing until the hardware reset occurred. I can do that for any count.

    By the way I suspect even if you set the count to 1sec, it will still enter every tick, but you just aren't seeing it with the shorter interval.

  • Hi Jacobi,

    If you do something like this-

    void watchdogCallback()
    {
        countArray[count1++] = Seconds_get();
        if(count1 < 3){
            Watchdog_clear(watchdogHandle);
    
        }
        if(count1 == 3)
        	WatchdogIntUnregister(0x40000000);
    
    }

    It is working as expected for any timeout period. Basically, that interrupt was causing the issue. I want to reset after some specific timeout says 3x36 sec, I will count the count1 variable like this and will be clearing the watchdog, once it is done, I'll unregister the interrupt and won't clear the watchdog, on the next count to zero, I am seeing the reset. Because we are registering an interrupt, maybe no cleaning this particular interrupt is causing the issue which can be fixed with this. 

    After thoroughly seeing what is happening, I conclude this, and I have this workaround.

    Let me know your thoughts on this.

    Also, no print statement is working inside the callback. It is giving reset. 

    Thanks

  • Hello Akhilesh,

    That's a rather interesting solution and one I hadn't thought of but it does make sense for this particular case if it is done correctly.

    First off, this really only works for the Watchdog because of the nature of what will happen when the Watchdog timeout is triggered after not clearing the interrupt. Namely, what this relies on the nature of how the Watchdog resets the system. The Watchdog Timer is what initiates the reset, and the ISR is used to clear the flag so the Timer continues without resetting. If the flag should not be cleared, then the ISR is not relevant anymore as that is the only purpose for it and the Timer will handle the reset. I think you are aware of this, but I want to make that clear for anyone else who might read this thread.

    I think this is the only situation I would ever condone using the IntUnregister TivaWare API in the midst of a TI-RTOS application. What you are basically doing is removing an interrupt in hardware without telling the kernel that you are doing so. So it will still be looking for the Interrupt Flag, but it won't see it and therefore does not have any errors and does not enter the ISR, and there is no risk of impacting the system to my knowledge.

    Also interesting to note is that there isn't a TI-RTOS API that even handles this for completely disabling the Watchdog with TM4C:

    /*
     *  ======== WatchdogTiva_close ========
     */
    void WatchdogTiva_close(Watchdog_Handle handle)
    {
        /* Not supported for Tiva */
        Assert_isTrue(false, NULL);
    }

    One last comment here is that, you would need code anywhere else that Watchdog_clear(watchdogHandle); is called to ensure that the Watchdog interrupt has been properly registered and enabled again. If that appears no where else in your system, good, but just wanted to make that point.

  • Hi Jacobi,

    Thanks for clearing this. Now that my watchdog is working as I want it to, I have some questions.

    When there is an exception, the execution goes into abort function which looks like this-

    void abort(void)
    {
        loader_exit();
        for (;;);   /* SPINS FOREVER */
    }
    

    I tried to comment loader_exit() and then my code hangs into for loop forever. Now that I expect my watchdog to reset itself when it goes into this for loop inside the abort function, it is not happening. 

    Is there any way to come out from this abort function??

    Thanks

  • Hello Akhilesh,

    I would expect the Watchdog should break you out of the function if it is configured right... I am not aware of any other ways to exit that function.

    Can you check if while in the for loop if the Watchdog flag is not being cleared?

    I'm wondering if somehow with the BIOS hanging in that loop if maybe the Watchdog ends up being cleared somehow.

  • Hi Jacobi,

    The watchdog is working fine. Also, the WDT_RIS and WDT_MIST registers are set to 1 which means the watchdog timeout event has occurred and its time-out event has been signaled to the interrupt controller.

    But again, nothing is happening. I expected a reset from this stage but no reset at all. Even the control never goes into watchdog interrupt callback.

    One more thing, the watchdog counter is working all fine. It goes to zero and starts counting from 0xffffffff to 0. But no reset is happening. I am not able to get back from this function which is the main reason I want to implement the watchdog (also the main purpose of watchdog is this).

    I am attaching the screenshot. 

    Thanks

    Akhilesh

  • Hello Akhilesh,

    Is it possible for you to provide another CCS project where I can re-create this and debug? I want to delve into more registers for the System Control of the device and the reset modules. 

  • Hi Jacobi,

    I am attaching the .zip project and also a screenshot that shows where my paths for ti rtos and other things re, so that you can build it without build errors. 

    TI RTOS - tirtos_tivac_2_16_01_14

    XDC- xdctools_3_32_00_06_core

    Code composer studio- CCSv6 with compiler - ti-cgt-arm_5.2.5

    Few things to be noted-

    1. I have registered my own exit and abort function inside the .cfg file.

    2. I am explicitly creating the buffer overflow inside the taskFunc() which is causing an exception in order to go into the exit function. 

    4336.petromo-tgt-wifi.zip

  • Hello Akhilesh,

    I have the project running but I am still debugging. I will give another update tomorrow.

  • Hello Akhilesh,

    It took a while to really uncover what is going on and the problem is actually with what you presumed was fixing your issue.

    WatchdogIntUnregister(0x40000000);

    That API is causing a system fault and messing with the Watchdog at the same time. And specifically, it is the API in it which edits the vector table.

    I changed from using that to using:

    IntDisable(34);

    34 is the Watchdog interrupt. With this, I was able to get the Watchdog resets from the exit function.

    See if that will work for your purposes. In any case, it looks like WatchdogIntUnregister is incompatible with TI-RTOS and cannot be used. Hopefully IntDisable works...

  • Hi Jacobi,

    Are you able to go into that exit() function and it is resetting from there? Because for me, once it goes into that for(;;) loop inside the exit function, the execution never goes into the watchdog callback. Also, if I put this IntDisable inside the exit function before for(;;) loop, even though I am not able to get reset from watchdog once the execution goes into the for loop of exit function. Ans yes, the watchdog keeps going on again and again.

    As per document, watchdog priority is 34. And that exit function is called because of some exception( manually created exception inside the taskfxn) and the priority of the exceptions are higher than watchdog. That's why even though watchdog is running, it is not able to reset from the exit function. I tried to make watchdog NMI using its registers (from datasheet it is given how to make it NMI) but nothing works out.

    Thanks

  • Hello Akhilesh,

    AKhilesh Gangwar said:
    Are you able to go into that exit() function and it is resetting from there? Because for me, once it goes into that for(;;) loop inside the exit function, the execution never goes into the watchdog callback.

    Yes but only after removing the WatchdogIntUnregister call.

    I also had adjusted the sleep duration of the Task because the Watchdog reset was triggering before the buffer overflow. I used 100 instead of 10000 for a delay for the task sleep.

    With that, the buffer overflow occurred before the Watchdog interrupt was unregistered and then in the exit function I got the system reset.

    Again the solution here is that you cannot use WatchdogIntUnregister. If you want I can attach the CCS project where I have it working as you are trying to do.

  • Hi Jacobi,

    This is my log-

    inside task... sleeping
    inside task... sleeping
    inside task... sleeping
    inside task... sleeping
    inside task... sleeping
    inside task... sleeping
    FSR = 0x0000
    HFSR = 0x40000000
    DFSR = 0x00000000
    MMAR = 0xe000ed34
    BFAR = 0xe000ed38
    AFSR = 0x00000000
    Terminating execution...
    my exit frunction... sleeping
    

    and it never resets. 

    Can you please attach the project? 

    Thanks

  • Hello Akhilesh,

    After the time for the Watchdog elapses, can you try and pause the code? If so does it pause in the exit function?

    Because for me when I get the reset, then the debug connection is severed but that isn't indicated until I try and pause the debugger. Once I do so, then it realizes that and leaves a message:

    CORTEX_M4_0: Error: Debug Port error occurred.
    CORTEX_M4_0: Trouble Halting Target CPU

  • Hi Jacobi,

    That was the issue. Even if I pause the debugger before the timeout, the behavior is changing. If I don't touch it before the timeout and pause the debugger once the second timeout elapses, I am seeing the reset.

    Thanks for the help. I am testing more on it and will let you know.

    Thanks,

    Akhi