[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