Watchdog - Is this code correct implementation?

About to add watchdog I am.

The code described on page 85 of the Beginner’s Guide didn’t quite work for me when I tried it and I would like to know if the following example correctly implements the watchdog function. The main changes from the Beginner’s Guide code were the syntax used to reference the GHI watchdog class.

Since I’m going to be inserting the watchdog function into a large piece of code that does a number of functions, I wanted to make sure I’ve understood the concept and syntax. Please advise if you see errors or poor coding if you have a minute. It does seem to work on the Panda II on which it is currently deployed.

Thanks in advance.

// 5/12/11 -  Watchdog test program - adapted from Beginner's Guide page 85 

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware.LowLevel;

using GHIElectronics.NETMF.FEZ;

namespace Watchdog
{
    public class Program
    {
        public static void Main()
        {
            // Timeout 5 seconds
            int i = 0;
            uint timeout = 1000 * 5;
            // Enable Watchdog using GHI code
            GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.Enable(timeout);
            // Start a time counter reset thread
            WDTCounterReset = new Thread(WDTCounterResetLoop);
            GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.ResetCounter();
            // dummy program starts here - just print integers 1-20 & then execute some bad code to throw an exception
            while (true)
            {
                while (i < 20)
                {
                    Debug.Print(" ticking right along ... " + i.ToString());
                    i++;
                }

                // start of bad code block used to throw an unhandled exception
                Debug.Print(" now try to throw exception" + i.ToString());
                // byte dc = 0, Dcm = 0;
                uint dknt = 0;
                byte[] wb = new byte[4];
                byte[] rb = new byte[3]; // byte[3] throws an unhandled exception, 4 is ok
                wb[0] = 10;
                GHIElectronics.NETMF.Hardware.BatteryRAM.Read(dknt, rb, 0, 4);
                Debug.Print("BRAM location " + dknt.ToString() + " = " + rb[0].ToString());
                i = 0;
                //end of bad code block

            }
            // If we exit the program, 
            // the thread will stop working and the system will reset!
        }
        static Thread WDTCounterReset;
        static void WDTCounterResetLoop()
        {
            while (true)
            {
                // reset time counter every 3 seconds
                Thread.Sleep(3000);
                GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.ResetCounter();
                // next line was from Beginner's Guide example - doesn't point to GHI code for watch dog
                // Watchdog.ResetCounter();
            }
        }
    }
}

As far as I can tell you never start the thread so it will just reset with this code. Here’s what I use and works well and all the code is nicely contained in one block. Just add this and call StartWatchdog() before you start doing anything else.


        private static Thread restartThread = null;
        private static bool HasReset = false;
        private static void StartWatchdog()
        {
            if (GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.LastResetCause == GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.ResetCause.WatchdogReset)
            {
                HasReset = true;
                Debug.Print("Restarted after watchdog reset");
            }

            //device will reboot if counter hasn't been reset within 20 seconds
            GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.Enable(20000);
            Debug.Print("Watchdog enabled");

            //reset every 3 seconds in background thread
            restartThread = new Thread(() =>
            {
                try
                {
                    while (true)
                    {
                        Thread.Sleep(3000);
                        GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.ResetCounter();
                    }
                }
                catch (Exception ex)
                {
                    Debug.Print("Unable to reset watchdog: " + ex.Message);
                }
            });
            restartThread.Start();
            Debug.Print("Watchdog reset thread started");
        }

Thanks, Paul B.

I appreciate and will study your example which appears better constructed than mine. To help me understand your cooment though, doesn’t


            GHIElectronics.NETMF.Hardware.LowLevel.Watchdog.Enable(timeout);
            // Start a time counter reset thread
            WDTCounterReset = new Thread(WDTCounterResetLoop);

start the thread ? Also isn’t the purpose of watchdog to cause a reset? I have a feeling I’m missing some key concept here.

Your line where you declare WDTCounterReset only creates the thread object, you need to implicitly start the thread by calling WDTCounterReset.Start(). after you create the thread object. Paul’s code does the same thing as yours, but uses anonymous delegates to do the same thing. From a beginners standpoint, your approach is easier to read and understand…

Pauls code creates a delegate thread (the thing after the =>) declared inline inside the function call. To use his code, you would call the StartWatchdog() function from your main code, what is difficult to understand for most beginners is that the inline code will continue to run even after the function exits.

That helps, Ron2 - thanks. Didn’t know there were such things as delegate threads - back to the manual. I’m still having a bit of difficulty getting the code to work properly so I’ll take what you’ve provided and do some more testing. If I get a fairly clean piece of code, I’ll repost for critique.

I tried taking Paul’s code putting a StartWatchdog() in main followed by the exception throwing snippet, but all I got was a hang with no reset. I’m obviously missing something but I’ll try to figure it out first.