diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 150fed2b991..413e9007ca1 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -244,6 +244,15 @@ config TIMER_READS_ITS_FREQUENCY_AT_RUNTIME The drivers select this option automatically when needed. Do not modify this unless you have a very good reason for it. +config SYSTEM_CLOCK_SLOPPY_IDLE + bool "Timer allowed to skew uptime clock during idle" + help + When true, the timer driver is not required to maintain a + correct system uptime count when the system enters idle. + Some platforms may take advantage of this to reduce the + overhead from regular interrupts required to handle counter + wraparound conditions. + config SYSTEM_CLOCK_INIT_PRIORITY int "System clock driver initialization priority" default 0 diff --git a/include/kernel.h b/include/kernel.h index 8840afc6a0b..b42c45e77e0 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -1672,26 +1672,36 @@ __syscall s64_t k_uptime_get(void); /** * @brief Enable clock always on in tickless kernel * - * This routine enables keeping the clock running (that is, it always - * keeps an active timer interrupt scheduled) when there are no timer - * events programmed in tickless kernel scheduling. This is necessary - * if the clock is used to track passage of time (e.g. via - * k_uptime_get_32()), otherwise the internal hardware counter may - * roll over between interrupts. + * Deprecated. This does nothing (it was always just a hint). This + * functionality has been migrated to the SYSTEM_CLOCK_SLOPPY_IDLE + * kconfig. * * @retval prev_status Previous status of always on flag */ -int k_enable_sys_clock_always_on(void); +/* LCOV_EXCL_START */ +__deprecated static inline int k_enable_sys_clock_always_on(void) +{ + __ASSERT(IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE), + "Please use CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE instead"); + + return !IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE); +} +/* LCOV_EXCL_STOP */ /** * @brief Disable clock always on in tickless kernel * - * This routine disables keeping the clock running when - * there are no timer events programmed in tickless kernel - * scheduling. To save power, this routine should be called - * immediately when clock is not used to track time. + * Deprecated. This does nothing (it was always just a hint). This + * functionality has been migrated to the SYS_CLOCK_SLOPPY_IDLE + * kconfig. */ -void k_disable_sys_clock_always_on(void); +/* LCOV_EXCL_START */ +__deprecated static inline void k_disable_sys_clock_always_on(void) +{ + __ASSERT(!IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE), + "Please use CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE instead"); +} +/* LCOV_EXCL_STOP */ /** * @brief Get system uptime (32-bit version). diff --git a/kernel/timeout.c b/kernel/timeout.c index 9801fb9714e..52bb2ef9903 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -21,7 +21,8 @@ static sys_dlist_t timeout_list = SYS_DLIST_STATIC_INIT(&timeout_list); static struct k_spinlock timeout_lock; -static bool can_wait_forever; +#define MAX_WAIT (IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE) \ + ? K_FOREVER : INT_MAX) /* Cycles left to process in the currently-executing z_clock_announce() */ static int announce_remaining; @@ -67,9 +68,8 @@ static s32_t elapsed(void) static s32_t next_timeout(void) { - int maxw = can_wait_forever ? K_FOREVER : INT_MAX; struct _timeout *to = first(); - s32_t ret = to == NULL ? maxw : MAX(0, to->dticks - elapsed()); + s32_t ret = to == NULL ? MAX_WAIT : MAX(0, to->dticks - elapsed()); #ifdef CONFIG_TIMESLICING if (_current_cpu->slice_ticks && _current_cpu->slice_ticks < ret) { @@ -209,19 +209,6 @@ void z_clock_announce(s32_t ticks) k_spin_unlock(&timeout_lock, key); } -int k_enable_sys_clock_always_on(void) -{ - int ret = !can_wait_forever; - - can_wait_forever = 0; - return ret; -} - -void k_disable_sys_clock_always_on(void) -{ - can_wait_forever = 1; -} - s64_t z_tick_get(void) { u64_t t = 0U;