pm: Optimize pre-wakeup in suspend procedure
When core is suspended and power mode has non zero exit_latency_us a system timeout will be rescheduled to a point in time that is earlier by exit_latency_us than request. It is to accommodate for lengthy resuming procedure which would cause requested timeout to be significantly late. However, setting additional wake up point has cost, it is one more redundant core wake up and that impacts performance and power consumption. Add Kconfig option to chose what conversion method is used. It has the biggest impact on small exit_latency_us where conversion may result in 0 ticks (no pre-wake up) or 1 tick (wake up). Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
ddedff7155
commit
226c6ae17c
@ -53,6 +53,26 @@ config PM_NEED_ALL_DEVICES_IDLE
|
||||
When this option is enabled, check that no devices are busy before
|
||||
entering into system low power mode.
|
||||
|
||||
choice PM_PREWAKEUP_CONV_MODE
|
||||
prompt "Pre-wakeup microseconds to ticks conversion method"
|
||||
default PM_PREWAKEUP_CONV_MODE_NEAR
|
||||
help
|
||||
Exit latency for each power state is given in microseconds. It is converted
|
||||
to ticks and system clock is set to wake up the core earlier before scheduled
|
||||
wake up. This option specifies rounding that is used when converting exit
|
||||
latency from microseconds to system ticks.
|
||||
|
||||
config PM_PREWAKEUP_CONV_MODE_NEAR
|
||||
bool "Nearest"
|
||||
|
||||
config PM_PREWAKEUP_CONV_MODE_CEIL
|
||||
bool "Round up"
|
||||
|
||||
config PM_PREWAKEUP_CONV_MODE_FLOOR
|
||||
bool "Round down"
|
||||
|
||||
endchoice
|
||||
|
||||
endif # PM
|
||||
|
||||
config PM_DEVICE
|
||||
|
||||
@ -26,6 +26,11 @@ LOG_MODULE_REGISTER(pm, CONFIG_PM_LOG_LEVEL);
|
||||
static ATOMIC_DEFINE(z_post_ops_required, CONFIG_MP_MAX_NUM_CPUS);
|
||||
static sys_slist_t pm_notifiers = SYS_SLIST_STATIC_INIT(&pm_notifiers);
|
||||
|
||||
/* Convert exit-latency-us to ticks using specified method. */
|
||||
#define EXIT_LATENCY_US_TO_TICKS(us) \
|
||||
IS_ENABLED(CONFIG_PM_PREWAKEUP_CONV_MODE_NEAR) ? k_us_to_ticks_near32(us) : \
|
||||
IS_ENABLED(CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL) ? k_us_to_ticks_ceil32(us) : \
|
||||
k_us_to_ticks_floor32(us)
|
||||
/*
|
||||
* Properly initialize cpu power states. Do not make assumptions that
|
||||
* ACTIVE_STATE is 0
|
||||
@ -145,6 +150,7 @@ bool pm_system_suspend(int32_t kernel_ticks)
|
||||
uint8_t id = CPU_ID;
|
||||
k_spinlock_key_t key;
|
||||
int32_t ticks, events_ticks;
|
||||
uint32_t exit_latency_ticks;
|
||||
|
||||
SYS_PORT_TRACING_FUNC_ENTER(pm, system_suspend, kernel_ticks);
|
||||
|
||||
@ -194,16 +200,13 @@ bool pm_system_suspend(int32_t kernel_ticks)
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((z_cpus_pm_state[id].exit_latency_us != 0) &&
|
||||
(ticks != K_TICKS_FOREVER)) {
|
||||
exit_latency_ticks = EXIT_LATENCY_US_TO_TICKS(z_cpus_pm_state[id].exit_latency_us);
|
||||
if ((exit_latency_ticks > 0) && (ticks != K_TICKS_FOREVER)) {
|
||||
/*
|
||||
* We need to set the timer to interrupt a little bit early to
|
||||
* accommodate the time required by the CPU to fully wake up.
|
||||
*/
|
||||
sys_clock_set_timeout(ticks -
|
||||
k_us_to_ticks_ceil32(
|
||||
z_cpus_pm_state[id].exit_latency_us),
|
||||
true);
|
||||
sys_clock_set_timeout(ticks - exit_latency_ticks, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user