From 1eefec4db3876305860eb57b91f454322d44a74a Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 18 Sep 2022 10:47:19 +0800 Subject: [PATCH] watchdog: Support auto monitor keep alive from timer lowerhalf Signed-off-by: Xiang Xiao --- drivers/timers/Kconfig | 8 +- drivers/timers/watchdog.c | 125 ++++++++++++++++++++------------ include/nuttx/timers/watchdog.h | 7 ++ 3 files changed, 93 insertions(+), 47 deletions(-) diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig index 8988d052b6..0bf0133b0d 100644 --- a/drivers/timers/Kconfig +++ b/drivers/timers/Kconfig @@ -371,6 +371,10 @@ choice config WATCHDOG_AUTOMONITOR_BY_CAPTURE bool "Capture callback" +config WATCHDOG_AUTOMONITOR_BY_TIMER + bool "Timer callback" + depends on TIMER + config WATCHDOG_AUTOMONITOR_BY_WDOG bool "Wdog callback" @@ -388,7 +392,7 @@ config WATCHDOG_AUTOMONITOR_TIMEOUT int "Auto-monitor reset timeout(second)" default 60 -if WATCHDOG_AUTOMONITOR_BY_WDOG || WATCHDOG_AUTOMONITOR_BY_WORKER +if !WATCHDOG_AUTOMONITOR_BY_CAPTURE && !WATCHDOG_AUTOMONITOR_BY_IDLE config WATCHDOG_AUTOMONITOR_PING_INTERVAL int "Auto-monitor keep a live interval" @@ -400,7 +404,7 @@ config WATCHDOG_AUTOMONITOR_PING_INTERVAL This interval will only be used by auto-monitor by Worker callback or by Timer callback. -endif # WATCHDOG_AUTOMONITOR_BY_WDOG || WATCHDOG_AUTOMONITOR_BY_WORKER +endif # !WATCHDOG_AUTOMONITOR_BY_CAPTURE && !WATCHDOG_AUTOMONITOR_BY_IDLE endif # WATCHDOG_AUTOMONITOR diff --git a/drivers/timers/watchdog.c b/drivers/timers/watchdog.c index c81a3c4ad0..10b932d67c 100644 --- a/drivers/timers/watchdog.c +++ b/drivers/timers/watchdog.c @@ -40,31 +40,31 @@ #include #include #include +#include #include -#ifdef CONFIG_WATCHDOG - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #ifdef CONFIG_WATCHDOG_AUTOMONITOR - -#define WATCHDOG_AUTOMONITOR_TIMEOUT_MSEC \ - (1000 * CONFIG_WATCHDOG_AUTOMONITOR_TIMEOUT) - -#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) || \ - defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) -#if (CONFIG_WATCHDOG_AUTOMONITOR_TIMEOUT == \ - CONFIG_WATCHDOG_AUTOMONITOR_PING_INTERVAL) -#define WATCHDOG_AUTOMONITOR_PING_INTERVAL \ - SEC2TICK(CONFIG_WATCHDOG_AUTOMONITOR_TIMEOUT / 2) -#else -#define WATCHDOG_AUTOMONITOR_PING_INTERVAL \ - SEC2TICK(CONFIG_WATCHDOG_AUTOMONITOR_PING_INTERVAL) -#endif -#endif - +# define WATCHDOG_AUTOMONITOR_TIMEOUT_MSEC \ + (CONFIG_WATCHDOG_AUTOMONITOR_TIMEOUT * MSEC_PER_SEC) +# if !defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) && \ + !defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) +# if CONFIG_WATCHDOG_AUTOMONITOR_TIMEOUT == \ + CONFIG_WATCHDOG_AUTOMONITOR_PING_INTERVAL +# define WATCHDOG_AUTOMONITOR_PING_INTERVAL \ + (CONFIG_WATCHDOG_AUTOMONITOR_PING_INTERVAL / 2) +# else +# define WATCHDOG_AUTOMONITOR_PING_INTERVAL \ + CONFIG_WATCHDOG_AUTOMONITOR_PING_INTERVAL +# endif +# define WATCHDOG_AUTOMONITOR_PING_INTERVAL_MSEC \ + (WATCHDOG_AUTOMONITOR_PING_INTERVAL * MSEC_PER_SEC) +# define WATCHDOG_AUTOMONITOR_PING_INTERVAL_TICK \ + SEC2TICK(WATCHDOG_AUTOMONITOR_PING_INTERVAL) +# endif #endif /**************************************************************************** @@ -76,14 +76,16 @@ struct watchdog_upperhalf_s { #ifdef CONFIG_WATCHDOG_AUTOMONITOR -#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) - struct wdog_s wdog; -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) - struct work_s work; -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) - struct pm_callback_s idle; -#endif - bool monitor; +# if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) + FAR struct timer_lowerhalf_s *timer; +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) + struct wdog_s wdog; +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) + struct work_s work; +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) + struct pm_callback_s idle; +# endif + bool monitor; #endif uint8_t crefs; /* The number of times the device has been opened */ @@ -144,6 +146,20 @@ static int watchdog_automonitor_capture(int irq, FAR void *context, return 0; } +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) +static bool watchdog_automonitor_timer(FAR uint32_t *next_interval_us, + FAR void *arg) +{ + FAR struct watchdog_upperhalf_s *upper = arg; + FAR struct watchdog_lowerhalf_s *lower = upper->lower; + + if (upper->monitor) + { + lower->ops->keepalive(lower); + } + + return upper->monitor; +} #elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) static void watchdog_automonitor_wdog(wdparm_t arg) { @@ -153,7 +169,7 @@ static void watchdog_automonitor_wdog(wdparm_t arg) if (upper->monitor) { lower->ops->keepalive(lower); - wd_start(&upper->wdog, WATCHDOG_AUTOMONITOR_PING_INTERVAL, + wd_start(&upper->wdog, WATCHDOG_AUTOMONITOR_PING_INTERVAL_TICK, watchdog_automonitor_wdog, (wdparm_t)upper); } } @@ -167,7 +183,7 @@ static void watchdog_automonitor_worker(FAR void *arg) { lower->ops->keepalive(lower); work_queue(LPWORK, &upper->work, watchdog_automonitor_worker, - upper, WATCHDOG_AUTOMONITOR_PING_INTERVAL); + upper, WATCHDOG_AUTOMONITOR_PING_INTERVAL_TICK); } } #elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) @@ -186,26 +202,37 @@ static void watchdog_automonitor_idle(FAR struct pm_callback_s *cb, #endif #ifdef CONFIG_WATCHDOG_AUTOMONITOR -static void watchdog_automonitor_start(FAR struct watchdog_upperhalf_s - *upper) +# if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) +static void +watchdog_automonitor_start(FAR struct watchdog_upperhalf_s *upper, + FAR struct timer_lowerhalf_s *timer) +# else +static void +watchdog_automonitor_start(FAR struct watchdog_upperhalf_s *upper) +# endif { FAR struct watchdog_lowerhalf_s *lower = upper->lower; if (!upper->monitor) { upper->monitor = true; -#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) +# if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) lower->ops->capture(lower, watchdog_automonitor_capture); -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) - wd_start(&upper->wdog, WATCHDOG_AUTOMONITOR_PING_INTERVAL, +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) + upper->timer = timer; + timer->ops->setcallback(timer, watchdog_automonitor_timer, upper); + timer->ops->settimeout(timer, WATCHDOG_AUTOMONITOR_PING_INTERVAL_MSEC); + timer->ops->start(timer); +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) + wd_start(&upper->wdog, WATCHDOG_AUTOMONITOR_PING_INTERVAL_TICK, watchdog_automonitor_wdog, (wdparm_t)upper); -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) work_queue(LPWORK, &upper->work, watchdog_automonitor_worker, - upper, WATCHDOG_AUTOMONITOR_PING_INTERVAL); -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) + upper, WATCHDOG_AUTOMONITOR_PING_INTERVAL_TICK); +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) upper->idle.notify = watchdog_automonitor_idle; pm_register(&upper->idle); -#endif +# endif if (lower->ops->settimeout) { lower->ops->settimeout(lower, WATCHDOG_AUTOMONITOR_TIMEOUT_MSEC); @@ -223,15 +250,17 @@ static void watchdog_automonitor_stop(FAR struct watchdog_upperhalf_s *upper) { upper->monitor = false; lower->ops->stop(lower); -#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) +# if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) lower->ops->capture(lower, NULL); -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) + upper->timer->ops->stop(upper->timer); +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) wd_cancel(&upper->wdog); -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) work_cancel(LPWORK, &upper->work); -#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) +# elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) pm_unregister(&upper->idle); -#endif +# endif } } #endif @@ -593,8 +622,14 @@ static int wdog_ioctl(FAR struct file *filep, int cmd, unsigned long arg) * ****************************************************************************/ +#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) +FAR void *watchdog_register(FAR const char *path, + FAR struct watchdog_lowerhalf_s *lower, + FAR struct timer_lowerhalf_s *timer) +#else FAR void *watchdog_register(FAR const char *path, FAR struct watchdog_lowerhalf_s *lower) +#endif { FAR struct watchdog_upperhalf_s *upper; int ret; @@ -637,7 +672,9 @@ FAR void *watchdog_register(FAR const char *path, goto errout_with_path; } -#ifdef CONFIG_WATCHDOG_AUTOMONITOR +#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) + watchdog_automonitor_start(upper, timer); +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR) watchdog_automonitor_start(upper); #endif @@ -702,5 +739,3 @@ void watchdog_unregister(FAR void *handle) nxsem_destroy(&upper->exclsem); kmm_free(upper); } - -#endif /* CONFIG_WATCHDOG */ diff --git a/include/nuttx/timers/watchdog.h b/include/nuttx/timers/watchdog.h index 41aef68c3c..3b93d53134 100644 --- a/include/nuttx/timers/watchdog.h +++ b/include/nuttx/timers/watchdog.h @@ -224,8 +224,15 @@ extern "C" * ****************************************************************************/ +#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) +struct timer_lowerhalf_s; +FAR void *watchdog_register(FAR const char *path, + FAR struct watchdog_lowerhalf_s *lower, + FAR struct timer_lowerhalf_s *timer); +#else FAR void *watchdog_register(FAR const char *path, FAR struct watchdog_lowerhalf_s *lower); +#endif /**************************************************************************** * Name: watchdog_unregister