watchdog: Support auto monitor keep alive from timer lowerhalf

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2022-09-18 10:47:19 +08:00 committed by Petro Karashchenko
parent 47d2859f85
commit 1eefec4db3
3 changed files with 93 additions and 47 deletions

View File

@ -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

View File

@ -40,31 +40,31 @@
#include <nuttx/semaphore.h>
#include <nuttx/wdog.h>
#include <nuttx/wqueue.h>
#include <nuttx/timers/timer.h>
#include <nuttx/timers/watchdog.h>
#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 */

View File

@ -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