arch_alarm: adjust oneshot/arch_alarm to support tick

This commit is contained in:
zhangyuan21 2022-09-23 14:36:49 +08:00 committed by Xiang Xiao
parent 750007ded9
commit fc9b5e1980
3 changed files with 178 additions and 61 deletions

View File

@ -96,6 +96,7 @@ config ALARM_ARCH
select ARCH_HAVE_TIMEKEEPING select ARCH_HAVE_TIMEKEEPING
select SCHED_TICKLESS_ALARM if SCHED_TICKLESS select SCHED_TICKLESS_ALARM if SCHED_TICKLESS
select SCHED_TICKLESS_LIMIT_MAX_SLEEP if SCHED_TICKLESS select SCHED_TICKLESS_LIMIT_MAX_SLEEP if SCHED_TICKLESS
select SCHED_TICKLESS_TICK_ARGUMENT if SCHED_TICKLESS
---help--- ---help---
Implement alarm arch API on top of oneshot driver interface. Implement alarm arch API on top of oneshot driver interface.

View File

@ -123,27 +123,27 @@ static void udelay_coarse(useconds_t microseconds)
static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower, static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower,
FAR void *arg) FAR void *arg)
{ {
struct timespec now; clock_t now = 0;
#ifdef CONFIG_SCHED_TICKLESS #ifdef CONFIG_SCHED_TICKLESS
ONESHOT_CURRENT(g_oneshot_lower, &now); ONESHOT_TICK_CURRENT(g_oneshot_lower, &now);
nxsched_alarm_expiration(&now); nxsched_alarm_tick_expiration(now);
#else #else
struct timespec delta; clock_t delta;
do do
{ {
static uint64_t tick = 1; static clock_t tick = 1;
struct timespec next; clock_t next;
nxsched_process_timer(); nxsched_process_timer();
timespec_from_usec(&next, ++tick * USEC_PER_TICK); next = ++tick;
ONESHOT_CURRENT(g_oneshot_lower, &now); ONESHOT_TICK_CURRENT(g_oneshot_lower, &now);
clock_timespec_subtract(&next, &now, &delta); 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 #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) void up_alarm_set_lowerhalf(FAR struct oneshot_lowerhalf_s *lower)
{ {
#ifdef CONFIG_SCHED_TICKLESS #ifdef CONFIG_SCHED_TICKLESS
struct timespec maxts; clock_t ticks;
uint64_t maxticks; #endif
g_oneshot_lower = lower; g_oneshot_lower = lower;
ONESHOT_MAX_DELAY(g_oneshot_lower, &maxts);
maxticks = timespec_to_usec(&maxts) / USEC_PER_TICK; #ifdef CONFIG_SCHED_TICKLESS
g_oneshot_maxticks = maxticks < UINT32_MAX ? maxticks : UINT32_MAX; ONESHOT_TICK_MAX_DELAY(g_oneshot_lower, &ticks);
g_oneshot_maxticks = ticks < UINT32_MAX ? ticks : UINT32_MAX;
#else #else
struct timespec ts; ONESHOT_TICK_START(g_oneshot_lower, oneshot_callback, NULL, 1);
g_oneshot_lower = lower;
timespec_from_usec(&ts, USEC_PER_TICK);
ONESHOT_START(g_oneshot_lower, oneshot_callback, NULL, &ts);
#endif #endif
} }
@ -210,11 +207,9 @@ void weak_function up_timer_getmask(FAR clock_t *mask)
if (g_oneshot_lower != NULL) if (g_oneshot_lower != NULL)
{ {
struct timespec maxts;
clock_t maxticks; clock_t maxticks;
ONESHOT_MAX_DELAY(g_oneshot_lower, &maxts); ONESHOT_TICK_MAX_DELAY(g_oneshot_lower, &maxticks);
maxticks = timespec_to_usec(&maxts) / USEC_PER_TICK;
for (; ; ) for (; ; )
{ {
@ -230,34 +225,14 @@ void weak_function up_timer_getmask(FAR clock_t *mask)
} }
#endif #endif
#if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT) #if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_CLOCK_TIMEKEEPING)
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)
int weak_function up_timer_gettick(FAR clock_t *ticks) int weak_function up_timer_gettick(FAR clock_t *ticks)
{ {
int ret = -EAGAIN; int ret = -EAGAIN;
if (g_oneshot_lower != NULL) if (g_oneshot_lower != NULL)
{ {
struct timespec now; ret = ONESHOT_TICK_CURRENT(g_oneshot_lower, ticks);
ret = ONESHOT_CURRENT(g_oneshot_lower, &now);
if (ret == 0)
{
*ticks = timespec_to_usec(&now) / USEC_PER_TICK;
}
} }
return ret; return ret;
@ -299,14 +274,14 @@ int weak_function up_timer_gettick(FAR clock_t *ticks)
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS #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; int ret = -EAGAIN;
if (g_oneshot_lower != NULL) if (g_oneshot_lower != NULL)
{ {
ret = ONESHOT_CANCEL(g_oneshot_lower, ts); ret = ONESHOT_TICK_CANCEL(g_oneshot_lower, ticks);
ONESHOT_CURRENT(g_oneshot_lower, ts); ONESHOT_TICK_CURRENT(g_oneshot_lower, ticks);
} }
return ret; return ret;
@ -338,18 +313,24 @@ int weak_function up_alarm_cancel(FAR struct timespec *ts)
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS #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; int ret = -EAGAIN;
if (g_oneshot_lower != NULL) if (g_oneshot_lower != NULL)
{ {
struct timespec now; clock_t now = 0;
struct timespec delta; clock_t delta;
ONESHOT_CURRENT(g_oneshot_lower, &now); ONESHOT_TICK_CURRENT(g_oneshot_lower, &now);
clock_timespec_subtract(ts, &now, &delta); delta = ticks - now;
ret = ONESHOT_START(g_oneshot_lower, oneshot_callback, NULL, &delta); if ((sclock_t)delta < 0)
{
delta = 0;
}
ret = ONESHOT_TICK_START(g_oneshot_lower, oneshot_callback,
NULL, delta);
} }
return ret; return ret;

View File

@ -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 * 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 * 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 * 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 * Public Types
@ -188,10 +200,19 @@ struct oneshot_operations_s
CODE int (*start)(FAR struct oneshot_lowerhalf_s *lower, CODE int (*start)(FAR struct oneshot_lowerhalf_s *lower,
oneshot_callback_t callback, FAR void *arg, oneshot_callback_t callback, FAR void *arg,
FAR const struct timespec *ts); 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); 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); 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 /* This structure describes the state of the oneshot timer lower-half
@ -237,6 +258,120 @@ extern "C"
* Public Function Prototypes * 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 * Name: oneshot_initialize
* *