diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig index ab69d8d3a8..b3ffd2cef2 100644 --- a/drivers/timers/Kconfig +++ b/drivers/timers/Kconfig @@ -96,6 +96,7 @@ config ALARM_ARCH select ARCH_HAVE_TIMEKEEPING select SCHED_TICKLESS_ALARM if SCHED_TICKLESS select SCHED_TICKLESS_LIMIT_MAX_SLEEP if SCHED_TICKLESS + select SCHED_TICKLESS_TICK_ARGUMENT if SCHED_TICKLESS ---help--- Implement alarm arch API on top of oneshot driver interface. diff --git a/drivers/timers/arch_alarm.c b/drivers/timers/arch_alarm.c index 31442106e2..85565c2a33 100644 --- a/drivers/timers/arch_alarm.c +++ b/drivers/timers/arch_alarm.c @@ -123,27 +123,27 @@ static void udelay_coarse(useconds_t microseconds) static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower, FAR void *arg) { - struct timespec now; + clock_t now = 0; #ifdef CONFIG_SCHED_TICKLESS - ONESHOT_CURRENT(g_oneshot_lower, &now); - nxsched_alarm_expiration(&now); + ONESHOT_TICK_CURRENT(g_oneshot_lower, &now); + nxsched_alarm_tick_expiration(now); #else - struct timespec delta; + clock_t delta; do { - static uint64_t tick = 1; - struct timespec next; + static clock_t tick = 1; + clock_t next; nxsched_process_timer(); - timespec_from_usec(&next, ++tick * USEC_PER_TICK); - ONESHOT_CURRENT(g_oneshot_lower, &now); - clock_timespec_subtract(&next, &now, &delta); + next = ++tick; + ONESHOT_TICK_CURRENT(g_oneshot_lower, &now); + delta = next - now; } - while (delta.tv_sec == 0 && delta.tv_nsec == 0); + while ((sclock_t)delta <= 0); - ONESHOT_START(g_oneshot_lower, oneshot_callback, NULL, &delta); + ONESHOT_TICK_START(g_oneshot_lower, oneshot_callback, NULL, delta); #endif } @@ -154,19 +154,16 @@ static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower, void up_alarm_set_lowerhalf(FAR struct oneshot_lowerhalf_s *lower) { #ifdef CONFIG_SCHED_TICKLESS - struct timespec maxts; - uint64_t maxticks; + clock_t ticks; +#endif g_oneshot_lower = lower; - ONESHOT_MAX_DELAY(g_oneshot_lower, &maxts); - maxticks = timespec_to_usec(&maxts) / USEC_PER_TICK; - g_oneshot_maxticks = maxticks < UINT32_MAX ? maxticks : UINT32_MAX; + +#ifdef CONFIG_SCHED_TICKLESS + ONESHOT_TICK_MAX_DELAY(g_oneshot_lower, &ticks); + g_oneshot_maxticks = ticks < UINT32_MAX ? ticks : UINT32_MAX; #else - struct timespec ts; - - g_oneshot_lower = lower; - timespec_from_usec(&ts, USEC_PER_TICK); - ONESHOT_START(g_oneshot_lower, oneshot_callback, NULL, &ts); + ONESHOT_TICK_START(g_oneshot_lower, oneshot_callback, NULL, 1); #endif } @@ -210,11 +207,9 @@ void weak_function up_timer_getmask(FAR clock_t *mask) if (g_oneshot_lower != NULL) { - struct timespec maxts; clock_t maxticks; - ONESHOT_MAX_DELAY(g_oneshot_lower, &maxts); - maxticks = timespec_to_usec(&maxts) / USEC_PER_TICK; + ONESHOT_TICK_MAX_DELAY(g_oneshot_lower, &maxticks); for (; ; ) { @@ -230,34 +225,14 @@ void weak_function up_timer_getmask(FAR clock_t *mask) } #endif -#if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT) -int weak_function up_timer_gettime(FAR struct timespec *ts) -{ - int ret = -EAGAIN; - - if (g_oneshot_lower != NULL) - { - ret = ONESHOT_CURRENT(g_oneshot_lower, ts); - } - - return ret; -} -#endif - -#if defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT) || defined(CONFIG_CLOCK_TIMEKEEPING) +#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_CLOCK_TIMEKEEPING) int weak_function up_timer_gettick(FAR clock_t *ticks) { int ret = -EAGAIN; if (g_oneshot_lower != NULL) { - struct timespec now; - - ret = ONESHOT_CURRENT(g_oneshot_lower, &now); - if (ret == 0) - { - *ticks = timespec_to_usec(&now) / USEC_PER_TICK; - } + ret = ONESHOT_TICK_CURRENT(g_oneshot_lower, ticks); } return ret; @@ -299,14 +274,14 @@ int weak_function up_timer_gettick(FAR clock_t *ticks) ****************************************************************************/ #ifdef CONFIG_SCHED_TICKLESS -int weak_function up_alarm_cancel(FAR struct timespec *ts) +int weak_function up_alarm_tick_cancel(FAR clock_t *ticks) { int ret = -EAGAIN; if (g_oneshot_lower != NULL) { - ret = ONESHOT_CANCEL(g_oneshot_lower, ts); - ONESHOT_CURRENT(g_oneshot_lower, ts); + ret = ONESHOT_TICK_CANCEL(g_oneshot_lower, ticks); + ONESHOT_TICK_CURRENT(g_oneshot_lower, ticks); } return ret; @@ -338,18 +313,24 @@ int weak_function up_alarm_cancel(FAR struct timespec *ts) ****************************************************************************/ #ifdef CONFIG_SCHED_TICKLESS -int weak_function up_alarm_start(FAR const struct timespec *ts) +int weak_function up_alarm_tick_start(clock_t ticks) { int ret = -EAGAIN; if (g_oneshot_lower != NULL) { - struct timespec now; - struct timespec delta; + clock_t now = 0; + clock_t delta; - ONESHOT_CURRENT(g_oneshot_lower, &now); - clock_timespec_subtract(ts, &now, &delta); - ret = ONESHOT_START(g_oneshot_lower, oneshot_callback, NULL, &delta); + ONESHOT_TICK_CURRENT(g_oneshot_lower, &now); + delta = ticks - now; + if ((sclock_t)delta < 0) + { + delta = 0; + } + + ret = ONESHOT_TICK_START(g_oneshot_lower, oneshot_callback, + NULL, delta); } return ret; diff --git a/include/nuttx/timers/oneshot.h b/include/nuttx/timers/oneshot.h index 9b7250352f..0a18aee287 100644 --- a/include/nuttx/timers/oneshot.h +++ b/include/nuttx/timers/oneshot.h @@ -91,7 +91,10 @@ * ****************************************************************************/ -#define ONESHOT_MAX_DELAY(l,t) ((l)->ops->max_delay(l,t)) +#define ONESHOT_MAX_DELAY(l,t) \ + ((l)->ops->max_delay ? (l)->ops->max_delay(l,t) : oneshot_max_delay(l,t)) +#define ONESHOT_TICK_MAX_DELAY(l,t) \ + ((l)->ops->tick_max_delay ? (l)->ops->tick_max_delay(l,t) : oneshot_tick_max_delay(l,t)) /**************************************************************************** * Name: ONESHOT_START @@ -113,7 +116,10 @@ * ****************************************************************************/ -#define ONESHOT_START(l,h,a,t) ((l)->ops->start(l,h,a,t)) +#define ONESHOT_START(l,h,a,t) \ + ((l)->ops->start ? (l)->ops->start(l,h,a,t) : oneshot_start(l,h,a,t)) +#define ONESHOT_TICK_START(l,h,a,t) \ + ((l)->ops->tick_start ? (l)->ops->tick_start(l,h,a,t) : oneshot_tick_start(l,h,a,t)) /**************************************************************************** * Name: ONESHOT_CANCEL @@ -139,7 +145,10 @@ * ****************************************************************************/ -#define ONESHOT_CANCEL(l,t) ((l)->ops->cancel(l,t)) +#define ONESHOT_CANCEL(l,t) \ + ((l)->ops->cancel ? (l)->ops->cancel(l,t) : oneshot_cancel(l,t)) +#define ONESHOT_TICK_CANCEL(l,t) \ + ((l)->ops->tick_cancel ? (l)->ops->tick_cancel(l,t) : oneshot_tick_cancel(l,t)) /**************************************************************************** * Name: ONESHOT_CURRENT @@ -160,7 +169,10 @@ * ****************************************************************************/ -#define ONESHOT_CURRENT(l,t) ((l)->ops->current ? (l)->ops->current(l,t) : -ENOSYS) +#define ONESHOT_CURRENT(l,t) \ + ((l)->ops->current ? (l)->ops->current(l,t) : oneshot_current(l,t)) +#define ONESHOT_TICK_CURRENT(l,t) \ + ((l)->ops->tick_current ? (l)->ops->tick_current(l,t) : oneshot_tick_current(l,t)) /**************************************************************************** * Public Types @@ -188,10 +200,19 @@ struct oneshot_operations_s CODE int (*start)(FAR struct oneshot_lowerhalf_s *lower, oneshot_callback_t callback, FAR void *arg, FAR const struct timespec *ts); - CODE int (*cancel)(struct oneshot_lowerhalf_s *lower, + CODE int (*cancel)(FAR struct oneshot_lowerhalf_s *lower, FAR struct timespec *ts); - CODE int (*current)(struct oneshot_lowerhalf_s *lower, + CODE int (*current)(FAR struct oneshot_lowerhalf_s *lower, FAR struct timespec *ts); + CODE int (*tick_max_delay)(FAR struct oneshot_lowerhalf_s *lower, + FAR clock_t *ticks); + CODE int (*tick_start)(FAR struct oneshot_lowerhalf_s *lower, + oneshot_callback_t callback, FAR void *arg, + clock_t ticks); + CODE int (*tick_cancel)(FAR struct oneshot_lowerhalf_s *lower, + FAR clock_t *ticks); + CODE int (*tick_current)(FAR struct oneshot_lowerhalf_s *lower, + FAR clock_t *ticks); }; /* This structure describes the state of the oneshot timer lower-half @@ -237,6 +258,120 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +static inline +int oneshot_max_delay(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts) +{ + clock_t tick; + int ret; + + DEBUGASSERT(lower->ops->tick_max_delay); + + ret = lower->ops->tick_max_delay(lower, &tick); + timespec_from_tick(ts, tick); + return ret; +} + +static inline +int oneshot_start(FAR struct oneshot_lowerhalf_s *lower, + oneshot_callback_t callback, FAR void *arg, + FAR const struct timespec *ts) +{ + clock_t tick; + + DEBUGASSERT(lower->ops->tick_start); + + tick = timespec_to_tick(ts); + return lower->ops->tick_start(lower, callback, arg, tick); +} + +static inline +int oneshot_cancel(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts) +{ + clock_t tick; + int ret; + + DEBUGASSERT(lower->ops->tick_cancel); + + ret = lower->ops->tick_cancel(lower, &tick); + timespec_from_tick(ts, tick); + + return ret; +} + +static inline +int oneshot_current(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts) +{ + clock_t tick; + int ret; + + DEBUGASSERT(lower->ops->tick_current); + + ret = lower->ops->tick_current(lower, &tick); + timespec_from_tick(ts, tick); + + return ret; +} + +static inline +int oneshot_tick_max_delay(FAR struct oneshot_lowerhalf_s *lower, + FAR clock_t *ticks) +{ + struct timespec ts; + int ret; + + DEBUGASSERT(lower->ops->max_delay); + + ret = lower->ops->max_delay(lower, &ts); + *ticks = timespec_to_tick(&ts); + return ret; +} + +static inline +int oneshot_tick_start(FAR struct oneshot_lowerhalf_s *lower, + oneshot_callback_t callback, FAR void *arg, + clock_t ticks) +{ + struct timespec ts; + + DEBUGASSERT(lower->ops->start); + + timespec_from_tick(&ts, ticks); + return lower->ops->start(lower, callback, arg, &ts); +} + +static inline +int oneshot_tick_cancel(FAR struct oneshot_lowerhalf_s *lower, + FAR clock_t *ticks) +{ + struct timespec ts; + int ret; + + DEBUGASSERT(lower->ops->cancel); + + ret = lower->ops->cancel(lower, &ts); + *ticks = timespec_to_tick(&ts); + + return ret; +} + +static inline +int oneshot_tick_current(FAR struct oneshot_lowerhalf_s *lower, + FAR clock_t *ticks) +{ + struct timespec ts; + int ret; + + DEBUGASSERT(lower->ops->current); + + ret = lower->ops->current(lower, &ts); + *ticks = timespec_to_tick(&ts); + + return ret; +} + /**************************************************************************** * Name: oneshot_initialize *