SAMA5 WDT: Miss watchdog fixes

This commit is contained in:
Gregory Nutt 2013-10-20 08:24:05 -06:00
parent 13ab1b586d
commit cc4c4f4593
4 changed files with 71 additions and 54 deletions

View File

@ -494,14 +494,29 @@ static void sam_copyvectorblock(void)
* Name: sam_wdtdisable
*
* Description:
* Disable the watchdog timer
* Disable the watchdog timer. The SAMA5 always boots with the watchdog
* timer enabled at its maximum timeout (16 seconds). The watchdog timer
* can disabled by writing to the Watchdog Mode Register (WDT_MR). The
* WDT_MR, however, can be written only one time after the CPU has been
* reset.
*
* So if no watchdog timer driver has been configured, the watchdog timer
* must be disabled as part of the start up logic. But, on the other
* hand, we must not write to the WDT_MR register if the watchdog timer
* driver is configured. In that case, some later application will
* configure the WDT and begin periodic pinging (within 16 seconds,
* hopefully).
*
****************************************************************************/
#ifndef CONFIG_SAMA5_WDT
static inline void sam_wdtdisable(void)
{
putreg32(WDT_MR_WDDIS, SAM_WDT_MR);
}
#else
# define sam_wdtdisable()
#endif
/****************************************************************************
* Public Functions

View File

@ -118,11 +118,11 @@ struct sam_lowerhalf_s
/* Register operations ******************************************************/
#if defined(CONFIG_SAMA5_WDT_REGDEBUG) && defined(CONFIG_DEBUG)
static uint16_t sam_getreg(uint32_t addr);
static void sam_putreg(uint16_t val, uint32_t addr);
static uint32_t sam_getreg(uintptr_t regaddr);
static void sam_putreg(uint32_t regval, uintptr_t regaddr);
#else
# define sam_getreg(addr) getreg32(addr)
# define sam_putreg(val,addr) putreg32(val,addr)
# define sam_getreg(regaddr) getreg32(regaddr)
# define sam_putreg(regval,regaddr) putreg32(regval,regaddr)
#endif
/* Interrupt hanlding *******************************************************/
@ -178,21 +178,21 @@ static struct sam_lowerhalf_s g_wdtdev;
****************************************************************************/
#if defined(CONFIG_SAMA5_WDT_REGDEBUG) && defined(CONFIG_DEBUG)
static uint16_t sam_getreg(uint32_t addr)
static uint32_t sam_getreg(uintptr_t regaddr)
{
static uint32_t prevaddr = 0;
static uint32_t count = 0;
static uint16_t preval = 0;
static uint32_t count = 0;
static uint32_t preval = 0;
/* Read the value from the register */
uint16_t val = getreg16(addr);
uint32_t regval = getreg32(regaddr);
/* Is this the same value that we read from the same registe last time? Are
* we polling the register? If so, suppress some of the output.
*/
if (addr == prevaddr && val == preval)
if (regaddr == prevaddr && regval == preval)
{
if (count == 0xffffffff || ++count > 3)
{
@ -200,7 +200,7 @@ static uint16_t sam_getreg(uint32_t addr)
{
lldbg("...\n");
}
return val;
return regval;
}
}
@ -219,15 +219,15 @@ static uint16_t sam_getreg(uint32_t addr)
/* Save the new address, value, and count */
prevaddr = addr;
preval = val;
prevaddr = regaddr;
preval = regval;
count = 1;
}
/* Show the register value read */
lldbg("%08x->%04x\n", addr, val);
return val;
lldbg("%08x->%048\n", regaddr, regval);
return regval;
}
#endif
@ -240,15 +240,15 @@ static uint16_t sam_getreg(uint32_t addr)
****************************************************************************/
#if defined(CONFIG_SAMA5_WDT_REGDEBUG) && defined(CONFIG_DEBUG)
static void sam_putreg(uint16_t val, uint32_t addr)
static void sam_putreg(uint32_t regval, uintptr_t regaddr)
{
/* Show the register value being written */
lldbg("%08x<-%04x\n", addr, val);
lldbg("%08x<-%08x\n", regaddr, regval);
/* Write the value */
putreg16(val, addr);
putreg32(regval, regaddr);
}
#endif
@ -304,6 +304,8 @@ static int sam_interrupt(int irq, FAR void *context)
static int sam_start(FAR struct watchdog_lowerhalf_s *lower)
{
FAR struct sam_lowerhalf_s *priv = (FAR struct sam_lowerhalf_s *)lower;
/* The watchdog timer is enabled or disabled by writing to the MR register.
*
* NOTE: The Watchdog Mode Register (WDT_MR) can be written only once. Only
@ -312,7 +314,7 @@ static int sam_start(FAR struct watchdog_lowerhalf_s *lower)
*/
wdvdbg("Entry\n");
return -ENOSYS;
return priv->started ? OK : -ENOSYS;
}
/****************************************************************************
@ -389,7 +391,7 @@ static int sam_keepalive(FAR struct watchdog_lowerhalf_s *lower)
****************************************************************************/
static int sam_getstatus(FAR struct watchdog_lowerhalf_s *lower,
FAR struct watchdog_status_s *status)
FAR struct watchdog_status_s *status)
{
FAR struct sam_lowerhalf_s *priv = (FAR struct sam_lowerhalf_s *)lower;
@ -403,7 +405,7 @@ static int sam_getstatus(FAR struct watchdog_lowerhalf_s *lower,
{
status->flags |= WDFLAGS_ACTIVE;
}
#ifdef CONFIG_SAMA5_WDT_INTERRUPT
if (priv->handler)
{
@ -494,7 +496,7 @@ static int sam_settimeout(FAR struct watchdog_lowerhalf_s *lower,
wdvdbg("reload=%d timout: %d->%d\n",
reload, timeout, priv->timeout);
/* Set the WDT_MR according to calculated value
*
* NOTE: The Watchdog Mode Register (WDT_MR) can be written only once. Only
@ -624,7 +626,7 @@ static xcpt_t sam_capture(FAR struct watchdog_lowerhalf_s *lower,
static int sam_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
unsigned long arg)
{
wdvdbg("Entry: cmd=%d arg=%ld\n", cmd, arg);
wdvdbg("cmd=%d arg=%ld\n", cmd, arg);
/* No ioctls are supported */
@ -636,7 +638,7 @@ static int sam_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
****************************************************************************/
/****************************************************************************
* Name: sam_wdtinitialize
* Name: up_wdginitialize
*
* Description:
* Initialize the WDT watchdog time. The watchdog timer is intialized and
@ -644,21 +646,29 @@ static int sam_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
* disabled.
*
* Input Parameters:
* devpath - The full path to the watchdog. This should be of the form
* /dev/watchdog0
* None
*
* Returned Values:
* None
*
****************************************************************************/
void sam_wdtinitialize(FAR const char *devpath)
int up_wdginitialize(void)
{
FAR struct sam_lowerhalf_s *priv = &g_wdtdev;
wdvdbg("Entry: devpath=%s\n", devpath);
wdvdbg("Entry: CR: %08x MR: %08x SR: %08x\n",
sam_getreg(SAM_WDT_CR), sam_getreg(SAM_WDT_MR),
sam_getreg(SAM_WDT_SR));
/* No clocking setup is required. The Watchdog Timer uses the Slow Clock
/* Check if some previous logic was disabled the watchdog timer. Since the
* MR can be written only one time, we are out of business if that is the
* case.
*/
DEBUGASSERT((sam_getreg(SAM_WDT_MR) & WDT_MR_WDDIS) != 0);
/* No clock setup is required. The Watchdog Timer uses the Slow Clock
* divided by 128 to establish the maximum Watchdog period to be 16 seconds
* (with a typical Slow Clock of 32768 kHz).
*/
@ -678,7 +688,9 @@ void sam_wdtinitialize(FAR const char *devpath)
/* Register the watchdog driver as /dev/watchdog0 */
(void)watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv);
(void)watchdog_register("/dev/watchdog0",
(FAR struct watchdog_lowerhalf_s *)priv);
return OK;
}
#endif /* CONFIG_WATCHDOG && CONFIG_SAMA5_WDT */

View File

@ -65,27 +65,6 @@ extern "C" {
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_wdtinitialize
*
* Description:
* Initialize the WDT watchdog timer. The watchdog timer is intialized and
* registered as 'devpath. The initial state of the watchdog time is
* disabled.
*
* Input Parameters:
* devpath - The full path to the watchdog. This should be of the form
* /dev/watchdog0
*
* Returned Values:
* None
*
****************************************************************************/
#ifdef CONFIG_SAMA5_WDT
void sam_wdtinitialize(FAR const char *devpath);
#endif
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -1006,7 +1006,7 @@ Configurations
5. The Real Time Clock/Calendar RTC) is enabled. These are the relevant
settings:
System Type:
CONFIG_SAMA5_RTC=y : Enable the RTC driver
@ -2152,7 +2152,7 @@ Configurations
Defaults should be okay for all related settings.
17. The Real Time Clock/Calendar RTC) may be enabled with these settings:
System Type:
CONFIG_SAMA5_RTC=y : Enable the RTC driver
@ -2182,13 +2182,24 @@ Configurations
CONFIG_WATCHDOG=y : Enables watchdog timer driver support
Application Configuration -> Eamples
CONFIG_EXAMPLES_WATCHDOG=y : Enable the apps/examples/watchdog
CONFIG_EXAMPLES_WATCHDOG=y : Enable apps/examples/watchdog
The WDT timer is driven off the slow, 32768Hz clock divided by 128.
As a result, the watchdog a maximum timeout value of 16 seconds. The
SAMA5 WDT may also only be programmed one time; the processor must be
reset before the WDT can be reprogrammed.
The SAMA5 always boots with the watchdog timer enabled at its maximum
timeout (16 seconds). In the normal case where no watchdog timer driver
has been configured, the watchdog timer is disabled as part of the start
up logic. But, since we are permitted only one opportunity to program
the WDT, we cannot disable the watchdog time if CONFIG_SAMA5_WDT=y. So,
be forewarned: You have only 16 seconds to run your watchdog timer test!
NOTE: If you are using the norboot program to run from FLASH as I did,
beware that the default version also disables the watchdog. You will
need a special version of norboot with CONFIG_SAMA5_WDT=y.
STATUS:
PCK FREQUENCY