Commit c076d94e authored by Anas Nashif's avatar Anas Nashif
Browse files

kernel: remove tickless idle



This feature predated the tickless kernel and has been in legacy mode
for a while. We now have no drivers or systems that do not support
tickless, so remove this option and cleanup the code to only use
tickless.

Signed-off-by: default avatarAnas Nashif <anas.nashif@intel.com>
parent c5d6bdb4
Loading
Loading
Loading
Loading
+0 −35
Original line number Diff line number Diff line
@@ -47,34 +47,6 @@ The power management features are classified into the following categories.
* System Power Management
* Device Power Management

Tickless Idle
*************

This is the name used to identify the event-based idling mechanism of the
Zephyr RTOS kernel scheduler. The kernel scheduler can run in two modes. During
normal operation, when at least one thread is active, it sets up the system
timer in periodic mode and runs in an interval-based scheduling mode. The
interval-based mode allows it to time slice between threads. Many times, the
threads would be waiting on semaphores, timeouts or for events. When there
are no threads running, it is inefficient for the kernel scheduler to run
in interval-based mode. This is because, in this mode the timer would trigger
an interrupt at fixed intervals causing the scheduler to be invoked at each
interval. The scheduler checks if any thread is ready to run. If no thread
is ready to run then it is a waste of power because of the unnecessary CPU
processing. This is avoided by the kernel switching to event-based idling
mode whenever there is no thread ready to run.

The kernel holds an ordered list of thread timeouts in the system. These are
the amount of time each thread has requested to wait. When the last active
thread goes to wait, the idle thread is scheduled. The idle thread programs
the timer to one-shot mode and programs the count to the earliest timeout
from the ordered thread timeout list. When the timer expires, a timer event
is generated. The ISR of this event will invoke the scheduler, which would
schedule the thread associated with the timeout. Before scheduling the
thread, the scheduler would switch the timer again to periodic mode. This
method saves power because the CPU is removed from the wait only when there
is a thread ready to run or if an external event occurred.

System Power Management
***********************

@@ -90,9 +62,6 @@ such as a SysTick, RTC, counter, or GPIO. Depending on the power mode entered,
only some SoC peripheral modules may be active and can be used as a wake up
source.

Enabling system power management compels the Zephyr kernel scheduler to work in
tickless idle mode (see :option:`CONFIG_TICKLESS_IDLE`).

Power States
============

@@ -485,10 +454,6 @@ the following configuration flags.

   This flag enables the power management subsystem.

:option:`CONFIG_TICKLESS_IDLE`

   This flag enables the tickless idle power saving feature.

:option:`CONFIG_PM_DEVICE`

   This flag is enabled if the SOC interface and the devices support device power
+0 −2
Original line number Diff line number Diff line
@@ -189,7 +189,6 @@ config RV32M1_LPTMR_TIMER
	bool "RV32M1 LPTMR system timer driver"
	default y
	depends on SOC_OPENISA_RV32M1_RISCV32
	depends on !TICKLESS_IDLE
	depends on RV32M1_INTMUX
	help
	  This module implements a kernel device driver for using the LPTMR
@@ -199,7 +198,6 @@ config RV32M1_LPTMR_TIMER
config LITEX_TIMER
	bool "LiteX Timer"
	default y
	depends on !TICKLESS_IDLE
	depends on SOC_RISCV32_LITEX_VEXRISCV
	help
	  This module implements a kernel device driver for LiteX Timer.
+18 −2
Original line number Diff line number Diff line
@@ -13,12 +13,23 @@
#include "altera_avalon_timer_regs.h"
#include "altera_avalon_timer.h"

#include "legacy_api.h"
/* The old driver "now" API would return a full uptime value.  The new
 * one only requires the driver to track ticks since the last announce
 * call.  Implement the new call in terms of the old one on legacy
 * drivers by keeping (yet another) uptime value locally.
 */
static uint32_t driver_uptime;

static uint32_t accumulated_cycle_count;

static int32_t _sys_idle_elapsed_ticks = 1;

static void wrapped_announce(int32_t ticks)
{
	driver_uptime += ticks;
	sys_clock_announce(ticks);
}

static void timer_irq_handler(const void *unused)
{
	ARG_UNUSED(unused);
@@ -28,7 +39,7 @@ static void timer_irq_handler(const void *unused)
	/* Clear the interrupt */
	alt_handle_irq((void *)TIMER_0_BASE, TIMER_0_IRQ);

	sys_clock_announce(_sys_idle_elapsed_ticks);
	wrapped_announce(_sys_idle_elapsed_ticks);
}

int sys_clock_driver_init(const struct device *device)
@@ -69,3 +80,8 @@ uint32_t sys_clock_cycle_get_32(void)
	 */
	return accumulated_cycle_count;
}

uint32_t sys_clock_elapsed(void)
{
	return 0;
}
+2 −3
Original line number Diff line number Diff line
@@ -326,7 +326,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
	 * However for single core using 32-bits arc timer, idle cannot
	 * be ignored, as 32-bits timer will overflow in a not-long time.
	 */
	if (IS_ENABLED(CONFIG_TICKLESS_IDLE) && ticks == K_TICKS_FOREVER) {
	if (IS_ENABLED(CONFIG_TICKLESS_KERNEL) && ticks == K_TICKS_FOREVER) {
		timer0_control_register_set(0);
		timer0_count_register_set(0);
		timer0_limit_register_set(0);
@@ -356,8 +356,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
	arch_irq_unlock(key);
#endif
#else
	if (IS_ENABLED(CONFIG_TICKLESS_IDLE) && idle
	    && ticks == K_TICKS_FOREVER) {
	if (IS_ENABLED(CONFIG_TICKLESS_KERNEL) && idle && ticks == K_TICKS_FOREVER) {
		timer0_control_register_set(0);
		timer0_count_register_set(0);
		timer0_limit_register_set(0);
+1 −2
Original line number Diff line number Diff line
@@ -172,8 +172,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
	 * the counter. (Note: we can assume if idle==true that
	 * interrupts are already disabled)
	 */
	if (IS_ENABLED(CONFIG_TICKLESS_IDLE) && idle
	    && ticks == K_TICKS_FOREVER) {
	if (IS_ENABLED(CONFIG_TICKLESS_KERNEL) && idle && ticks == K_TICKS_FOREVER) {
		SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
		last_load = TIMER_STOPPED;
		return;
Loading