You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/11/06 21:33:41 UTC
[incubator-nuttx] branch master updated: arch/arm/src/imxrt: adds
support for WDOG1
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new c7a9b66 arch/arm/src/imxrt: adds support for WDOG1
c7a9b66 is described below
commit c7a9b66833258759b47afc117634880ffa67f9d9
Author: Nicholas Chin <ni...@gmail.com>
AuthorDate: Tue Nov 3 13:00:37 2020 -0500
arch/arm/src/imxrt: adds support for WDOG1
Based on work done by Jake Choy.
---
arch/arm/src/imxrt/Kconfig | 5 +
arch/arm/src/imxrt/imxrt_wdog.c | 337 ++++++++++++++++++++++++++++++++++++++--
arch/arm/src/imxrt/imxrt_wdog.h | 23 +++
3 files changed, 355 insertions(+), 10 deletions(-)
diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig
index 8cb93b4..c2657bb 100644
--- a/arch/arm/src/imxrt/Kconfig
+++ b/arch/arm/src/imxrt/Kconfig
@@ -217,6 +217,11 @@ config IMXRT_LCD
default n
depends on IMXRT_HAVE_LCD
+config IMXRT_WDOG
+ bool "Watchdog 1"
+ default n
+ depends on WATCHDOG
+
menu "FlexIO Peripherals"
config IMXRT_FLEXIO1
diff --git a/arch/arm/src/imxrt/imxrt_wdog.c b/arch/arm/src/imxrt/imxrt_wdog.c
index a3dbb1b..9302afc 100644
--- a/arch/arm/src/imxrt/imxrt_wdog.c
+++ b/arch/arm/src/imxrt/imxrt_wdog.c
@@ -40,29 +40,347 @@
#include <nuttx/config.h>
#include <stdint.h>
-#include <fixedmath.h>
+#include <stdbool.h>
+
+#include <debug.h>
#include <assert.h>
+#include <errno.h>
-#include "arm_arch.h"
+#include <nuttx/timers/watchdog.h>
+#include "arm_arch.h"
#include "hardware/imxrt_wdog.h"
-#include "imxrt_config.h"
+#include "imxrt_wdog.h"
+
#include <arch/board/board.h> /* Include last: has dependencies */
+#if defined(CONFIG_WATCHDOG) && defined(CONFIG_IMXRT_WDOG)
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-/* Configuration ************************************************************/
+
+/* Select the path to the registered watchdog timer device */
+
+#ifdef CONFIG_WATCHDOG_DEVPATH
+#define DEVPATH CONFIG_WATCHDOG_DEVPATH
+#else
+#define DEVPATH "/dev/watchdog0"
+#endif
+
+/* Time out range is from 0 to 128 seconds in 0.5s intervals */
+
+#define WDOG_MIN (500)
+#define WDOG_MAX (128000)
+
+#define WDOG_KEEP_ALIVE_KEY1 (0x5555u)
+#define WDOG_KEEP_ALIVE_KEY2 (0xaaaau)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct imxrt_wdog_lower
+{
+ FAR const struct watchdog_ops_s *ops; /* Lower half operations */
+ uint32_t timeout;
+ uint32_t enabled;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Timeout to register field helper */
+
+uint32_t imxrt_wdog_ms_to_reg(uint32_t timeout);
+
+/* Lower half driver methods */
+
+static int imxrt_wdog_start(FAR struct watchdog_lowerhalf_s *lower);
+static int imxrt_wdog_stop(FAR struct watchdog_lowerhalf_s *lower);
+static int imxrt_wdog_keepalive(FAR struct watchdog_lowerhalf_s *lower);
+static int imxrt_wdog_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status);
+static int imxrt_wdog_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout);
/****************************************************************************
* Private Data
****************************************************************************/
+/* "Lower half" driver ops */
+
+static const struct watchdog_ops_s g_wdgops =
+{
+ .start = imxrt_wdog_start,
+ .stop = imxrt_wdog_stop,
+ .keepalive = imxrt_wdog_keepalive,
+ .getstatus = imxrt_wdog_getstatus,
+ .settimeout = imxrt_wdog_settimeout,
+ .capture = NULL,
+ .ioctl = NULL,
+};
+
+/* "Lower half" driver state */
+
+static struct imxrt_wdog_lower g_wdgdev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imxrt_wdog_ms_to_reg
+ *
+ * Description:
+ * Start the watchdog timer, resetting the time to the current timeout,
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the
+ * lower-half driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+uint32_t imxrt_wdog_ms_to_reg(uint32_t ms)
+{
+ uint32_t reg = ms / 500; /* This gives the value needed for
+ * ms rounded up to the nearest 500ms of timeout
+ */
+
+ if (reg != 0 && ms % 500 == 0)
+ {
+ /* If the number is divisible by 500ms we subtract 1.
+ * Else we will set the timeout to the smallest achievable timeout
+ * that is greater than the requested value.
+ */
+
+ reg--;
+ }
+
+ return reg;
+}
+
+/****************************************************************************
+ * Name: imxrt_wdog
+ *
+ * Description:
+ * Start the watchdog timer, setting the time to the current timeout,
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the
+ * lower-half driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int imxrt_wdog_start(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct imxrt_wdog_lower *priv = (FAR struct imxrt_wdog_lower *)lower;
+ uint16_t regval;
+
+ if (priv->enabled == false)
+ {
+ priv->enabled = true;
+
+ regval = getreg16(IMXRT_WDOG1_WCR);
+ regval |= WDOG_WCR_WT(imxrt_wdog_ms_to_reg(priv->timeout));
+ putreg16(regval, IMXRT_WDOG1_WCR);
+
+ /* Now that the timeout field is properly set, start the watchdog. */
+
+ regval |= WDOG_WCR_WDE;
+ putreg16(regval, IMXRT_WDOG1_WCR);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: imxrt_wdog_stop
+ *
+ * Description:
+ * Exists since it is a required function for the watchdog lower-half
+ * driver. On the IMXRT you cannot disable the watchdog once it is started.
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the
+ * lower-half driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int imxrt_wdog_stop(FAR struct watchdog_lowerhalf_s *lower)
+{
+ FAR struct imxrt_wdog_lower *priv = (FAR struct imxrt_wdog_lower *)lower;
+
+ if (priv->enabled)
+ {
+ /* We cannot disable the watchdog once it is enabled. */
+
+ wderr("ERROR: Cannot stop Wdog once started\n");
+ return -ENOSYS;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: imxrt_wdog_keepalive
+ *
+ * Description:
+ * Reset the watchdog timer to the current timeout value, prevent any
+ * imminent watchdog timeouts. This is sometimes referred as "pinging"
+ * the watchdog timer or "petting the dog".
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the
+ * lower-half driver state structure.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int imxrt_wdog_keepalive(FAR struct watchdog_lowerhalf_s *lower)
+{
+ irqstate_t flags = spin_lock_irqsave();
+
+ putreg16(WDOG_KEEP_ALIVE_KEY1, IMXRT_WDOG1_WSR);
+ putreg16(WDOG_KEEP_ALIVE_KEY2, IMXRT_WDOG1_WSR);
+
+ spin_unlock_irqrestore(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: imxrt_wdog_getstatus
+ *
+ * Description:
+ * Get the current watchdog timer status
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the
+ * lower-half driver state structure.
+ * status - The location to return the watchdog status information.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int imxrt_wdog_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+ FAR struct watchdog_status_s *status)
+{
+ FAR struct imxrt_wdog_lower *priv = (FAR struct imxrt_wdog_lower *)lower;
+
+ status->flags = WDFLAGS_RESET;
+
+ if (priv->enabled)
+ {
+ status->flags |= WDFLAGS_ACTIVE;
+ }
+
+ status->timeout = priv->timeout;
+ status->timeleft = 0; /* not supported for WDOG1 */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: imxrt_wdog_settimeout
+ *
+ * Description:
+ * Set a new timeout value (and reset the watchdog timer)
+ *
+ * Input Parameters:
+ * lower - A pointer the publicly visible representation of the
+ * "lower-half" driver state structure.
+ * timeout - The new timeout value in milliseconds.
+ *
+ * Returned Values:
+ * Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int imxrt_wdog_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+ uint32_t timeout)
+{
+ uint32_t regval;
+ FAR struct imxrt_wdog_lower *priv = (FAR struct imxrt_wdog_lower *)lower;
+
+ if (timeout < WDOG_MIN || timeout > WDOG_MAX)
+ {
+ wderr("ERROR: Cannot represent timeout=%d. Range=[%d, %d]\n",
+ timeout, WDOG_MIN, WDOG_MAX);
+ return -ERANGE;
+ }
+
+ priv->timeout = timeout;
+
+ irqstate_t flags = spin_lock_irqsave();
+
+ /* write timer value to WCR WT register */
+
+ regval = getreg16(IMXRT_WDOG1_WCR);
+ regval &= ~WDOG_WCR_WT_MASK; /* clear previous count value */
+ regval |= WDOG_WCR_WT(priv->timeout);
+ putreg16(regval, IMXRT_WDOG1_WCR);
+
+ /* reload the Wdog counter by petting it */
+
+ putreg16(WDOG_KEEP_ALIVE_KEY1, IMXRT_WDOG1_WSR);
+ putreg16(WDOG_KEEP_ALIVE_KEY2, IMXRT_WDOG1_WSR);
+
+ spin_unlock_irqrestore(flags);
+
+ return OK;
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
+ * Name: imxrt_wdog_initialize
+ *
+ * Description:
+ * Initialize the watchdog time. The watchdog timer is initialized and
+ * registered at devpath. The initial state of the watchdog time is
+ * disabled.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void imxrt_wdog_initialize(void)
+{
+ FAR struct imxrt_wdog_lower *priv = &g_wdgdev;
+
+ priv->ops = &g_wdgops;
+ priv->timeout = WDOG_MIN;
+
+ /* Register the watchdog driver at the path */
+
+ wdinfo("Entry: devpath=%s\n", DEVPATH);
+ watchdog_register(DEVPATH, (FAR struct watchdog_lowerhalf_s *)priv);
+}
+
+#endif /* CONFIG_WATCHDOG && CONFIG_IMXRT_WDOG */
+
+/****************************************************************************
* Name: imxrt_wdog_disable
*
* Description:
@@ -84,15 +402,14 @@ void imxrt_wdog_disable_all(void)
reg = getreg16(IMXRT_WDOG2_WCR);
if (reg & WDOG_WCR_WDE)
- {
- reg &= ~WDOG_WCR_WDE;
- putreg16(reg, IMXRT_WDOG2_WCR);
- }
+ {
+ reg &= ~WDOG_WCR_WDE;
+ putreg16(reg, IMXRT_WDOG2_WCR);
+ }
flags = enter_critical_section();
putreg32(RTWDOG_UPDATE_KEY, IMXRT_RTWDOG_CNT);
- putreg32(0xFFFF, IMXRT_RTWDOG_TOVAL);
+ putreg32(0xffff, IMXRT_RTWDOG_TOVAL);
modifyreg32(IMXRT_RTWDOG_CS, RTWDOG_CS_EN, RTWDOG_CS_UPDATE);
leave_critical_section(flags);
-
}
diff --git a/arch/arm/src/imxrt/imxrt_wdog.h b/arch/arm/src/imxrt/imxrt_wdog.h
index 6db8dad..8bf2a0c 100644
--- a/arch/arm/src/imxrt/imxrt_wdog.h
+++ b/arch/arm/src/imxrt/imxrt_wdog.h
@@ -59,6 +59,29 @@
* Public Function Prototypes
****************************************************************************/
+#if defined(CONFIG_WATCHDOG) && defined(CONFIG_IMXRT_WDOG)
+
+/****************************************************************************
+ * Name: imxrt_wdog_initialize
+ *
+ * Description:
+ * Initialize the watchdog time. The watchdog timer is initialized and
+ * registered at 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
+ *
+ ****************************************************************************/
+
+void imxrt_wdog_initialize(void);
+
+#endif /* CONFIG_WATCHDOG && CONFIG_IMXRT_WDOG */
+
/****************************************************************************
* Name: imxrt_wdog_disable
*