Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions drivers/timers/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ config TIMER_ARCH
select ARCH_HAVE_TICKLESS
select ARCH_HAVE_TIMEKEEPING
select SCHED_TICKLESS_LIMIT_MAX_SLEEP if SCHED_TICKLESS
select SCHED_TICKLESS_TICK_ARGUMENT if SCHED_TICKLESS
---help---
Implement timer arch API on top of timer driver interface.

Expand Down Expand Up @@ -147,7 +146,6 @@ 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.

Expand Down
16 changes: 14 additions & 2 deletions drivers/timers/arch_alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,18 @@ int weak_function up_timer_gettime(struct timespec *ts)
****************************************************************************/

#ifdef CONFIG_SCHED_TICKLESS
int weak_function up_alarm_cancel(FAR struct timespec *ts)
{
int ret = -EAGAIN;

if (g_oneshot_lower != NULL)
{
ret = ONESHOT_CANCEL(g_oneshot_lower, ts);
}

return ret;
}

int weak_function up_alarm_tick_cancel(FAR clock_t *ticks)
{
int ret = -EAGAIN;
Expand Down Expand Up @@ -368,7 +380,8 @@ int weak_function up_alarm_tick_cancel(FAR clock_t *ticks)
*
****************************************************************************/

int weak_function up_alarm_start(const struct timespec *ts)
#ifdef CONFIG_SCHED_TICKLESS
int weak_function up_alarm_start(FAR const struct timespec *ts)
{
int ret = -EAGAIN;

Expand All @@ -380,7 +393,6 @@ int weak_function up_alarm_start(const struct timespec *ts)
return ret;
}

#ifdef CONFIG_SCHED_TICKLESS
int weak_function up_alarm_tick_start(clock_t ticks)
{
int ret = -EAGAIN;
Expand Down
16 changes: 2 additions & 14 deletions include/nuttx/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -2002,11 +2002,8 @@ void up_timer_getmask(FAR clock_t *mask);
****************************************************************************/

#if defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_alarm_cancel(FAR struct timespec *ts);
# else
int up_alarm_tick_cancel(FAR clock_t *ticks);
# endif
#endif

/****************************************************************************
Expand Down Expand Up @@ -2034,12 +2031,9 @@ int up_alarm_tick_cancel(FAR clock_t *ticks);
*
****************************************************************************/

int up_alarm_start(FAR const struct timespec *ts);

#if defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_alarm_start(FAR const struct timespec *ts);
int up_alarm_tick_start(clock_t ticks);
# endif
#endif

/****************************************************************************
Expand Down Expand Up @@ -2079,11 +2073,8 @@ int up_alarm_tick_start(clock_t ticks);
****************************************************************************/

#if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_timer_cancel(FAR struct timespec *ts);
# else
int up_timer_tick_cancel(FAR clock_t *ticks);
# endif
#endif

/****************************************************************************
Expand Down Expand Up @@ -2111,12 +2102,9 @@ int up_timer_tick_cancel(FAR clock_t *ticks);
*
****************************************************************************/

int up_timer_start(FAR const struct timespec *ts);

#if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM)
# ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
int up_timer_start(FAR const struct timespec *ts);
int up_timer_tick_start(clock_t ticks);
# endif
#endif

/****************************************************************************
Expand Down
20 changes: 0 additions & 20 deletions sched/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -73,26 +73,6 @@ config SCHED_TICKLESS

if SCHED_TICKLESS

config SCHED_TICKLESS_TICK_ARGUMENT
bool "Scheduler use tick argument"
default n
---help---
Enables use of tick argument in scheduler. If enabled, then the
board-specific logic must provide the following functions:

int up_timer_gettick(FAR clock_t *ticks);

If SCHED_TICKLESS_ALARM is enabled, then these additional interfaces are
expected:

int up_alarm_tick_cancel(FAR clock_t *ticks);
int up_alarm_tick_start(clock_t ticks);

Otherwise, these additional interfaces are expected:

int up_timer_tick_cancel(FAR clock_t *ticks);
int up_timer_tick_start(clock_t ticks);

config SCHED_TICKLESS_ALARM
bool "Tickless alarm"
default n
Expand Down
150 changes: 76 additions & 74 deletions sched/sched/sched_timerexpiration.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,32 @@ static unsigned int g_timernested;
* Private Functions
****************************************************************************/

static inline_function clock_t adjust_next_interval(clock_t interval)
{
clock_t ret = interval;

#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP
ret = MIN(ret, g_oneshot_maxticks);
#endif

/* Normally, timer event cannot triggered on exact time due to the
* existence of interrupt latency.
* Assuming that the interrupt latency is distributed within
* [Best-Case Execution Time, Worst-Case Execution Time],
* we can set the timer adjustment value to the BCET to reduce the latency.
* After the adjustment, the timer interrupt latency will be
* [0, WCET - BCET].
* Please use this carefully, if the timer adjustment value is not the
* best-case interrupt latency, it will immediately fired another timer
* interrupt, which may result in a much larger timer interrupt latency.
*/

ret = ret <= (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK) ? 0 :
ret - (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK);

return ret;
}

static inline_function clock_t get_time_tick(void)
{
#ifdef CONFIG_SYSTEM_TIME64
Expand All @@ -126,7 +152,8 @@ static inline_function clock_t update_time_tick(clock_t tick)
#endif
}

#if !defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT) && !defined(CONFIG_CLOCK_TIMEKEEPING)
#if !defined(CONFIG_CLOCK_TIMEKEEPING) && !defined(CONFIG_ALARM_ARCH) && \
!defined(CONFIG_TIMER_ARCH)
int up_timer_gettick(FAR clock_t *ticks)
{
struct timespec ts;
Expand All @@ -137,40 +164,57 @@ int up_timer_gettick(FAR clock_t *ticks)
}
#endif

#ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT
# ifdef CONFIG_SCHED_TICKLESS_ALARM
int up_alarm_tick_start(clock_t ticks)
#ifdef CONFIG_SCHED_TICKLESS_ALARM
static inline_function
int nxsched_timer_tick_start(clock_t ticks, clock_t delay)
{
# ifndef CONFIG_ALARM_ARCH
struct timespec ts;
clock_ticks2time(&ts, ticks);
clock_ticks2time(&ts, ticks + delay);
return up_alarm_start(&ts);
# else
return up_alarm_tick_start(ticks + delay);
# endif
}

int up_alarm_tick_cancel(FAR clock_t *ticks)
static inline_function
int nxsched_timer_tick_cancel(clock_t *ticks)
{
int ret;
# ifndef CONFIG_ALARM_ARCH
struct timespec ts;
int ret;
ret = up_alarm_cancel(&ts);
ret = up_alarm_cancel(&ts);
*ticks = clock_time2ticks_floor(&ts);
# else
ret = up_alarm_tick_cancel(ticks);
# endif
return ret;
}
# else
int up_timer_tick_start(clock_t ticks)

#else
static inline_function
int nxsched_timer_tick_start(clock_t ticks, clock_t delay)
{
# ifndef CONFIG_TIMER_ARCH
struct timespec ts;
clock_ticks2time(&ts, ticks);
clock_ticks2time(&ts, delay);
return up_timer_start(&ts);
# else
return up_timer_tick_start(delay);
# endif
}

int up_timer_tick_cancel(FAR clock_t *ticks)
static inline_function
int nxsched_timer_tick_cancel(clock_t *ticks)
{
# ifndef CONFIG_TIMER_ARCH
struct timespec ts;
int ret;
ret = up_timer_cancel(&ts);
*ticks = clock_time2ticks_floor(&ts);
return ret;
}
up_timer_cancel(&ts);
# else
up_timer_cancel(ticks);
# endif
return up_timer_gettick(ticks);
}
#endif

/****************************************************************************
Expand Down Expand Up @@ -386,48 +430,10 @@ static clock_t nxsched_timer_process(clock_t ticks, clock_t elapsed,

static clock_t nxsched_timer_start(clock_t ticks, clock_t interval)
{
int ret;

if (interval != CLOCK_MAX)
{
#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP
interval = MIN(interval, g_oneshot_maxticks);
#endif

/* Normally, timer event cannot triggered on exact time
* due to the existence of interrupt latency.
* Assuming that the interrupt latency is distributed within
* [Best-Case Execution Time, Worst-Case Execution Time],
* we can set the timer adjustment value to the BCET to
* reduce the latency.
* After the adjustment, the timer interrupt latency will be
* [0, WCET - BCET].
* Please use this carefully, if the timer adjustment value is not
* the best-case interrupt latency, it will immediately fired
* another timer interrupt, which may result in a much larger timer
* interrupt latency.
*/

interval = interval <= (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK) ? 0 :
interval - (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK);

#ifdef CONFIG_SCHED_TICKLESS_ALARM
/* Convert the delay to a time in the future (with respect
* to the time when last stopped the timer).
*/

ret = up_alarm_tick_start(ticks + interval);
#else
/* [Re-]start the interval timer */

ret = up_timer_tick_start(interval);
#endif

if (ret < 0)
{
serr("ERROR: up_timer_start/up_alarm_start failed: %d\n", ret);
UNUSED(ret);
}
interval = adjust_next_interval(interval);
nxsched_timer_tick_start(ticks, interval);
}

atomic_set(&g_timer_interval, interval);
Expand All @@ -437,7 +443,6 @@ static clock_t nxsched_timer_start(clock_t ticks, clock_t interval)
static inline_function
clock_t nxsched_timer_update(clock_t ticks, bool noswitches)
{
clock_t nexttime;
clock_t elapsed;

/* Calculate the elapsed time and update clock tickbase. */
Expand All @@ -446,9 +451,7 @@ clock_t nxsched_timer_update(clock_t ticks, bool noswitches)

/* Process the timer ticks and set up the next interval (or not) */

nexttime = nxsched_timer_process(ticks, elapsed, noswitches);

return nxsched_timer_start(ticks, nexttime);
return nxsched_timer_process(ticks, elapsed, noswitches);
}

/****************************************************************************
Expand All @@ -473,16 +476,20 @@ clock_t nxsched_timer_update(clock_t ticks, bool noswitches)

void nxsched_timer_expiration(void)
{
irqstate_t flags;
clock_t ticks;
irqstate_t flags = enter_critical_section();
clock_t next;

up_timer_gettick(&ticks);

flags = enter_critical_section();

/* Get the interval associated with last expiration */

g_timernested++;

up_timer_gettick(&ticks);

nxsched_timer_update(ticks, false);
next = nxsched_timer_update(ticks, false);
nxsched_timer_start(ticks, next);

g_timernested--;

Expand Down Expand Up @@ -529,20 +536,15 @@ void nxsched_timer_expiration(void)
void nxsched_reassess_timer(void)
{
clock_t ticks;
clock_t next;

if (!g_timernested)
{
/* Cancel the timer and get the current time */

#ifdef CONFIG_SCHED_TICKLESS_ALARM
up_alarm_tick_cancel(&ticks);
#else
clock_t elapsed;
up_timer_gettick(&ticks);
up_timer_tick_cancel(&elapsed);
#endif

nxsched_timer_update(ticks, true);
nxsched_timer_tick_cancel(&ticks);
next = nxsched_timer_update(ticks, true);
nxsched_timer_start(ticks, next);
}
}

Expand Down
Loading