[En-Nut-Discussion] SAM7 watchdog driver

Ben Hoyt benhoyt at gmail.com
Mon Sep 11 02:40:04 CEST 2006


Hi, I noticed the "AT91" watchdog driver was only good for the R40008 and
not the SAM7. I'm using a SAM7S256 (essentially the same as the 7X256) and
so I've written watchdog routines for that -- admittedly very trivial.

Note that the AT91 watchdog mode register (which control all watchdog
features/timeouts) can only be written once per processor reset. This is a
kind of safety feature, but it does mean you can't really enable and disable
the watchdog on the SAM7.

Also note that I had to comment out the watchdog disable lines in the
assembly startup code, otherwise I couldn't do anything useful with the
watchdog in my code -- again, because it's write-once.

Cheers,
Ben.

-----
// NutOS watchdog code for AT91SAM7 - Ben Hoyt - 9 Sep 2006

#include <dev/watchdog.h>

#define SLOWCLK_FREQ 32768
#define WDTCNT_FREQ (SLOWCLK_FREQ/128)

// These functions are called by the platform independent Watchdog API
// That is, the NutWatchDogFOO() functions in dev/watchdog.c

// Note that the AT91SAM7 watchdog mode register can only be written once.
// This means you must call either NutWatchDogStart or NutWatchDogDisable
// once and only once. Also, you must comment out the watchdog disable
// in the startup assembler code (in crtat91sam7x256_rom.S in my case).

// Start watchdog timer with timeout in milliseconds
// xmode is a hardware-dependent parameter which means:
// xmode = 0 means normal operation
// xmode > 0 means you can't reset watchdog within xmode/256 second window;
//           this is to prevent a software loop continuosly restarting it
//           (see AT91SAM7 watchdog documentation for more info)
u_long Sam7WatchDogStart(u_long ms, u_long xmode)
{
    u_long ticks;

    // convert milliseconds to slow clock ticks (rounded)
    ticks = (ms*WDTCNT_FREQ+500)/1000;

    // maximum is 16 seconds (or just under)
    if (ticks>0xFFF)
        ticks = 0xFFF;

    // enable reset, set up counter value and delta value
    outr(WDT_MR, WDT_WDRSTEN | ticks | (ticks-xmode)<<16);

    // return actual timeout value (again, rounded)
    return (ticks*1000+WDTCNT_FREQ/2)/WDTCNT_FREQ;
}

// Restart watchdog counter
void Sam7WatchDogRestart(void)
{
    outr(WDT_CR, WDT_KEY | WDT_WDRSTT);
}

// Disable watchdog
void Sam7WatchDogDisable(void)
{
    outr(WDT_MR, WDT_WDDIS);
}

// Enable watchdog (do nothing - SAM7 watchdog mode register can only be
// written once)
void Sam7WatchDogEnable(void)
{
}
-----

-- 
Ben Hoyt
Mobile: +64 21 331 841
Email: benhoyt at gmail.com



More information about the En-Nut-Discussion mailing list