diff --git a/sched/wdog/wd_gettime.c b/sched/wdog/wd_gettime.c index 1195e41626..be8ce9883a 100644 --- a/sched/wdog/wd_gettime.c +++ b/sched/wdog/wd_gettime.c @@ -88,6 +88,7 @@ int wd_gettime(WDOG_ID wdog) delay += curr->lag; if (curr == wdog) { + delay -= wd_elapse(); leave_critical_section(flags); return delay; } diff --git a/sched/wdog/wd_initialize.c b/sched/wdog/wd_initialize.c index 2b8ffdca62..b29a32ad89 100644 --- a/sched/wdog/wd_initialize.c +++ b/sched/wdog/wd_initialize.c @@ -67,6 +67,14 @@ sq_queue_t g_wdactivelist; uint16_t g_wdnfree; +/* This is wdog tickbase, for wd_gettime() may called many times + * between 2 times of wd_timer(), we use it to update wd_gettime(). + */ + +#ifdef CONFIG_SCHED_TICKLESS +clock_t g_wdtickbase; +#endif + /**************************************************************************** * Private Data ****************************************************************************/ diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c index 9bfc56a41d..ab38bbcbc3 100644 --- a/sched/wdog/wd_start.c +++ b/sched/wdog/wd_start.c @@ -292,6 +292,12 @@ int wd_start(WDOG_ID wdog, int32_t delay, wdentry_t wdentry, int argc, ...) if (g_wdactivelist.head == NULL) { +#ifdef CONFIG_SCHED_TICKLESS + /* Update clock tickbase */ + + g_wdtickbase = clock_systimer(); +#endif + /* Add the watchdog to the head == tail of the queue. */ sq_addlast((FAR sq_entry_t *)wdog, &g_wdactivelist); @@ -461,14 +467,19 @@ unsigned int wd_timer(int ticks) /* There are. Decrement the lag counter */ - wdog->lag -= decr; - ticks -= decr; + wdog->lag -= decr; + ticks -= decr; + g_wdtickbase += decr; /* Check if the watchdog at the head of the list is ready to run */ wd_expiration(); } + /* Update clock tickbase */ + + g_wdtickbase += ticks; + /* Return the delay for the next watchdog to expire */ ret = g_wdactivelist.head ? diff --git a/sched/wdog/wdog.h b/sched/wdog/wdog.h index 559580be5b..30bcec5401 100644 --- a/sched/wdog/wdog.h +++ b/sched/wdog/wdog.h @@ -46,8 +46,30 @@ #include #include +#include #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: wd_elapse + * + * Description: + * This function is used to get time-elapse from last time wd_timer() be + * called. In case of CONFIG_SCHED_TICKLESS configured, wd_timer() may + * take lots of ticks, during this time, wd_start()/wd_cancel() may + * called, so we need wd_elapse() to correct the delay/lag. + * + ****************************************************************************/ + +#ifdef CONFIG_SCHED_TICKLESS +# define wd_elapse() (clock_systimer() - g_wdtickbase) +#else +# define wd_elapse() (0) +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -80,6 +102,14 @@ extern sq_queue_t g_wdactivelist; extern uint16_t g_wdnfree; +/* This is wdog tickbase, for wd_gettime() may called many times + * between 2 times of wd_timer(), we use it to update wd_gettime(). + */ + +#ifdef CONFIG_SCHED_TICKLESS +extern clock_t g_wdtickbase; +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/