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

View File

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

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