SAMA5 WDT: Miss watchdog fixes
This commit is contained in:
parent
13ab1b586d
commit
cc4c4f4593
@ -494,14 +494,29 @@ static void sam_copyvectorblock(void)
|
|||||||
* Name: sam_wdtdisable
|
* Name: sam_wdtdisable
|
||||||
*
|
*
|
||||||
* Description:
|
* 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)
|
static inline void sam_wdtdisable(void)
|
||||||
{
|
{
|
||||||
putreg32(WDT_MR_WDDIS, SAM_WDT_MR);
|
putreg32(WDT_MR_WDDIS, SAM_WDT_MR);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
# define sam_wdtdisable()
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
|
@ -118,11 +118,11 @@ struct sam_lowerhalf_s
|
|||||||
/* Register operations ******************************************************/
|
/* Register operations ******************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_SAMA5_WDT_REGDEBUG) && defined(CONFIG_DEBUG)
|
#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 void sam_putreg(uint16_t val, uint32_t addr);
|
static void sam_putreg(uint32_t regval, uintptr_t regaddr);
|
||||||
#else
|
#else
|
||||||
# define sam_getreg(addr) getreg32(addr)
|
# define sam_getreg(regaddr) getreg32(regaddr)
|
||||||
# define sam_putreg(val,addr) putreg32(val,addr)
|
# define sam_putreg(regval,regaddr) putreg32(regval,regaddr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Interrupt hanlding *******************************************************/
|
/* Interrupt hanlding *******************************************************/
|
||||||
@ -178,21 +178,21 @@ static struct sam_lowerhalf_s g_wdtdev;
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_SAMA5_WDT_REGDEBUG) && defined(CONFIG_DEBUG)
|
#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 prevaddr = 0;
|
||||||
static uint32_t count = 0;
|
static uint32_t count = 0;
|
||||||
static uint16_t preval = 0;
|
static uint32_t preval = 0;
|
||||||
|
|
||||||
/* Read the value from the register */
|
/* 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
|
/* 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.
|
* 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)
|
if (count == 0xffffffff || ++count > 3)
|
||||||
{
|
{
|
||||||
@ -200,7 +200,7 @@ static uint16_t sam_getreg(uint32_t addr)
|
|||||||
{
|
{
|
||||||
lldbg("...\n");
|
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 */
|
/* Save the new address, value, and count */
|
||||||
|
|
||||||
prevaddr = addr;
|
prevaddr = regaddr;
|
||||||
preval = val;
|
preval = regval;
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the register value read */
|
/* Show the register value read */
|
||||||
|
|
||||||
lldbg("%08x->%04x\n", addr, val);
|
lldbg("%08x->%048\n", regaddr, regval);
|
||||||
return val;
|
return regval;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -240,15 +240,15 @@ static uint16_t sam_getreg(uint32_t addr)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_SAMA5_WDT_REGDEBUG) && defined(CONFIG_DEBUG)
|
#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 */
|
/* Show the register value being written */
|
||||||
|
|
||||||
lldbg("%08x<-%04x\n", addr, val);
|
lldbg("%08x<-%08x\n", regaddr, regval);
|
||||||
|
|
||||||
/* Write the value */
|
/* Write the value */
|
||||||
|
|
||||||
putreg16(val, addr);
|
putreg32(regval, regaddr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -304,6 +304,8 @@ static int sam_interrupt(int irq, FAR void *context)
|
|||||||
|
|
||||||
static int sam_start(FAR struct watchdog_lowerhalf_s *lower)
|
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.
|
/* 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
|
* 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");
|
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,
|
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;
|
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;
|
status->flags |= WDFLAGS_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SAMA5_WDT_INTERRUPT
|
#ifdef CONFIG_SAMA5_WDT_INTERRUPT
|
||||||
if (priv->handler)
|
if (priv->handler)
|
||||||
{
|
{
|
||||||
@ -494,7 +496,7 @@ static int sam_settimeout(FAR struct watchdog_lowerhalf_s *lower,
|
|||||||
|
|
||||||
wdvdbg("reload=%d timout: %d->%d\n",
|
wdvdbg("reload=%d timout: %d->%d\n",
|
||||||
reload, timeout, priv->timeout);
|
reload, timeout, priv->timeout);
|
||||||
|
|
||||||
/* Set the WDT_MR according to calculated value
|
/* Set the WDT_MR according to calculated value
|
||||||
*
|
*
|
||||||
* NOTE: The Watchdog Mode Register (WDT_MR) can be written only once. Only
|
* 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,
|
static int sam_ioctl(FAR struct watchdog_lowerhalf_s *lower, int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
wdvdbg("Entry: cmd=%d arg=%ld\n", cmd, arg);
|
wdvdbg("cmd=%d arg=%ld\n", cmd, arg);
|
||||||
|
|
||||||
/* No ioctls are supported */
|
/* 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:
|
* Description:
|
||||||
* Initialize the WDT watchdog time. The watchdog timer is intialized and
|
* 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.
|
* disabled.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* devpath - The full path to the watchdog. This should be of the form
|
* None
|
||||||
* /dev/watchdog0
|
|
||||||
*
|
*
|
||||||
* Returned Values:
|
* Returned Values:
|
||||||
* None
|
* None
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void sam_wdtinitialize(FAR const char *devpath)
|
int up_wdginitialize(void)
|
||||||
{
|
{
|
||||||
FAR struct sam_lowerhalf_s *priv = &g_wdtdev;
|
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
|
* divided by 128 to establish the maximum Watchdog period to be 16 seconds
|
||||||
* (with a typical Slow Clock of 32768 kHz).
|
* (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 */
|
/* 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 */
|
#endif /* CONFIG_WATCHDOG && CONFIG_SAMA5_WDT */
|
||||||
|
@ -65,27 +65,6 @@ extern "C" {
|
|||||||
* Public Functions
|
* 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
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
@ -1006,7 +1006,7 @@ Configurations
|
|||||||
|
|
||||||
5. The Real Time Clock/Calendar RTC) is enabled. These are the relevant
|
5. The Real Time Clock/Calendar RTC) is enabled. These are the relevant
|
||||||
settings:
|
settings:
|
||||||
|
|
||||||
System Type:
|
System Type:
|
||||||
CONFIG_SAMA5_RTC=y : Enable the RTC driver
|
CONFIG_SAMA5_RTC=y : Enable the RTC driver
|
||||||
|
|
||||||
@ -2152,7 +2152,7 @@ Configurations
|
|||||||
Defaults should be okay for all related settings.
|
Defaults should be okay for all related settings.
|
||||||
|
|
||||||
17. The Real Time Clock/Calendar RTC) may be enabled with these settings:
|
17. The Real Time Clock/Calendar RTC) may be enabled with these settings:
|
||||||
|
|
||||||
System Type:
|
System Type:
|
||||||
CONFIG_SAMA5_RTC=y : Enable the RTC driver
|
CONFIG_SAMA5_RTC=y : Enable the RTC driver
|
||||||
|
|
||||||
@ -2182,13 +2182,24 @@ Configurations
|
|||||||
CONFIG_WATCHDOG=y : Enables watchdog timer driver support
|
CONFIG_WATCHDOG=y : Enables watchdog timer driver support
|
||||||
|
|
||||||
Application Configuration -> Eamples
|
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.
|
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
|
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
|
SAMA5 WDT may also only be programmed one time; the processor must be
|
||||||
reset before the WDT can be reprogrammed.
|
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:
|
STATUS:
|
||||||
|
|
||||||
PCK FREQUENCY
|
PCK FREQUENCY
|
||||||
|
Loading…
x
Reference in New Issue
Block a user