System Power Management

group group_hal_syspm

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:

  • Active - This is the normal operating state of the MCU

  • Sleep - In this state the MCU is no longer running. It can be woken up again from an interrupt. This state is reached by calling cyhal_syspm_sleep.

  • Deep Sleep - In this state the MCU is no longer running. It can only be woken up by select interrupts. This state is reached by calling cyhal_syspm_deepsleep.

Additionally, there are three supported system states:

  • Normal (CYHAL_SYSPM_SYSTEM_NORMAL) - This is a normal operating state for the device. This is exposed by cyhal_syspm_set_system_state.

  • Low (CYHAL_SYSPM_SYSTEM_LOW) - This is a lower power operating state that may be supported by the device. This state often imposes specific requirements on clock speeds and voltage levels. See the device specific documentation for any device specific requirements for this mode, or whether it is even supported. If the device supports this mode, it is exposed by cyhal_syspm_set_system_state.

  • Hibernate - This is the lowest available power state. In this state most of the chip is powered down. It has a very limited number of wakeup sources, and may require the device to reboot in order to come back up. It can be accessed by calling cyhal_syspm_hibernate.

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.

note

The power management functionality available depends on the availability of the features in the hardware. For detailed information about exactly what is supported on each device, refer to the Device Datasheet or Technical Reference Manual (TRM).

Features

This driver provides control over multiple different types of power management and when those transitions are allowed:

  • Change CPU Power State: APIs to allow changing the current CPU state into one of the lower power CPU states (SLEEP, DEEPSLEEP)

  • Change System Power State: An API allows for changing the system wide power state between one of states (NORMAL, LOW)

  • Hibernate: An API that allows to set the hibernate wakeup source and set the system state to Hibernate.

  • General Purpose Power State Transition Callback: APIs allow for registering/unregistering a callback function to be notified when various power state transitions happen. If registered, the application can do anything necessary at power transitions. It can even prevent the transition if need-be.

  • Peripheral Specific Power State Transition Callback: APIs allow for registering/unregistering a callback function to be called when a peripheral with a CUSTOM power mode strategy exists and a power mode transition is requested. This allows the application to customize when it is OK for the peripheral to enter a low power state.

  • Lock DeepSleep: APIs to prevent/allow the CPU from going to deep sleep. This is a convenience API rather than needing to implement a full Transition Callback handler.

Quick Start

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.

Code Snippets

Snippet 1: Simple deep sleep locking

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.

    cyhal_syspm_lock_deepsleep();

    // Perform work that should not be interrupted by deepsleep

    cyhal_syspm_unlock_deepsleep();

Snippet 2: Calling different power state functions

The following snippet shows the different functions that exist to change power states on the device and how they can each be called.

    cy_rslt_t rslt;

    // Put the MCU to sleep. Peripherals will continue to operate.
    rslt = cyhal_syspm_sleep();

    // Put the MCU to deep-sleep. Many peripherals will also stop.
    rslt = cyhal_syspm_deepsleep();

    // Put the system into a hibernate state. Most of the system will stop.
    rslt = cyhal_syspm_hibernate(CYHAL_SYSPM_HIBERNATE_WDT);

    // Put the system into a low power state. Peripherals will continue to work, but some may have
    // restrictions on operating clock frequency or voltages.
    rslt = cyhal_syspm_set_system_state(CYHAL_SYSPM_SYSTEM_LOW);

Snippet 3: Using callbacks for application power management

The following snippet shows how to use the callback mechanisms to manage whether it is safe to enter low power modes.

bool syspm_app_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode,
                        void* callback_arg)
{
    (void)callback_arg;
    bool allow_transition = true;

    switch (mode)
    {
        case CYHAL_SYSPM_CHECK_READY:
            // Check to see if it is OK to change power modes.
            // If it is OK the change, make sure nothing will invalidate this and return true.
            // If it is not OK the change, return false.

            // Example: prevent transition if requested mode is HIBERNATE.
            allow_transition = (state != CYHAL_SYSPM_CB_SYSTEM_HIBERNATE);
            break;

        case CYHAL_SYSPM_CHECK_FAIL:
            // Undo anything done as part of CHECK_READY since it is not actually chaning.
            break;

        case CYHAL_SYSPM_BEFORE_TRANSITION:
            // Do anything necessary to shut things down.
            break;

        case CYHAL_SYSPM_AFTER_TRANSITION:
            // Undo anything done as part of CHECK_READY or BEFORE_TRANSITION since it is coming
            // back up.
            break;
    }

    return allow_transition;
}


void snippet_cyhal_syspm_app_callback(void)
{
    cy_rslt_t                   rslt;
    cyhal_syspm_callback_data_t callback_data =
    {
        .callback = syspm_app_callback,
        .states   =
            (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_SYSTEM_HIBERNATE |
                                           CYHAL_SYSPM_CB_SYSTEM_LOW),
        .args     = NULL,
        .next     = NULL,
    };

    cyhal_syspm_register_callback(&callback_data);

    // Attempt to hibernate. This will be rejected by the callback.
    rslt = cyhal_syspm_hibernate(CYHAL_SYSPM_HIBERNATE_RTC_ALARM);
    if (CY_RSLT_SUCCESS != rslt)
    {
        // If couldn't go to hibernate, try deep sleep.
        rslt = cyhal_syspm_deepsleep();
    }

    cyhal_syspm_unregister_callback(&callback_data);
}

Defines

CYHAL_SYSPM_CALLBACK_STATE_ALL

Define for enabling all system and MCU state callbacks .

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.

Return

If mode is CYHAL_SYSPM_CHECK_READY, then this indicates whether the low power mode should be allowed (true) or not (false). Otherwise the return value is ignored.

Parameters
  • [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.

Enums

enum cyhal_syspm_callback_state_t

cyhal_syspm_callback_state_t: 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.

Values:

enumerator CYHAL_SYSPM_CB_CPU_SLEEP

Flag for MCU sleep callback.

enumerator CYHAL_SYSPM_CB_CPU_DEEPSLEEP

Flag for MCU deep sleep callback.

enumerator CYHAL_SYSPM_CB_SYSTEM_HIBERNATE

Flag for Hibernate callback.

enumerator CYHAL_SYSPM_CB_SYSTEM_NORMAL

Flag for Normal mode callback.

enumerator CYHAL_SYSPM_CB_SYSTEM_LOW

Flag for Low power mode callback.

enum cyhal_syspm_callback_mode_t

cyhal_syspm_callback_mode_t: 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.

Values:

enumerator CYHAL_SYSPM_CHECK_READY

Callbacks with this mode are executed before entering into the low power mode.

The purpose of this transition state is to check if the device is ready to enter the low power mode. The application must not perform any actions that would prevent transition after returning true for this mode.

enumerator CYHAL_SYSPM_CHECK_FAIL

Callbacks with this mode are only executed if the callback returned true for CYHAL_SYSPM_CHECK_READY and a later callback returns false for CYHAL_SYSPM_CHECK_READY.

This mode should roll back any changes made to avoid blocking transition made in CYHAL_SYSPM_CHECK_READY mode

enumerator CYHAL_SYSPM_BEFORE_TRANSITION

Callbacks with this mode are executed after the CYHAL_SYSPM_CHECK_READY callbacks’ execution returns true.

In this mode, the application must perform the actions to be done before entering into the low power mode.

enumerator CYHAL_SYSPM_AFTER_TRANSITION

In this mode, the application must perform the actions to be done after exiting the low power mode.

enum cyhal_syspm_system_state_t

cyhal_syspm_system_state_t: 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.

Values:

enumerator CYHAL_SYSPM_SYSTEM_NORMAL

Normal Mode.

enumerator CYHAL_SYSPM_SYSTEM_LOW

Low Power Mode.

enum cyhal_syspm_hibernate_source_t

cyhal_syspm_hibernate_source_t: Flags enum for the hibernate wakeup sources.

note

Not all wakeup sources are valid on devices. Refer to the datasheet for device specifics.

Values:

enumerator CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW

Wake on a low logic level for the LPComp0.

enumerator CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH

Wake on a high logic level for the LPComp0.

enumerator CYHAL_SYSPM_HIBERNATE_LPCOMP1_LOW

Wake on a low logic level for the LPComp1.

enumerator CYHAL_SYSPM_HIBERNATE_LPCOMP1_HIGH

Wake on a high logic level for the LPComp1.

enumerator CYHAL_SYSPM_HIBERNATE_RTC_ALARM

Configure the RTC alarm as wakeup source.

enumerator CYHAL_SYSPM_HIBERNATE_WDT

Configure the WDT interrupt as wakeup source.

enumerator CYHAL_SYSPM_HIBERNATE_PINA_LOW

Configure a low logic level for the first wakeup-pin.

See device datasheet for specific pin.

enumerator CYHAL_SYSPM_HIBERNATE_PINA_HIGH

Configure a high logic level for the first wakeup-pin.

See device datasheet for specific pin.

enumerator CYHAL_SYSPM_HIBERNATE_PINB_LOW

Configure a low logic level for the second wakeup-pin.

See device datasheet for specific pin.

enumerator CYHAL_SYSPM_HIBERNATE_PINB_HIGH

Configure a high logic level for the second wakeup-pin.

See device datasheet for specific pin.

enum cyhal_syspm_voltage_supply_t

cyhal_syspm_voltage_supply_t: Supply voltages whose levels can be specified and queried via cyhal_syspm_set_supply_voltage and cyhal_syspm_get_supply_voltage, respectively.

note

Not all supplies which are present are included here. This enum only contains the voltage supplies whose values are relevant to the operation of one or more HAL drivers.

Values:

enumerator CYHAL_VOLTAGE_SUPPLY_VDDA

VDDA - Analog supply voltage.

enumerator CYHAL_VOLTAGE_SUPPLY_MAX

Alias for the highest value in this enum.

Functions

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).

Return

Returns CY_RSLT_SUCCESS if the processor successfully entered the hibernate mode, otherwise error.

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.

warning

Do not call this function with different polarity levels for the same wakeup source. For example, do not call a function like this: cyhal_syspm_hibernate(CYHAL_SYSPM_HIBERNATE_LPCOMP0_LOW | CYHAL_SYSPM_HIBERNATE_LPCOMP0_HIGH);

Return

Returns CY_RSLT_SUCCESS if the processor successfully entered the hibernate mode, otherwise error.

Parameters
  • [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.

note

Not all devices support different states within the Active power mode. If the device does not support changing state, an error will be returned.

Return

Returns CY_RSLT_SUCCESS if the processor successfully entered the requested system state, otherwise error.

Parameters
  • [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.

note

Not all devices support different states within the Active power mode. If the device does not support changing state, this will return CYHAL_SYSPM_SYSTEM_NORMAL.

Return

Returns the current system-wide power state of the device.

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.

note

The callback will be executed from a critical section

Parameters
  • [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.

  • Parameters
    • [in] callback_data: The data for the callback to unregister

cy_rslt_t cyhal_syspm_sleep(void)

Set CPU to sleep mode.

Return

Returns CY_RSLT_SUCCESS if the processor successfully entered the sleep mode , otherwise error.

cy_rslt_t cyhal_syspm_deepsleep(void)

Set CPU to deep sleep mode.

Return

Returns CY_RSLT_SUCCESS if the processor successfully entered the deep sleep mode, otherwise error.

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.

note

The actual ms in the best case will be 1 ms less than the desired time to prevent the device from over-sleeping due to low clock accuracy.

Return

The status of the deep-sleep request.

Parameters
  • [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.

note

The actual ms in the best case will be 1 ms less than the desired time to prevent the device from over-sleeping due to low clock accuracy.

Return

The status of the sleep request.

Parameters
  • [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.

note

This only informs the system of the voltage level. It does not alter any of the device operating conditions.

Parameters
  • 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.

note

This only returns the value provided to cyhal_syspm_set_supply_voltage. It does not perform any measurements of the current supply level.

Return

The voltage level on the specified supply, in millivolts. If the voltage has not been specified, returns 0.

Parameters
  • supply: The supply whose voltage is being specified.

struct cyhal_syspm_callback_data_t
#include <cyhal_general_types.h>

Power management callback data object.

This is used to register a new callback handler for power management transitions. The specific power states to register for can be specified as well as any modes

Public Members

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.