Interface for changing power states and restricting when they are allowed.
Power management is handled both at a system level and at a peripheral driver level. The system wide API (this) allows the user to interact with the product as a whole. Additionally, each peripheral keeps track of what its state is and whether it can safely move to a new state while still maintaining any current operations. To initialize the system wide power management, cyhal_syspm_init should be called as part of the initial device startup.
At the System level, the APIs are intended to allow the application to specify exactly what is happening. It can request changes to both the MCU Power State as well as the System Wide Power State. There are three supported MCU Power States:
Additionally, there are three supported system states:
Any time a power state transition is requested a series of callbacks are invoked. This allows peripherals, or other parts of the application, to confirm they are not currently doing something that would not work in the requested power state. HAL Peripheral drivers automatically register these callbacks when they are initialized. The application also has the option to register a callback function(s) to be called on requested state transitions by callling cyhal_syspm_register_callback. If registered, the application level callbacks are invoked first. This gives the application a chance stop any peripherals, if appropriate, to ensure the power transition can actually happen. Alternatively it can directly reject the transition. Each callback registered can specify the exact set of states ( cyhal_syspm_callback_state_t ) that it should be called for. Each callback is invoked multiple times as part of the transition process as defined by cyhal_syspm_callback_mode_t.
At any point the code can lock the ability to enter deep sleep by calling cyhal_syspm_lock_deepsleep. This should be done in critical blocks that need to continue remain active. When the critical work is complete, and the lock is no longer needed, it can be released by calling cyhal_syspm_unlock_deepsleep. The lock is a counter with a max count of USHRT_MAX. It must be locked/unlocked an equal number of times before the device is actually able to enter deep sleep.
All peripherals are expected to operate in the default Active/Normal power state. Some peripherals (primarily analog) can operate in lower power states as well. These drivers will operate in all power states that the hardware supports.
When power transitions are requested each type of peripheral has a default behavior. Peripherals that can continue to operate in the requested power mode do not interfere. Peripherals that are not currently active allow the transition, but make sure they restore their state if needed for when the device comes back. Peripherals that are active and cannot continue to work in the requested power state will block the transition.
This driver provides control over multiple different types of power management and when those transitions are allowed:
Unlike most HAL drivers this does not require initializing an instance object. The APIs provided here can be called at anytime. See the snippets below for examples of how to use this driver.
The following snippet shows how to use the deep sleep locking APIs to restrict when the device can enter deep sleep. In between the lock/unlock calls any attempt to change power modes will automatically be canceled.
The following snippet shows the different functions that exist to change power states on the device and how they can each be called.
The following snippet shows how to use the callback mechanisms to manage whether it is safe to enter low power modes.
API Reference | |
SYSPM HAL Results | |
SYSPM specific return codes. | |
Data Structures | |
struct | cyhal_syspm_callback_data_t |
Power management callback data object. More... | |
Macros | |
#define | CYHAL_SYSPM_CALLBACK_STATE_ALL |
Define for enabling all system and MCU state callbacks . More... | |
Typedefs | |
typedef bool(* | cyhal_syspm_callback_t) (cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *callback_arg) |
The system wide custom action power callback type. More... | |
Functions | |
cy_rslt_t | cyhal_syspm_init (void) |
Performs any system wide power management initialization that is needed for future operations. More... | |
cy_rslt_t | cyhal_syspm_hibernate (cyhal_syspm_hibernate_source_t wakeup_source) |
Sets the system mode to hibernate. More... | |
cy_rslt_t | cyhal_syspm_set_system_state (cyhal_syspm_system_state_t state) |
Set the system-wide state of the device. More... | |
cyhal_syspm_system_state_t | cyhal_syspm_get_system_state (void) |
Gets the system-wide state of the device. More... | |
void | cyhal_syspm_register_callback (cyhal_syspm_callback_data_t *callback_data) |
Register the specified handler with the power manager to be notified of power state changes. More... | |
void | cyhal_syspm_unregister_callback (cyhal_syspm_callback_data_t *callback_data) |
Removes the registered handler from the power manager so no future notifications are made. More... | |
cy_rslt_t | cyhal_syspm_sleep (void) |
Set CPU to sleep mode. More... | |
cy_rslt_t | cyhal_syspm_deepsleep (void) |
Set CPU to deep sleep mode. More... | |
void | cyhal_syspm_lock_deepsleep (void) |
Lock deep sleep. More... | |
void | cyhal_syspm_unlock_deepsleep (void) |
Unlock deep sleep. More... | |
cy_rslt_t | cyhal_syspm_tickless_deepsleep (cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms) |
Timed deep-sleep without system timer. More... | |
cy_rslt_t | cyhal_syspm_tickless_sleep (cyhal_lptimer_t *obj, uint32_t desired_ms, uint32_t *actual_ms) |
Timed sleep without system timer. More... | |
void | cyhal_syspm_set_supply_voltage (cyhal_syspm_voltage_supply_t supply, uint32_t mvolts) |
Informs the system of the current voltage level on the specified supply. More... | |
uint32_t | cyhal_syspm_get_supply_voltage (cyhal_syspm_voltage_supply_t supply) |
Retrieves the current voltage level on the specified supply, as set in cyhal_syspm_set_supply_voltage. More... | |
struct cyhal_syspm_callback_data_t |
Data Fields | ||
---|---|---|
cyhal_syspm_callback_t | callback | Callback to run on power state change. |
cyhal_syspm_callback_state_t | states |
Power states that should trigger calling the callback. Multiple cyhal_syspm_callback_state_t values can be ored together. |
cyhal_syspm_callback_mode_t | ignore_modes |
Modes to ignore invoking the callback for. Multiple cyhal_syspm_callback_mode_t values can be ored together. |
void * | args | Argument value to provide to the callback. |
struct cyhal_syspm_callback_data * | next |
Pointer to the next callback strucure. This should be initialized to NULL. |
#define CYHAL_SYSPM_CALLBACK_STATE_ALL |
Define for enabling all system and MCU state callbacks .
typedef bool(* cyhal_syspm_callback_t) (cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void *callback_arg) |
The system wide custom action power callback type.
[in] | state | State the system or CPU is being transitioned into. |
[in] | mode | Callback mode. |
[in] | callback_arg | User argument passed as part of registering callback in cyhal_syspm_register_callback. |
Flags enum for the cpu state in a custom callback.
This is used to indicate what states a callback should be called in. When a callback is called, only one of these will be set at a time.
Enumeration of the transition modes in custom callback.
The general sequence is: CHECK_READY, BEFORE_TRANSITION, AFTER_TRANSITION. If any callback indicates that it is not able to change state as part of CHECK_READY, CHECK_FAIL will be run instead of the BEFORE/AFTER_TRANSITION.
Enumeration of the system wide power modes.
These modes are device specifc and may not be supported on all devices. Refer to the device specific documentation or the Data Sheet to determine what is allowed. Devices that do support these modes may have requirements for adjusting system settings such as clocks or voltage levels before transition.
Enumerator | |
---|---|
CYHAL_SYSPM_SYSTEM_NORMAL | Normal Mode. |
CYHAL_SYSPM_SYSTEM_LOW | Low Power Mode. |
Flags enum for the hibernate wakeup sources.
Supply voltages whose levels can be specified and queried via cyhal_syspm_set_supply_voltage and cyhal_syspm_get_supply_voltage, respectively.
Enumerator | |
---|---|
CYHAL_VOLTAGE_SUPPLY_VDDA | VDDA - Analog supply voltage. |
CYHAL_VOLTAGE_SUPPLY_MAX | Alias for the highest value in this enum. |
cy_rslt_t cyhal_syspm_init | ( | void | ) |
Performs any system wide power management initialization that is needed for future operations.
This can include things like unlocking IOs that might have been frozen when entering a low power state or registering callback functions that are necessary to allow notifications of power events. This should be called as part of initializing the device in a Board Support Package (BSP).
cy_rslt_t cyhal_syspm_hibernate | ( | cyhal_syspm_hibernate_source_t | wakeup_source | ) |
Sets the system mode to hibernate.
This function configures the sources to wake up the device from hibernate mode and then sets the system to hibernate mode.
In hibernate mode, all internal supplies are off and no internal state is retained.
Sources can be wakeup pins, LPComparators, Watchdog (WDT) interrupt, or a Real-Time clock (RTC) alarm (interrupt). Wakeup from system hibernate always results in a device reset and normal boot process.
Wakeup pins:
A wakeup is supported by pins with programmable polarity. These pins are typically connected to the GPIO pins or on-chip peripherals under some conditions. See device datasheet to check if this feature is supported and for specific pin connections. Setting the wakeup pin to this level will cause a wakeup from system hibernate mode.
LPComparators:
A wakeup is supported by LPComps with programmable polarity. Setting the LPComp to this level will cause a wakeup from system hibernate mode.
Watchdog Timer:
A wakeup is performed by a WDT interrupt.
Real-time Clock:
A wakeup is performed by the RTC alarm.
For information about hibernate behavior, wakeup sources and their assignment in specific devices, refer to the appropriate device TRM.
[in] | wakeup_source | The source to be configured as a wakeup source from the system hibernate power mode, see cyhal_syspm_hibernate_source_t. The input parameter values can be ORed. For example, if you want to enable LPComp0 (active high) and WDT, call this function: cyhal_syspm_hibernate(CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH | CYHAL_SYSPM_HIBERNATE_WDT). |
cy_rslt_t cyhal_syspm_set_system_state | ( | cyhal_syspm_system_state_t | state | ) |
Set the system-wide state of the device.
This is used to change the power state within the Active power mode. cyhal_syspm_get_system_state can be used to get the current state.
[in] | state | System wide state. |
cyhal_syspm_system_state_t cyhal_syspm_get_system_state | ( | void | ) |
Gets the system-wide state of the device.
States can be changed by calling cyhal_syspm_set_system_state.
void cyhal_syspm_register_callback | ( | cyhal_syspm_callback_data_t * | callback_data | ) |
Register the specified handler with the power manager to be notified of power state changes.
This is intended for application wide decisions. Peripherals handle their ability to perform power transitions internally. This callback will be called before any of the peripheral callbacks for CYHAL_SYSPM_CHECK_READY and CYHAL_SYSPM_BEFORE_TRANSITION. This callback will be called after all peripheral callback for CYHAL_SYSPM_CHECK_FAIL and CYHAL_SYSPM_AFTER_TRANSITION.
[in] | callback_data | The data for the callback to register |
void cyhal_syspm_unregister_callback | ( | cyhal_syspm_callback_data_t * | callback_data | ) |
Removes the registered handler from the power manager so no future notifications are made.
[in] | callback_data | The data for the callback to unregister |
cy_rslt_t cyhal_syspm_sleep | ( | void | ) |
Set CPU to sleep mode.
cy_rslt_t cyhal_syspm_deepsleep | ( | void | ) |
Set CPU to deep sleep mode.
void cyhal_syspm_lock_deepsleep | ( | void | ) |
Lock deep sleep.
This function prevents the CPU from going to deep sleep. The lock is implemented as a counter from 0 to USHRT_MAX. Each call to this function increments the counter by 1. cyhal_syspm_unlock_deepsleep must be called an equal number of times to fully unlock. Deepsleep will only be allowed when the counter is equal to 0.
void cyhal_syspm_unlock_deepsleep | ( | void | ) |
Unlock deep sleep.
This function decrements the lock counter by 1 and must be called an equal number of times as cyhal_syspm_lock_deepsleep is called to fully unlock. Deepsleep will only be allowed when the counter is equal to 0.
cy_rslt_t cyhal_syspm_tickless_deepsleep | ( | cyhal_lptimer_t * | obj, |
uint32_t | desired_ms, | ||
uint32_t * | actual_ms | ||
) |
Timed deep-sleep without system timer.
Provides a way to deep-sleep for a desired number of milliseconds(ms) with the system timer disabled. The system timer is disabled before sleeping and a low power timer is setup to wake the device from deep-sleep after the desired number of ms have elapsed.
[in] | obj | Pre-Initialized LPTimer object. |
[in] | desired_ms | Desired number of ms to deep-sleep. |
[out] | actual_ms | Actual number of ms that was spent in deep-sleep. This value can range from 0 to desired_ms - 1 depending on how long the device was able to deep-sleep. |
cy_rslt_t cyhal_syspm_tickless_sleep | ( | cyhal_lptimer_t * | obj, |
uint32_t | desired_ms, | ||
uint32_t * | actual_ms | ||
) |
Timed sleep without system timer.
Provides a way to sleep for a desired number of milliseconds(ms) with the system timer disabled. The system timer is disabled before sleeping and a low power timer is setup to wake the device from sleep after the desired number of ms have elapsed.
[in] | obj | Pre-Initialized LPTimer object. |
[in] | desired_ms | Desired number of ms to sleep. |
[out] | actual_ms | Actual number of ms that was spent in sleep. This value can range from 0 to desired_ms - 1 depending on how long the device was able to sleep. |
void cyhal_syspm_set_supply_voltage | ( | cyhal_syspm_voltage_supply_t | supply, |
uint32_t | mvolts | ||
) |
Informs the system of the current voltage level on the specified supply.
This is generally expected to be set once at system startup, but it may be set repeatedly during runtime if operating conditions change. Once set, this value can be queried via cyhal_syspm_get_supply_voltage.
supply | The supply whose voltage is being specified. |
mvolts | The voltage level on the specified supply, in millivolts. |
uint32_t cyhal_syspm_get_supply_voltage | ( | cyhal_syspm_voltage_supply_t | supply | ) |
Retrieves the current voltage level on the specified supply, as set in cyhal_syspm_set_supply_voltage.
supply | The supply whose voltage is being specified. |