Usage Guide
Quick Start
Three steps to have an application enter PG (power gating) and be woken by the RTC.
1. Enable the Kconfig options
CONFIG_PM=y
# The idle thread stack has to be enlarged, or the sleep path overflows it
CONFIG_IDLE_STACK_SIZE=4096
# The wake-up source device itself must be enabled too
CONFIG_RTC=y
CONFIG_RTC_ALARM=y
CONFIG_RTC_AMEBA=y
2. Mark the device as a wake-up source in an overlay
&rtc {
status = "okay";
wakeup-source;
};
3. Configure the device in the application
The PM framework only enables a device’s wake-up capability; the device itself still has to be initialised and configured as usual, such as setting an RTC alarm or configuring a GPIO interrupt.
The application does not request sleep explicitly. The default
Residency Based policy selects a state whenever the idle time is long
enough; for how that is decided see Selecting a Power State. APPG
followed by APPW in the serial log means one PG sleep and wake completed;
for the markers see Reading the Log.
Note
Zephyr takes over arming the AP wake-up sources only when it is booted by a
Zephyr-side bootloader (MCUboot, or TF-M BL2 in the //ns split
configuration). Under ameba-loader the KM0 firmware arms them and the DTS
properties above have no effect.
Configuration Details
Kconfig for other wake-up sources
# timer (counter) as a wake-up source
CONFIG_COUNTER=y
# GPIO as a wake-up source
CONFIG_GPIO=y
DTS for other wake-up sources
&gpiob {
status = "okay";
wakeup-source;
};
&timer0 {
status = "okay";
wakeup-source;
};
The node also needs a wakeup-source-id property, the hardware event ID of
that wake-up source. It is normally already given in the SoC’s dtsi.
Note
A node with wakeup-source but no wakeup-source-id is not enabled as
a wake-up source, and nothing reports it.
Warning
The ameba counter driver supports relative alarms only. Setting
COUNTER_ALARM_CFG_ABSOLUTE returns -ENOTSUP and the alarm is never
armed, which presents as a device that never wakes and reports nothing.
Warning
counter_cancel_channel_alarm() does not stop the counter. Per the Zephyr
counter API, counter_start() asks for free running and cancelling an
alarm does not undo it; a node marked wakeup-source is armed in the PMC
at boot, and whether the PMC wakes the AP is independent of whether the
peripheral’s own interrupt is masked.
Call counter_stop() explicitly once the wake-up source is no longer
needed; for the RTC, disable the alarm by calling rtc_alarm_set_time()
with mask = 0. Otherwise the leftover source keeps producing wake
events, which presents as later sleep requests not entering PG.
Selecting a Power State
The Residency Based policy is used by default: the framework compares the
expected idle time against each state’s min-residency-us + exit-latency-us
and picks the deepest state that fits, so the application never requests a
state itself. See
Introduction
.
The expected idle time comes from the kernel and equals the time until the
next registered timeout expires (z_get_next_timeout_expiry()). It is not
directly configurable; what the application controls is its own behaviour, the
duration of its k_msleep() calls, its timer periods, and whether threads
wake frequently.
The thresholds are declared per SoC in the dtsi as power-states nodes.
The current defaults:
State |
|
|
|
|---|---|---|---|
CG |
|
3000 |
2000 |
PG |
|
5000 |
2500 |
So an idle time of 5 ms is needed before PG is chosen, between 3 ms and 5 ms CG
is chosen, and below 3 ms only WFI runs. The defaults are the same on all
three SoCs. The board dts declares which states are available to the CPU
through cpu-power-states, currently <&pm_cg &pm_pg>.
An application may override these in an overlay, for instance to lower the PG threshold:
&pm_pg {
min-residency-us = <2000>;
};
Note
exit-latency-us describes the hardware wake-up cost and should match
what the hardware actually takes; lowering it makes the framework choose the
state when the idle time does not justify it, so the wake-up cost dominates.
Adjusting the threshold normally means changing min-residency-us alone.
To restrict the available states temporarily, for example to forbid PG, use
Zephyr’s pm_policy_state_lock_get() / pm_policy_state_lock_put().
Per-SoC Support
CG (PM_STATE_SUSPEND_TO_IDLE) and PG (PM_STATE_SUSPEND_TO_RAM)
are supported.
Boot paths: MCUboot, the //ns split configuration (TF-M BL2), and
ameba-loader.
In the //ns configuration the secure world is carried across a PG, so
secure session state such as a volatile key stays valid after the wake.
CG and PG are supported.
Boot paths: MCUboot, the //ns split configuration (TF-M BL2), and
ameba-loader.
In the //ns configuration the secure world is carried across a PG, as
on RTL8721F.
PG (PM_STATE_SUSPEND_TO_RAM) is supported, on both the uniprocessor
and SMP builds; under SMP the whole cluster is powered down.
CG is not supported: forcing it makes the NP take a SecureFault.
There is no //ns split configuration. Under SMP one sleep may be
recorded as several enter/exit pairs: CPU0 has to wait for CPU1 to stop
and abandons the attempt until then, the idle loop retrying.
Running the PM Tests
zephyr/tests/boards/realtek/pm covers the system timebase, waking on a
kernel timeout, several wake-up sources under both CG and PG, and repeated PG.
west twister -p rtl8721f_evb/rtl8721f/ns -T zephyr/tests/boards/realtek/pm
Supported targets:
rtl8721f_evb/rtl8721f/mcuboot
rtl8721f_evb/rtl8721f/ns
rtl872xda_evb/rtl8721dx/mcuboot
rtl872xda_evb/rtl8721dx/ns
rtl8730e_evb/rtl8730e
Note
The ameba-loader variants are not among them: there the KM0 firmware arms
the wake-up sources, the test cannot arm them itself, and the AP would stay
powered down. For that scenario see
applications/amebaloder_pm_system_manage.
For a ready-to-run sample rather than a test suite, see
applications/mcuboot_pm_system_manage, woken in turn by the RTC, a counter
and a GPIO.
Reading the Log
A complete PG sleep and wake looks like this:
<inf> soc_pm: call pm_state_set: 4
APPG
NPPG
NPPW
APPW
<inf> soc_pm: [pm_state_exit_post_ops] AP wake: 4
Wake up by: rtc@4080aa00.
What each marker means:
Marker |
Meaning |
|---|---|
|
Entering state N ( |
|
AP entered PG / CG |
|
NP entered PG / CG |
|
NP woke |
|
AP woke |
|
Post-wake processing finished |
The AP entering without the NP following (APPG with no NPPG) means the
NP was not ready, and the AP leaves this sleep.
Troubleshooting
Symptom |
Where to look |
|---|---|
No |
The policy selected no state. Either the idle time is below
|
|
The NP was not ready and the AP left this sleep |
Sleeps but never wakes |
The wake-up source was never armed. Check that the node has both
|
Uptime does not advance after a wake |
Time compensation relies on the always-on application takes it over as a counter device and stops or resets it, the compensation is lost |