Architecture
Linux System Sleep Framework
In order to reduce system power consumption, Linux provides a comprehensive power management framework. The power management system is a relatively extensive subsystem that covers aspects such as power supply, clocks, frequencies, voltages, and system sleep. Among these, system sleep acts as a crucial role in the overall power consumption of the system and is the primary focus of this chapter.
The architecture of the Linux system sleep framework is illustrated in following figure.
Linux system sleep framework
The user space can access the PM (Power Management) core through the sysfs layer to control entry into and exit from system sleep. The PM core also provides Kernel APIs for the Kernel space. The suspend core is the main component of the PM core. Since system sleep involves various aspects of the system, the suspend core may invoke other sub-frameworks, such as the interrupt subsystem. The PM core ultimately relies on architecture dependent drivers related to system sleep, including the drivers for the power management controller (PMC) and peripheral devices. The PMC requires the involvement of asymmetric multi-processors.
This chip is an asymmetric multi-processors architecture, which includes CA32, KM4, and KM0. These cores can collaborate with each other to achieve lower power consumption. Inter-core communication is achieved through IPC (Inter-Process Communication). The PMC coordinates the involvement of multiple-cores in control.
Multi-processors architecture
Another advantage of using an asymmetric multi-processors architecture is that simple functions can be developed on the small core, allowing for low power consumption while providing the required functionality for users.
Sleep Mode
Because of the multi-processors architecture, system power consumption can be very low. At the same time, it provides more options for sleep states. Currently, it supports the following sleep modes.
Sleep mode |
Label |
Description |
---|---|---|
Active |
_ |
|
Standby |
mem |
|
CG |
cg |
|
Users can control sleep modes through the sysfs interfaces. The “Label” indicates the value to be written to the relevant sysfs node when entering a specific sleep mode.
Standby mode affects only CA32 itself and does not impact the states of KM0 and KM4. CG (clock gating) mode has a deeper sleep level and consumes much lower power than standby mode. CG mode affects all cores and DRAM states. When controlling CA32 to enter CG mode, CA32 will notify KM0 and KM4 through IPC to also enter CG mode. If KM4 and CA32 are in CG mode, DRAM will also enter low-power state. DRAM low power state means, if DRAM is DDR memory, it will enter self-refresh mode, which means it will maintain all memory but can’t not be accessed. That state needs much lower power.
备注
PG (power gating) mode is in development. It will consume lower power than CG mode.
Power consumption: PG < CG < standby.
Time consumed during sleep/wakeup: PG > CG > standby.
Usage
Wakeup Source Configuration
Introduction
The peripherals listed below can be configured as wakeup sources now, and these peripherals’ interrupts can wake up the system.
The mapping between peripherals and wakeup sources is listed in the following table.
Peripheral |
Wakeup source |
---|---|
GPIOA |
WAKE_SRC_GPIOA |
GPIOB |
WAKE_SRC_GPIOB |
GPIOC |
WAKE_SRC_GPIOC |
TIMER1 |
WAKE_SRC_Timer1 |
TIMER2 |
WAKE_SRC_Timer2 |
TIMER3 |
WAKE_SRC_Timer3 |
TIMER4 |
WAKE_SRC_Timer4 |
TIMER5 |
WAKE_SRC_Timer5 |
TIMER7 |
WAKE_SRC_Timer7 |
RTC |
WAKE_SRC_RTC |
ADC |
WAKE_SRC_ADC |
CAPTOUCH |
WAKE_SRC_CTOUCH |
UART0 |
WAKE_SRC_UART0 |
UART1 |
WAKE_SRC_UART1 |
UART2 |
WAKE_SRC_UART2 |
LOGUART |
WAKE_SRC_UART_LOG |
备注
For LOGUART, it is normal for logs to be garbled during sleep and wakeup.
General Configuration
Follow the steps below to configure a wakeup source, taking ADC as an example:
Modify the structure
sleep_wevent_config
for sleep settings in the configuration filefirmware/component/usrcfg/rtl8730e/ameba_sleepcfg.c
./*wakeup attribute can be set to WAKEUP_NULL/WAKEUP_LP/WAKEUP_NP/WAKEUP_AP*/ WakeEvent_TypeDef sleep_wevent_config[] = { // Module wakeup {WAKE_SRC_nFIQOUT1_OR_nIRQOUT1, WAKEUP_NULL}, {WAKE_SRC_nFIQOUT0_OR_nIRQOUT0, WAKEUP_NULL}, {WAKE_SRC_BT_WAKE_HOST, WAKEUP_NULL}, {WAKE_SRC_AON_WAKEPIN, WAKEUP_LP}, {WAKE_SRC_WDG4, WAKEUP_NULL}, {WAKE_SRC_WDG3, WAKEUP_NULL}, {WAKE_SRC_WDG2, WAKEUP_NULL}, {WAKE_SRC_WDG1, WAKEUP_NULL}, {WAKE_SRC_UART2, WAKEUP_NULL}, {WAKE_SRC_UART1, WAKEUP_NULL}, {WAKE_SRC_UART0, WAKEUP_NULL}, {WAKE_SRC_SPI1, WAKEUP_NULL}, {WAKE_SRC_SPI0, WAKEUP_NULL}, {WAKE_SRC_USB_OTG, WAKEUP_NULL}, {WAKE_SRC_IPC_AP, WAKEUP_AP}, {WAKE_SRC_IPC_NP, WAKEUP_NP}, {WAKE_SRC_VADBT_OR_VADPC, WAKEUP_NULL}, {WAKE_SRC_PWR_DOWN, WAKEUP_LP}, {WAKE_SRC_BOR, WAKEUP_NULL}, {WAKE_SRC_ADC_COMP, WAKEUP_NULL}, {WAKE_SRC_ADC, WAKEUP_NULL}, {WAKE_SRC_CTOUCH, WAKEUP_NULL}, {WAKE_SRC_RTC, WAKEUP_NULL}, {WAKE_SRC_GPIOC, WAKEUP_NULL}, {WAKE_SRC_GPIOB, WAKEUP_NULL}, {WAKE_SRC_GPIOA, WAKEUP_NULL}, {WAKE_SRC_UART_LOG, WAKEUP_NULL}, {WAKE_SRC_Timer7, WAKEUP_NULL}, {WAKE_SRC_Timer6, WAKEUP_NP}, {WAKE_SRC_Timer5, WAKEUP_NULL}, {WAKE_SRC_Timer4, WAKEUP_NULL}, {WAKE_SRC_Timer3, WAKEUP_NULL}, {WAKE_SRC_Timer2, WAKEUP_NULL}, {WAKE_SRC_Timer1, WAKEUP_NULL}, {WAKE_SRC_Timer0, WAKEUP_NULL}, {WAKE_SRC_WDG0, WAKEUP_NULL}, {WAKE_SRC_AP_WAKE, WAKEUP_NULL}, {WAKE_SRC_NP_WAKE, WAKEUP_NULL}, {WAKE_SRC_AON_TIM, WAKEUP_NULL}, {WAKE_SRC_WIFI_FTSR_MAILBOX, WAKEUP_LP}, {WAKE_SRC_WIFI_FISR_FESR, WAKEUP_LP}, {0xFFFFFFFF, WAKEUP_NULL}, };
Set
WAKE_SRC_ADC
toWAKEUP_AP
to tell the system to consider ADC interrupt as a wakeup event.{WAKE_SRC_ADC, WAKEUP_AP},
When ADC interrupt occurs, it will wake the system.
Recompile and download the firmware to apply the new settings.
Once the firmware with the updated sleep configuration is programmed into the device and the system enters sleep mode, if there is an ADC interrupt (e.g., due to some predefined conditions according to users’ needs), it will trigger the system to wake up from sleep.
Special Configuration
Some peripherals have an additional configuration in addition to the general configuration.
OSC4M
ADC, CAPTOUCH, UART, LOGUART need OSC4M to drive itself when in sleep mode. Users should configure keep_OSC4M_on
to TRUE in the structure ps_config
in firmware/component/usrcfg/rtl8730e/ameba_sleepcfg.c
to enable OSC4M.
PSCFG_TypeDef ps_config = {
.km0_tickles_debug = TRUE, /* if open Wi-Fi FW, should close it, or beacon will lost in WOWLAN */
.km0_pg_enable = FALSE,
.km0_pll_off = TRUE,
.km0_audio_vad_on = FALSE,
#if defined(CONFIG_CLINTWOOD ) && CONFIG_CLINTWOOD
.km0_config_psram = FALSE, /* if device enters sleep mode or not, false for keep active */
.km0_sleep_withM4 = FALSE,
#else
.km0_config_psram = TRUE, /* if device enters sleep mode or not, false for keep active */
.km0_sleep_withM4 = TRUE,
#endif
.keep_OSC4M_on = TRUE,
.xtal_mode_in_sleep = XTAL_OFF,
.swr_mode_in_sleep = SWR_PFM,
};
User Space Development
Users can configure sleep mode through sysfs. The commonly used files related to sleep in sysfs are listed in following table.
File |
Description |
---|---|
/sys/power/state |
Enter sleep mode at a certain level unconditionally |
/sys/power/wakeup_count |
Synchronization mechanism for wakeup events in user space and kernel space |
/sys/power/autosleep |
Opportunistic sleep, automatically enter a certain level of sleep mode when there is no wakelock |
/sys/power/wake_lock |
Writing a value to this file will add a wakelock, and the presence of a wakelock will prevent autosleep |
/sys/power/wake_unlock |
Writing a value to this file will clear a wakelock |
Unconditional Sleep
To enter sleep mode unconditionally, use the following command:
echo label > /sys/power/state
The value of label can be mem
or cg
, representing Standby mode and CG mode respectively.
Wakeup Count
Sometimes the system should not enter sleep mode unconditionally because a wakeup event may occur at this time; otherwise, the wakeup event may lose. Therefore, Linux provides Wakeup Count, a synchronization mechanism between user space and kernel space for sleep and wake events.
Its typical usage process is as follows:
Read the value of
wakeup_count
If the read is successful, write the read value back to
wakeup_count
; otherwise, continue readingIf the write is successful, it indicates that the kernel allows sleep; otherwise, repeat the above process
Enter sleep mode
Refer to <test>/pm_wakeup_count
for more information.
Autosleep and Wakelock
Autosleep, also known as opportunistic sleep, means being ready to enter sleep mode at any time. The wakelock can prevent the system from entering sleep mode. There can be multiple wakelocks, and currently the kernel limits the number of wakelocks to 100.
Write the required value to
/sys/power/wake_lock
will create a wakelock:echo wakelock1 > /sys/power/wake_lock
Write the required value to
/sys/power/wake_unlock
will release the wakelock:echo wakelock1 > /sys/power/wake_unlock
Check all wakelocks:
cat /sys/power/wake_lock
Enable autosleep, and when
/sys/power/wake_lock
is empty, the system will enter sleep mode automatically:echo label > /sys/power/autosleep
The value of label can be
mem
andcg
like unconditional sleep (/sys/power/state
).Disable autosleep:
echo off > /sys/power/autosleep
Refer to <test>/pm_wakelock
for more information.
备注
The wakelock can only prevent autosleep (/sys/power/autosleep
), not unconditional sleep (/sys/power/state
).
Kernel APIs
Interface |
Description |
---|---|
pm_stay_awake |
Notify the kernel that it is processing wakeup events, preventing the kernel from entering sleep mode |
pm_relax |
Wakeup event processing completed |
pm_wakeup_event |
Notify the kernel that the wakeup event will be processed within the specified time |
Paired use of pm_stay_awake
and pm_relax
in the kernel can control whether to enter sleep mode or not.
Application Development on KM0
Due to the high power consumption of CA32 and DRAM, users can develop some simple applications on KM0, allowing CA32 and DRAM to enter low-power mode, which can achieve good power-saving effects.
备注
KM0 runs the FreeRTOS operating system.
By default, when both CA32 and KM4 are in CG mode, KM0 will also automatically enter CG mode. Similar to Linux, KM0 also provides a wakelock mechanism to restrict KM0 from entering sleep mode. Therefore, users can set a wakelock on KM0 and then enter CG on the Linux side, so that CA32, KM4, and DRAM will enter low-power mode, while KM0 and SRAM can continue to run.
KM0 has predefined some wakelocks located in firmware/source/component/soc/amebasmart/misc/ameba_pmu.h
. Users can also add new wakelocks.
typedef enum {
PMU_OS = 0,
PMU_WLAN_DEVICE = 1,
PMU_KM4_RUN = 2,
PMU_AP_RUN = 3,
PMU_BT_DEVICE = 4,
PMU_VAD_DEVICE = 5,
PMU_DEV_USER_BASE = 6, /*number 6 ~ 31 is reserved for customer use*/
PMU_MAX,
} PMU_DEVICE;
If users want to use UART0 to transmit data on KM0 and do not want KM0 to enter sleep mode, the following code should be added to the application to acquire the wakelock.
pmu_acquire_wakelock(PMU_UART0_DEVICE);
The method to release the wakelock is
pmu_release_wakelock(PMU_UART0_DEVICE);
If all wakelocks are released, KM0 will enter sleep mode.