Skip to content

Commit 226c6ae

Browse files
nordic-krchkartben
authored andcommitted
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 <[email protected]>
1 parent ddedff7 commit 226c6ae

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

subsys/pm/Kconfig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,26 @@ config PM_NEED_ALL_DEVICES_IDLE
5353
When this option is enabled, check that no devices are busy before
5454
entering into system low power mode.
5555

56+
choice PM_PREWAKEUP_CONV_MODE
57+
prompt "Pre-wakeup microseconds to ticks conversion method"
58+
default PM_PREWAKEUP_CONV_MODE_NEAR
59+
help
60+
Exit latency for each power state is given in microseconds. It is converted
61+
to ticks and system clock is set to wake up the core earlier before scheduled
62+
wake up. This option specifies rounding that is used when converting exit
63+
latency from microseconds to system ticks.
64+
65+
config PM_PREWAKEUP_CONV_MODE_NEAR
66+
bool "Nearest"
67+
68+
config PM_PREWAKEUP_CONV_MODE_CEIL
69+
bool "Round up"
70+
71+
config PM_PREWAKEUP_CONV_MODE_FLOOR
72+
bool "Round down"
73+
74+
endchoice
75+
5676
endif # PM
5777

5878
config PM_DEVICE

subsys/pm/pm.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ LOG_MODULE_REGISTER(pm, CONFIG_PM_LOG_LEVEL);
2626
static ATOMIC_DEFINE(z_post_ops_required, CONFIG_MP_MAX_NUM_CPUS);
2727
static sys_slist_t pm_notifiers = SYS_SLIST_STATIC_INIT(&pm_notifiers);
2828

29+
/* Convert exit-latency-us to ticks using specified method. */
30+
#define EXIT_LATENCY_US_TO_TICKS(us) \
31+
IS_ENABLED(CONFIG_PM_PREWAKEUP_CONV_MODE_NEAR) ? k_us_to_ticks_near32(us) : \
32+
IS_ENABLED(CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL) ? k_us_to_ticks_ceil32(us) : \
33+
k_us_to_ticks_floor32(us)
2934
/*
3035
* Properly initialize cpu power states. Do not make assumptions that
3136
* ACTIVE_STATE is 0
@@ -145,6 +150,7 @@ bool pm_system_suspend(int32_t kernel_ticks)
145150
uint8_t id = CPU_ID;
146151
k_spinlock_key_t key;
147152
int32_t ticks, events_ticks;
153+
uint32_t exit_latency_ticks;
148154

149155
SYS_PORT_TRACING_FUNC_ENTER(pm, system_suspend, kernel_ticks);
150156

@@ -194,16 +200,13 @@ bool pm_system_suspend(int32_t kernel_ticks)
194200
}
195201
#endif
196202

197-
if ((z_cpus_pm_state[id].exit_latency_us != 0) &&
198-
(ticks != K_TICKS_FOREVER)) {
203+
exit_latency_ticks = EXIT_LATENCY_US_TO_TICKS(z_cpus_pm_state[id].exit_latency_us);
204+
if ((exit_latency_ticks > 0) && (ticks != K_TICKS_FOREVER)) {
199205
/*
200206
* We need to set the timer to interrupt a little bit early to
201207
* accommodate the time required by the CPU to fully wake up.
202208
*/
203-
sys_clock_set_timeout(ticks -
204-
k_us_to_ticks_ceil32(
205-
z_cpus_pm_state[id].exit_latency_us),
206-
true);
209+
sys_clock_set_timeout(ticks - exit_latency_ticks, true);
207210
}
208211

209212
/*

0 commit comments

Comments
 (0)