Fix a couple of bugs in the STM32 IWDG driver
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4620 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
d8d410ba2e
commit
461a0ea6cc
|
@ -223,6 +223,9 @@ static void parse_args(FAR struct wdog_example_s *wdog, int argc, FAR char **arg
|
||||||
int wdog_main(int argc, char *argv[])
|
int wdog_main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct wdog_example_s wdog;
|
struct wdog_example_s wdog;
|
||||||
|
#ifdef CONFIG_DEBUG_WATCHDOG
|
||||||
|
struct watchdog_status_s status;
|
||||||
|
#endif
|
||||||
long elapsed;
|
long elapsed;
|
||||||
int fd;
|
int fd;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -278,6 +281,21 @@ int wdog_main(int argc, char *argv[])
|
||||||
|
|
||||||
usleep(wdog.pingdelay * 1000);
|
usleep(wdog.pingdelay * 1000);
|
||||||
|
|
||||||
|
/* Show watchdog status. Only if debug is enabled because this
|
||||||
|
* could interfere with the timer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_WATCHDOG
|
||||||
|
ret = ioctl(fd, WDIOC_GETSTATUS, (unsigned long)&status);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
message("wdog_main: ioctl(WDIOC_GETSTATUS) failed: %d\n", errno);
|
||||||
|
goto errout_with_dev;
|
||||||
|
}
|
||||||
|
message("wdog_main: flags=%08x timeout=%d timeleft=%d\n",
|
||||||
|
status.flags, status.timeout, status.timeleft);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Then ping */
|
/* Then ping */
|
||||||
|
|
||||||
ret = ioctl(fd, WDIOC_KEEPALIVE, 0);
|
ret = ioctl(fd, WDIOC_KEEPALIVE, 0);
|
||||||
|
@ -299,6 +317,21 @@ int wdog_main(int argc, char *argv[])
|
||||||
|
|
||||||
usleep(wdog.pingdelay * 1000);
|
usleep(wdog.pingdelay * 1000);
|
||||||
|
|
||||||
|
/* Show watchdog status. Only if debug is enabled because this
|
||||||
|
* could interfere with the timer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_WATCHDOG
|
||||||
|
ret = ioctl(fd, WDIOC_GETSTATUS, (unsigned long)&status);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
message("wdog_main: ioctl(WDIOC_GETSTATUS) failed: %d\n", errno);
|
||||||
|
goto errout_with_dev;
|
||||||
|
}
|
||||||
|
message("wdog_main: flags=%08x timeout=%d timeleft=%d\n",
|
||||||
|
status.flags, status.timeout, status.timeleft);
|
||||||
|
#endif
|
||||||
|
|
||||||
message(" NO ping elapsed=%ld\n", elapsed);
|
message(" NO ping elapsed=%ld\n", elapsed);
|
||||||
msgflush();
|
msgflush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <nuttx/clock.h>
|
||||||
#include <nuttx/watchdog.h>
|
#include <nuttx/watchdog.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
|
@ -90,6 +91,19 @@
|
||||||
|
|
||||||
#define CONFIG_STM32_IWDG_ONETIMESETUP 1
|
#define CONFIG_STM32_IWDG_ONETIMESETUP 1
|
||||||
|
|
||||||
|
/* REVISIT: Another possibility is that we CAN change the prescaler and
|
||||||
|
* reload values after starting the timer. This option is untested but the
|
||||||
|
* implementation place conditioned on the following:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef CONFIG_STM32_IWDG_DEFERREDSETUP
|
||||||
|
|
||||||
|
/* But you can only try one at a time */
|
||||||
|
|
||||||
|
#if defined(CONFIG_STM32_IWDG_ONETIMESETUP) && defined(CONFIG_STM32_IWDG_DEFERREDSETUP)
|
||||||
|
# error "Both CONFIG_STM32_IWDG_ONETIMESETUP and CONFIG_STM32_IWDG_DEFERREDSETUP are defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Debug ********************************************************************/
|
/* Debug ********************************************************************/
|
||||||
/* Non-standard debug that may be enabled just for testing the watchdog
|
/* Non-standard debug that may be enabled just for testing the watchdog
|
||||||
* driver. NOTE: that only lldbg types are used so that the output is
|
* driver. NOTE: that only lldbg types are used so that the output is
|
||||||
|
@ -117,6 +131,7 @@ struct stm32_lowerhalf_s
|
||||||
FAR const struct watchdog_ops_s *ops; /* Lower half operations */
|
FAR const struct watchdog_ops_s *ops; /* Lower half operations */
|
||||||
uint32_t lsifreq; /* The calibrated frequency of the LSI oscillator */
|
uint32_t lsifreq; /* The calibrated frequency of the LSI oscillator */
|
||||||
uint32_t timeout; /* The (actual) selected timeout */
|
uint32_t timeout; /* The (actual) selected timeout */
|
||||||
|
uint32_t lastreset; /* The last reset time */
|
||||||
bool started; /* true: The watchdog timer has been started */
|
bool started; /* true: The watchdog timer has been started */
|
||||||
uint8_t prescaler; /* Clock prescaler value */
|
uint8_t prescaler; /* Clock prescaler value */
|
||||||
uint16_t reload; /* Timer reload value */
|
uint16_t reload; /* Timer reload value */
|
||||||
|
@ -282,7 +297,7 @@ static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv)
|
||||||
* yet be cleared.
|
* yet be cleared.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_STM32_IWDG_ONETIMESETUP
|
#ifdef CONFIG_STM32_IWDG_DEFERREDSETUP
|
||||||
while ((stm32_getreg(STM32_IWDG_SR) & (IWDG_SR_PVU|IWDG_SR_RVU)) != 0);
|
while ((stm32_getreg(STM32_IWDG_SR) & (IWDG_SR_PVU|IWDG_SR_RVU)) != 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -317,6 +332,7 @@ static inline void stm32_setprescaler(FAR struct stm32_lowerhalf_s *priv)
|
||||||
static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
|
static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
|
||||||
{
|
{
|
||||||
FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
|
FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
wdvdbg("Entry: started=%d\n");
|
wdvdbg("Entry: started=%d\n");
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
|
@ -331,9 +347,11 @@ static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
|
||||||
* is started, then refuse any further attempts to change timeout.
|
* is started, then refuse any further attempts to change timeout.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Set up prescaler and reload value for the selected timeout */
|
/* Set up prescaler and reload value for the selected timeout before
|
||||||
|
* starting the watchdog timer.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_STM32_IWDG_ONETIMESETUP
|
#if defined(CONFIG_STM32_IWDG_ONETIMESETUP) || defined(CONFIG_STM32_IWDG_DEFERREDSETUP)
|
||||||
stm32_setprescaler(priv);
|
stm32_setprescaler(priv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -342,8 +360,11 @@ static int stm32_start(FAR struct watchdog_lowerhalf_s *lower)
|
||||||
* bits, the watchdog is automatically enabled at power-on.
|
* bits, the watchdog is automatically enabled at power-on.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
stm32_putreg(IWDG_KR_KEY_START, STM32_IWDG_KR);
|
stm32_putreg(IWDG_KR_KEY_START, STM32_IWDG_KR);
|
||||||
|
priv->lastreset = clock_systimer();
|
||||||
priv->started = true;
|
priv->started = true;
|
||||||
|
irqrestore(flags);
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -390,10 +411,18 @@ static int stm32_stop(FAR struct watchdog_lowerhalf_s *lower)
|
||||||
|
|
||||||
static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower)
|
static int stm32_keepalive(FAR struct watchdog_lowerhalf_s *lower)
|
||||||
{
|
{
|
||||||
/* Reload the IWDG timer */
|
FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
wdvdbg("Entry\n");
|
wdvdbg("Entry\n");
|
||||||
|
|
||||||
|
/* Reload the IWDG timer */
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR);
|
stm32_putreg(IWDG_KR_KEY_RELOAD, STM32_IWDG_KR);
|
||||||
|
priv->lastreset = clock_systimer();
|
||||||
|
irqrestore(flags);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,8 +446,8 @@ static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
|
||||||
FAR struct watchdog_status_s *status)
|
FAR struct watchdog_status_s *status)
|
||||||
{
|
{
|
||||||
FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
|
FAR struct stm32_lowerhalf_s *priv = (FAR struct stm32_lowerhalf_s *)lower;
|
||||||
|
uint32_t ticks;
|
||||||
uint32_t elapsed;
|
uint32_t elapsed;
|
||||||
uint16_t reload;
|
|
||||||
|
|
||||||
wdvdbg("Entry\n");
|
wdvdbg("Entry\n");
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
|
@ -431,23 +460,28 @@ static int stm32_getstatus(FAR struct watchdog_lowerhalf_s *lower,
|
||||||
status->flags |= WDFLAGS_ACTIVE;
|
status->flags |= WDFLAGS_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the actual timeout is milliseconds */
|
/* Return the actual timeout in milliseconds */
|
||||||
|
|
||||||
status->timeout = priv->timeout;
|
status->timeout = priv->timeout;
|
||||||
|
|
||||||
/* I am not sure what will be returned when reading from the reload register.
|
/* Get the elapsed time since the last ping */
|
||||||
* Documentation says that the value from the VDD section should be read
|
|
||||||
* so presume it the decremented value.
|
|
||||||
*/
|
|
||||||
|
|
||||||
reload = stm32_getreg(STM32_IWDG_RLR);
|
ticks = clock_systimer() - priv->lastreset;
|
||||||
elapsed = priv->reload - reload;
|
elapsed = (int32_t)TICK2MSEC(ticks);
|
||||||
status->timeleft = (priv->timeout * elapsed) / priv->reload;
|
|
||||||
|
if (elapsed > priv->timeout)
|
||||||
|
{
|
||||||
|
elapsed = priv->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the approximate time until the watchdog timer expiration */
|
||||||
|
|
||||||
|
status->timeleft = priv->timeout - elapsed;
|
||||||
|
|
||||||
wdvdbg("Status :\n");
|
wdvdbg("Status :\n");
|
||||||
wdvdbg(" flags : %08x\n", status->flags);
|
wdvdbg(" flags : %08x\n", status->flags);
|
||||||
wdvdbg(" timeout : %d\n", status->timeout);
|
wdvdbg(" timeout : %d\n", status->timeout);
|
||||||
wdvdbg(" timeleft : %d\n", status->flags);
|
wdvdbg(" timeleft : %d\n", status->timeleft);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,11 +613,19 @@ static int stm32_settimeout(FAR struct watchdog_lowerhalf_s *lower,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_STM32_IWDG_ONETIMESETUP
|
#ifndef CONFIG_STM32_IWDG_ONETIMESETUP
|
||||||
|
/* If CONFIG_STM32_IWDG_DEFERREDSETUP is selected, then perform the register
|
||||||
|
* configuration only if the timer has been started.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_STM32_IWDG_DEFERREDSETUP
|
||||||
|
if (priv->started)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
stm32_setprescaler(priv);
|
stm32_setprescaler(priv);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wdvdbg("prescaler=%d fiwdg=%d reload=%d timeout=%d\n",
|
wdvdbg("prescaler=%d fiwdg=%d reload=%d\n", prescaler, fiwdg, reload);
|
||||||
prescaler, fiwdg, reload, priv->timeout);
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue