This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 3959bceea4a752a9c6226c91b70f552887897b22
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Fri Oct 23 00:42:50 2026 -0300

    drivers/timers: add a watchdog implemented by a wdog timer.
    
    Add CONFIG_WATCHDOG_WDOG and watchdog_wdog_initialize(), a watchdog
    lower half built on a wdog timer, like timer_wdog.c does for the timer
    interface. It is meant for the platforms with no watchdog hardware,
    such as the simulator: when it is not fed in time it panics, reboots or
    powers off the board, as selected by CONFIG_WATCHDOG_WDOG_ACTION. It can
    not detect a system where the tick stopped.
    
    Register it from sim_bringup() when CONFIG_WATCHDOG_WDOG is set. The
    simulator cannot reset, so the new sim:watchdog configuration powers it
    off with status 77 when the watchdog expires, and runs the wdog example.
    Document it.
    
    Assisted-by: Claude Code:claude-sonnet-5-5
    Signed-off-by: Daniel P. Carvalho <[email protected]>
---
 .../platforms/sim/sim/boards/sim/index.rst         |  12 ++
 boards/sim/sim/sim/configs/watchdog/defconfig      |  88 +++++++++
 boards/sim/sim/sim/src/sim_bringup.c               |  12 ++
 drivers/timers/CMakeLists.txt                      |   3 +
 drivers/timers/Kconfig                             |  43 +++++
 drivers/timers/Make.defs                           |   3 +
 drivers/timers/watchdog_wdog.c                     | 211 +++++++++++++++++++++
 include/nuttx/timers/watchdog_wdog.h               |  75 ++++++++
 8 files changed, 447 insertions(+)

diff --git a/Documentation/platforms/sim/sim/boards/sim/index.rst 
b/Documentation/platforms/sim/sim/boards/sim/index.rst
index ff1de014568..f23d8c482c3 100644
--- a/Documentation/platforms/sim/sim/boards/sim/index.rst
+++ b/Documentation/platforms/sim/sim/boards/sim/index.rst
@@ -1815,6 +1815,18 @@ since there are some compatibility issues. By default 
SIM will be blocked at
 startup to wait client connection, if a client connected, then the fb example
 will launch.
 
+watchdog
+--------
+
+This configuration enables ``CONFIG_WATCHDOG_WDOG``, a watchdog timer
+registered at ``CONFIG_WATCHDOG_DEVPATH``. The simulator cannot reset itself,
+so the watchdog powers it off when it expires, with status 77
+(``CONFIG_WATCHDOG_WDOG_STATUS``). It enables the ``wdog`` example: it feeds
+the watchdog for a while, stops, and the simulator exits with that status when
+the timeout expires::
+
+    nsh> wdog
+
 vpnkit
 ------
 
diff --git a/boards/sim/sim/sim/configs/watchdog/defconfig 
b/boards/sim/sim/sim/configs/watchdog/defconfig
new file mode 100644
index 00000000000..f628ba79068
--- /dev/null
+++ b/boards/sim/sim/sim/configs/watchdog/defconfig
@@ -0,0 +1,88 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ARCH="sim"
+CONFIG_ARCH_BOARD="sim"
+CONFIG_ARCH_BOARD_SIM=y
+CONFIG_ARCH_CHIP="sim"
+CONFIG_ARCH_SIM=y
+CONFIG_BOARDCTL_APP_SYMTAB=y
+CONFIG_BOARDCTL_POWEROFF=y
+CONFIG_BOARD_LOOPSPERMSEC=0
+CONFIG_BOOT_RUNFROMEXTSRAM=y
+CONFIG_BUILTIN=y
+CONFIG_COVERAGE_ALL=y
+CONFIG_COVERAGE_TOOLCHAIN=y
+CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEV_GPIO=y
+CONFIG_DEV_LOOP=y
+CONFIG_ETC_FATDEVNO=2
+CONFIG_ETC_ROMFS=y
+CONFIG_ETC_ROMFSDEVNO=1
+CONFIG_EXAMPLES_GPIO=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_EXAMPLES_WATCHDOG=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FAT_LCNAMES=y
+CONFIG_FAT_LFN=y
+CONFIG_FS_BINFS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_HOSTFS=y
+CONFIG_FS_LINKS=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_RAMMAP=y
+CONFIG_FS_ROMFS=y
+CONFIG_GPIO_LOWER_HALF=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=4096
+CONFIG_INIT_ENTRYPOINT="init_main"
+CONFIG_IOEXPANDER=y
+CONFIG_IOEXPANDER_DUMMY=y
+CONFIG_LIBC_ENVPATH=y
+CONFIG_LIBC_EXECFUNCS=y
+CONFIG_LIBC_LOCALE=y
+CONFIG_LIBC_LOCALE_CATALOG=y
+CONFIG_LIBC_LOCALE_GETTEXT=y
+CONFIG_LIBC_MAX_EXITFUNS=1
+CONFIG_LIBC_NUMBERED_ARGS=y
+CONFIG_NDEBUG=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILE_APPS=y
+CONFIG_NSH_READLINE=y
+CONFIG_PATH_INITIAL="/bin"
+CONFIG_PIPES=y
+CONFIG_PSEUDOFS_ATTRIBUTES=y
+CONFIG_PSEUDOFS_FILE=y
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_READLINE_EDIT_EMACS=y
+CONFIG_READLINE_TABCOMPLETION=y
+CONFIG_RTC=y
+CONFIG_RTC_ARCH=y
+CONFIG_RTC_DRIVER=y
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_CHILD_STATUS=y
+CONFIG_SCHED_EVENTS=y
+CONFIG_SCHED_HAVE_PARENT=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SIM_HOSTFS=y
+CONFIG_SIM_WALLTIME_SIGNAL=y
+CONFIG_START_MONTH=6
+CONFIG_START_YEAR=2008
+CONFIG_SYSTEM_DUMPSTACK=y
+CONFIG_SYSTEM_GCOV=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_NXINIT=y
+CONFIG_TASK_NAME_SIZE=15
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_WDOG=y
+CONFIG_WATCHDOG_WDOG_POWEROFF=y
+CONFIG_WATCHDOG_WDOG_STATUS=77
diff --git a/boards/sim/sim/sim/src/sim_bringup.c 
b/boards/sim/sim/sim/src/sim_bringup.c
index 9dc6bcf21d0..c47f9646a8c 100644
--- a/boards/sim/sim/sim/src/sim_bringup.c
+++ b/boards/sim/sim/sim/src/sim_bringup.c
@@ -74,6 +74,10 @@
 #include <nuttx/timers/timer_wdog.h>
 #endif
 
+#ifdef CONFIG_WATCHDOG_WDOG
+#include <nuttx/timers/watchdog_wdog.h>
+#endif
+
 #include "sim_internal.h"
 #include "sim.h"
 
@@ -599,6 +603,14 @@ int sim_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_WATCHDOG_WDOG
+  ret = watchdog_wdog_initialize(CONFIG_WATCHDOG_DEVPATH);
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "ERROR: watchdog_wdog_initialize failed: %d\n", ret);
+    }
+#endif
+
 #ifdef CONFIG_TIMER_WDOG
   ret = timer_wdog_initialize(0);
   if (ret < 0)
diff --git a/drivers/timers/CMakeLists.txt b/drivers/timers/CMakeLists.txt
index f819a283336..5aa04fd5c36 100644
--- a/drivers/timers/CMakeLists.txt
+++ b/drivers/timers/CMakeLists.txt
@@ -24,6 +24,9 @@ set(SRCS)
 
 if(CONFIG_WATCHDOG)
   list(APPEND SRCS watchdog.c)
+  if(CONFIG_WATCHDOG_WDOG)
+    list(APPEND SRCS watchdog_wdog.c)
+  endif()
 endif()
 
 if(CONFIG_TIMER)
diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig
index f1c518d9313..2cf30db1bec 100644
--- a/drivers/timers/Kconfig
+++ b/drivers/timers/Kconfig
@@ -480,6 +480,49 @@ menuconfig WATCHDOG
 
 if WATCHDOG
 
+config WATCHDOG_WDOG
+       bool "Watchdog implemented by wdog timer"
+       default n
+       depends on !WATCHDOG_AUTOMONITOR_BY_ONESHOT && 
!WATCHDOG_AUTOMONITOR_BY_TIMER
+       ---help---
+               Build a watchdog timer on top of the wdog timers, for the 
platforms
+               that have no watchdog hardware, e.g. the simulator. It cannot 
detect
+               a system where the tick stopped. Not to be confused with
+               WATCHDOG_AUTOMONITOR_BY_WDOG, where a wdog feeds a real 
watchdog. It
+               is not available with the oneshot and timer auto-monitors, which
+               change the watchdog_register() prototype. Call
+               watchdog_wdog_initialize() from the board to register it.
+
+if WATCHDOG_WDOG
+
+config WATCHDOG_WDOG_TIMEOUT
+       int "Initial timeout (millisecond)"
+       default 5000
+
+choice WATCHDOG_WDOG_ACTION
+       prompt "Action when the watchdog expires"
+       default WATCHDOG_WDOG_PANIC
+
+config WATCHDOG_WDOG_PANIC
+       bool "Panic"
+
+config WATCHDOG_WDOG_REBOOT
+       bool "Reboot"
+       depends on BOARDCTL_RESET
+
+config WATCHDOG_WDOG_POWEROFF
+       bool "Power off"
+       depends on BOARDCTL_POWEROFF
+
+endchoice # WATCHDOG_WDOG_ACTION
+
+config WATCHDOG_WDOG_STATUS
+       int "Status passed to the board when it reboots or powers off"
+       default 0
+       depends on WATCHDOG_WDOG_REBOOT || WATCHDOG_WDOG_POWEROFF
+
+endif # WATCHDOG_WDOG
+
 config WATCHDOG_DEVPATH
        string "Watchdog Device Path"
        default "/dev/watchdog0"
diff --git a/drivers/timers/Make.defs b/drivers/timers/Make.defs
index 1b0bf427fb8..3c48a32f2e1 100644
--- a/drivers/timers/Make.defs
+++ b/drivers/timers/Make.defs
@@ -24,6 +24,9 @@
 
 ifeq ($(CONFIG_WATCHDOG),y)
   CSRCS += watchdog.c
+  ifeq ($(CONFIG_WATCHDOG_WDOG),y)
+    CSRCS += watchdog_wdog.c
+  endif
   TMRDEPPATH = --dep-path timers
   TMRVPATH = :timers
 endif
diff --git a/drivers/timers/watchdog_wdog.c b/drivers/timers/watchdog_wdog.c
new file mode 100644
index 00000000000..c2345507db1
--- /dev/null
+++ b/drivers/timers/watchdog_wdog.c
@@ -0,0 +1,211 @@
+/****************************************************************************
+ * drivers/timers/watchdog_wdog.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <nuttx/board.h>
+#include <nuttx/clock.h>
+#include <nuttx/debug.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/wdog.h>
+#include <nuttx/timers/watchdog.h>
+#include <nuttx/timers/watchdog_wdog.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct watchdog_wdog_s
+{
+  struct watchdog_lowerhalf_s lower;   /* Must be first */
+  struct wdog_s               wdog;    /* The timer that expires */
+  uint32_t                    timeout; /* Timeout in milliseconds */
+  bool                        started; /* Is the watchdog running */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int watchdog_wdog_start(FAR struct watchdog_lowerhalf_s *lower);
+static int watchdog_wdog_stop(FAR struct watchdog_lowerhalf_s *lower);
+static int watchdog_wdog_keepalive(FAR struct watchdog_lowerhalf_s *lower);
+static int watchdog_wdog_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+                                   FAR struct watchdog_status_s *status);
+static int watchdog_wdog_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+                                    uint32_t timeout);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct watchdog_ops_s g_watchdog_wdog_ops =
+{
+  .start      = watchdog_wdog_start,
+  .stop       = watchdog_wdog_stop,
+  .keepalive  = watchdog_wdog_keepalive,
+  .getstatus  = watchdog_wdog_getstatus,
+  .settimeout = watchdog_wdog_settimeout,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: watchdog_wdog_expire
+ *
+ * Description:
+ *   The wdog handler: the watchdog was not fed in time.
+ *
+ ****************************************************************************/
+
+static void watchdog_wdog_expire(wdparm_t arg)
+{
+  _alert("Watchdog expired\n");
+
+#if defined(CONFIG_WATCHDOG_WDOG_REBOOT)
+  board_reset(CONFIG_WATCHDOG_WDOG_STATUS);
+#elif defined(CONFIG_WATCHDOG_WDOG_POWEROFF)
+  board_power_off(CONFIG_WATCHDOG_WDOG_STATUS);
+#else
+  PANIC();
+#endif
+}
+
+/****************************************************************************
+ * Name: watchdog_wdog_arm
+ ****************************************************************************/
+
+static int watchdog_wdog_arm(FAR struct watchdog_wdog_s *priv)
+{
+  return wd_start(&priv->wdog, MSEC2TICK(priv->timeout),
+                  watchdog_wdog_expire, (wdparm_t)priv);
+}
+
+static int watchdog_wdog_start(FAR struct watchdog_lowerhalf_s *lower)
+{
+  FAR struct watchdog_wdog_s *priv = (FAR struct watchdog_wdog_s *)lower;
+  int ret;
+
+  ret = watchdog_wdog_arm(priv);
+  if (ret >= 0)
+    {
+      priv->started = true;
+    }
+
+  return ret;
+}
+
+static int watchdog_wdog_stop(FAR struct watchdog_lowerhalf_s *lower)
+{
+  FAR struct watchdog_wdog_s *priv = (FAR struct watchdog_wdog_s *)lower;
+
+  priv->started = false;
+  wd_cancel(&priv->wdog);
+  return OK;
+}
+
+static int watchdog_wdog_keepalive(FAR struct watchdog_lowerhalf_s *lower)
+{
+  FAR struct watchdog_wdog_s *priv = (FAR struct watchdog_wdog_s *)lower;
+
+  return priv->started ? watchdog_wdog_arm(priv) : OK;
+}
+
+static int watchdog_wdog_getstatus(FAR struct watchdog_lowerhalf_s *lower,
+                                   FAR struct watchdog_status_s *status)
+{
+  FAR struct watchdog_wdog_s *priv = (FAR struct watchdog_wdog_s *)lower;
+
+  status->flags    = priv->started ? WDFLAGS_ACTIVE | WDFLAGS_RESET : 0;
+  status->timeout  = priv->timeout;
+  status->timeleft = 0;
+
+  if (priv->started)
+    {
+      /* wd_start() adds a tick, do not report more than the timeout */
+
+      status->timeleft = TICK2MSEC(wd_gettime(&priv->wdog));
+      if (status->timeleft > priv->timeout)
+        {
+          status->timeleft = priv->timeout;
+        }
+    }
+
+  return OK;
+}
+
+static int watchdog_wdog_settimeout(FAR struct watchdog_lowerhalf_s *lower,
+                                    uint32_t timeout)
+{
+  FAR struct watchdog_wdog_s *priv = (FAR struct watchdog_wdog_s *)lower;
+
+  if (timeout == 0)
+    {
+      return -EINVAL;
+    }
+
+  priv->timeout = timeout;
+  return watchdog_wdog_keepalive(lower);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: watchdog_wdog_initialize
+ ****************************************************************************/
+
+int watchdog_wdog_initialize(FAR const char *path)
+{
+  FAR struct watchdog_wdog_s *priv;
+
+  DEBUGASSERT(path != NULL);
+
+  priv = kmm_zalloc(sizeof(struct watchdog_wdog_s));
+  if (priv == NULL)
+    {
+      return -ENOMEM;
+    }
+
+  priv->lower.ops = &g_watchdog_wdog_ops;
+  priv->timeout   = CONFIG_WATCHDOG_WDOG_TIMEOUT;
+
+  if (watchdog_register(path, &priv->lower) == NULL)
+    {
+      kmm_free(priv);
+      return -EEXIST;
+    }
+
+  return OK;
+}
diff --git a/include/nuttx/timers/watchdog_wdog.h 
b/include/nuttx/timers/watchdog_wdog.h
new file mode 100644
index 00000000000..a5b3779a70f
--- /dev/null
+++ b/include/nuttx/timers/watchdog_wdog.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * include/nuttx/timers/watchdog_wdog.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_TIMERS_WATCHDOG_WDOG_H
+#define __INCLUDE_NUTTX_TIMERS_WATCHDOG_WDOG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#ifdef CONFIG_WATCHDOG_WDOG
+/****************************************************************************
+ * Name: watchdog_wdog_initialize
+ *
+ * Description:
+ *   Register a watchdog timer implemented by a wdog timer, for the
+ *   platforms that have no watchdog hardware (e.g. the simulator). Like any
+ *   watchdog it expires if it is not fed within its timeout, but since
+ *   there is no hardware to reset the system it does what
+ *   CONFIG_WATCHDOG_WDOG_ACTION selects (panic, reboot or power off). It
+ *   does not fire if the system tick stops.
+ *
+ * Input Parameters:
+ *   path - The device path, e.g. CONFIG_WATCHDOG_DEVPATH. The initial
+ *          timeout is CONFIG_WATCHDOG_WDOG_TIMEOUT.
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int watchdog_wdog_initialize(FAR const char *path);
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_TIMERS_WATCHDOG_WDOG_H */

Reply via email to