Search code examples
cembeddedwatchdog

Programming in presence of watchdog timer


I am new to embedded systems programming, although I have done courses during studies, practical programming is still a bit further away.

Here is the problem: I have to program a small system on NXP LPC2103 microcontroller (ARM 7 based), without an operating system. It has a watchdog timer which needs to be regularly updated. The system has a GPRS modem with TCP/IP stack embedded, and initializing this takes time longer than the watchdog needs to timeout. When I call the initialization function, the system resets.

I spoke to a more experienced colleague and he suggested that I need to exit and reenter the same initialization function from the main function in which I bite the watchdog timer so long until the function finishes executing. The idea sounds good, but I would like to also hear some other experiences. Also, a reference (book or website) could be also useful, because I couldn't find anything specific to this.

I wouldn't like to call watchdog timer from the initialization function, I don't find this good.


Solution

  • I wouldn't like to call watchdog timer from the initialization function, I don't find this good.

    It might be overkill for this one situation, but a general technique I've used for long running operations where you might want to perform other work is to have the long running function accept a callback function pointer that will be periodically called. The pattern that I usually use is to have a callback prototype that might look like:

    int (callback_t*)(void* progress, void* context);
    

    The long running function will periodically call the callback, with some information that indicates it's progress (how that progress is represented to what it means is dependent on the details of the particular function) and with a context value that the original caller passed in along with the callback pointer (again - what that parameter means and how it's interpreted is entirely up to the callback). generically, the return value of the callback function might be used to indicate that the 'long running thing' should cancel or otherwise change behavior.

    This way, your initialization function can take a callback pointer with a context value, and just periodically call it. Obviously, in your situation, those callbacks would have to occur often enough to keep the watchdog happy.

    int watchdog_callback( void* progress, void* context)
    {
        kick_the_watchdog();
    
        return 0;  // zero means 'keep going...'
    }
    
    
    void init_modem( callback_t pCallback, void* callback_context)
    {
        // do some stuff
    
        pCallback( 0, callback_context);
    
        // do some other stuff
    
        pCallback( 1, callback_context);
    
    
        while (waiting_for_modem()) {
             // do work...
    
             pCallback( 2, callback_context);
        }    
    }
    

    One nice thing about this pattern is that it can be used in different situations - you might have a function that reads or writes a large amount of data. The callback pattern might be used to have something display the progress.

    Note that if you find that you have other long-running functions, the same watchdog_callback() function could be used to allow them to deal with preventing the watchdog from reseting. However, if you find yourself needing to rely on this type of thing often for the watchdog in particular, then you might need to consider how your tasks are interacting and either break them down more or use a more complex watchdog scheme that has the watchdog managed by its own task that other tasks interact with to keep the watchdog timer happy indirectly.