From 43797ea6cc431f98d9ea440824f9a84bd91ef3ec Mon Sep 17 00:00:00 2001 From: yaojiaqi Date: Mon, 30 Dec 2024 14:59:33 +0800 Subject: [PATCH] drivers/timers/watchdog: add watchdog timer notifier chain Add support for watchdog timer notifer chain so that users can customize the callback function when the watchdog timer times out which enabled by Auto-monitor Signed-off-by: yaojiaqi --- drivers/timers/Kconfig | 8 ++++ drivers/timers/watchdog.c | 67 +++++++++++++++++++++++++++++++ include/nuttx/timers/watchdog.h | 71 +++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig index b76d50e127..aaab1a4b55 100644 --- a/drivers/timers/Kconfig +++ b/drivers/timers/Kconfig @@ -439,6 +439,14 @@ menuconfig WATCHDOG_AUTOMONITOR if WATCHDOG_AUTOMONITOR +config WATCHDOG_TIMEOUT_NOTIFIER + bool "Enable watchdog timeout notifier" + default n + ---help--- + The watchdog timeout notifier chain mechanism supports users registering + custom callback functions, which will be called when the watchdog timer + managed by Auto-monitor times out. + choice prompt "Auto-monitor keepalive by" default WATCHDOG_AUTOMONITOR_BY_WDOG diff --git a/drivers/timers/watchdog.c b/drivers/timers/watchdog.c index ca4cc9aa51..b23c5e3008 100644 --- a/drivers/timers/watchdog.c +++ b/drivers/timers/watchdog.c @@ -71,6 +71,20 @@ # endif #endif +#if defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_ONESHOT) +# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_ONESHOT +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_TIMER) +# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_TIMER +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WDOG) +# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_WDOG +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_WORKER) +# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_WORKER +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_CAPTURE) +# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_CAPTURE +#elif defined(CONFIG_WATCHDOG_AUTOMONITOR_BY_IDLE) +# define WATCHDOG_NOTIFIER_ACTION WATCHDOG_KEEPALIVE_BY_IDLE +#endif + /**************************************************************************** * Private Type Definitions ****************************************************************************/ @@ -135,6 +149,10 @@ static const struct file_operations g_wdogops = wdog_ioctl, /* ioctl */ }; +#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER +static ATOMIC_NOTIFIER_HEAD(g_watchdog_notifier_list); +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -699,6 +717,55 @@ static int wdog_ioctl(FAR struct file *filep, int cmd, unsigned long arg) * Public Functions ****************************************************************************/ +#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER +/**************************************************************************** + * Name: watchdog_notifier_chain_register + * + * Description: + * Add notifier to the watchdog notifier chain + * + * Input Parameters: + * nb - New entry in notifier chain + * + ****************************************************************************/ + +void watchdog_notifier_chain_register(FAR struct notifier_block *nb) +{ + atomic_notifier_chain_register(&g_watchdog_notifier_list, nb); +} + +/**************************************************************************** + * Name: watchdog_notifier_chain_unregister + * + * Description: + * Remove notifier from the watchdog notifier chain + * + * Input Parameters: + * nb - Entry to remove from notifier chain + * + ****************************************************************************/ + +void watchdog_notifier_chain_unregister(FAR struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&g_watchdog_notifier_list, nb); +} + +/**************************************************************************** + * Name: watchdog_automonitor_timeout + * + * Description: + * This function can be called in the watchdog timeout interrupt handler. + * If so, callbacks on the watchdog timer notify chain are called when the + * watchdog timer times out. + * + ****************************************************************************/ + +void watchdog_automonitor_timeout(void) +{ + atomic_notifier_call_chain(&g_watchdog_notifier_list, action, data); +} +#endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */ + /**************************************************************************** * Name: watchdog_register * diff --git a/include/nuttx/timers/watchdog.h b/include/nuttx/timers/watchdog.h index d29a7c80ff..6b1b2c15ab 100644 --- a/include/nuttx/timers/watchdog.h +++ b/include/nuttx/timers/watchdog.h @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_WATCHDOG @@ -88,6 +89,35 @@ #define WDFLAGS_CAPTURE (1 << 2) /* 1=Call the user function when the * watchdog timer expires */ +/* Keepalive Actions ********************************************************/ + +/* According to the keepalive action specified by the Auto-monitor, callback + * functions registered on the watchdog notifier chain may take corresponding + * actions. + * + * These are detected and handled by the "upper half" watchdog timer driver. + * + * WATCHDOG_KEEPALIVE_BY_ONESHOT - The watchdog timer is keepalive by + * oneshot timer. + * WATCHDOG_KEEPALIVE_BY_TIMER - The watchdog timer is keepalive by + * timer. + * WATCHDOG_KEEPALIVE_BY_WDOG - The watchdog timer is keepalive by + * wdog. + * WATCHDOG_KEEPALIVE_BY_WORKER - The watchdog timer is keepalive by + * worker queue. + * WATCHDOG_KEEPALIVE_BY_CAPTURE - The watchdog timer is keepalive by + * capture. + * WATCHDOG_KEEPALIVE_BY_IDLE - The watchdog timer is keepalive by + * idle task. + */ + +#define WATCHDOG_KEEPALIVE_BY_ONESHOT 0 +#define WATCHDOG_KEEPALIVE_BY_TIMER 1 +#define WATCHDOG_KEEPALIVE_BY_WDOG 2 +#define WATCHDOG_KEEPALIVE_BY_WORKER 3 +#define WATCHDOG_KEEPALIVE_BY_CAPTURE 4 +#define WATCHDOG_KEEPALIVE_BY_IDLE 5 + /**************************************************************************** * Public Types ****************************************************************************/ @@ -197,6 +227,47 @@ extern "C" #define EXTERN extern #endif +#ifdef CONFIG_WATCHDOG_TIMEOUT_NOTIFIER +/**************************************************************************** + * Name: watchdog_notifier_chain_register + * + * Description: + * Add notifier to the watchdog notifier chain + * + * Input Parameters: + * nb - New entry in notifier chain + * + ****************************************************************************/ + +void watchdog_notifier_chain_register(FAR struct notifier_block *nb); + +/**************************************************************************** + * Name: watchdog_notifier_chain_unregister + * + * Description: + * Remove notifier from the watchdog notifier chain + * + * Input Parameters: + * nb - Entry to remove from notifier chain + * + ****************************************************************************/ + +void watchdog_notifier_chain_unregister(FAR struct notifier_block *nb); + +/**************************************************************************** + * Name: watchdog_automonitor_timeout + * + * Description: + * This function can be called in the watchdog timeout interrupt handler. + * If so, callbacks on the watchdog timer notify chain are called when the + * watchdog timer times out. + * + ****************************************************************************/ + +void watchdog_automonitor_timeout(void); + +#endif /* CONFIG_WATCHDOG_TIMEOUT_NOTIFIER */ + /**************************************************************************** * Name: watchdog_register *