CC3200 Power Management Framework

Table of Contents

Introduction

Optimizing device power consumption is inherently complex and can be overwhelming to application developers. For the CC3200, TI offers a ready-made, deployment agnostic and easy-to-use software component called Power Management Framework (PMF). The PMF offering is intended to assist developers who are eagerly focused on the end-solution to take the system to production and deployment in a short amount of time. To facilitate the application developer’s creation of a solution that is ready for end use, the PMF offers services in diverse aspects of the system. The following diagram captures the breadth of the feature scope of the PMF.

The concept of moving the system to the lowest possible configured power state, and then restoring the context of the system without any intervention of the application(s) is the central idea behind PMF.

The subsequent sections provide information about CC3200 power states and the services and API provided by the PMF and its supporting modules.

Power Management on the CC3200

The low power modes supported in the CC3200 subsystem are: Sleep, Deep Sleep, Low Power Deep Sleep (LPDS) and Hibernate (HIB).

The diagram below captures the key considerations that a developer needs to take in choosing the power mode suitable for a given use case.

The key points to note are:

  1. Sleep: By default, the sleep clock to the peripherals are disabled. If the application chooses to enter sleep anytime and requires certain peripherals to be active (as a source of wakeup), the sleep clock to the peripheral has to be enabled. This is an APPs processor control.

  2. Deep Sleep: It is recommended to use Deep Sleep only when using networking services. Using peripherals in conjunction with Deep Sleep is not recommended. This is an APPs processor control.

  3. Low Power Deep Sleep (LPDS):  The CPU and peripheral context needs to be restored on exit from LPDS. Only 1 out of the 6 GPIOs can be used as a wake source from LPDS. This is an APPs processor control.

  4. Hibernate (HIB): This is equivalent to a Power On Reset except for the fact that the SlowClockCOunter continues to tick and a minimal set of registers (two 32 bit registers) are retained across HIB cycles. This is a complete CC3200 subsystem control.

Power Management Framework

Design

The objective of the power management framework is to provide an easy to use infrastructure for developers to create a power aware solution. The framework abstracts the inherently complex power management by providing simple services that can be invoked by application developers.

The salient features of the PM framework are:

Software Interface

The programming interface provided by the power management framework is as described in the diagram below.

APIs can be divided into: Core APIs and User hook functions. Key points to note on the APIs are as follows:

  1. PM framework initialization APIs - Mandatory

  2. Device driver registration and control APIs - These APIs aid the peripheral power state transitions in sync with the system power state transitions.

  3. PM framework control: User applications have a choice of controlling the PM framework kicking in (enable/disable) to better control the execution flow. The APIs are reference counted.

  4. PM framework core execution API - The API has to be placed in the idle loop of the application. It attempts to enter the low power modes in the order HIB -> LPDS -> DeepSleep -> Sleep. Before entry into HIB, LPDS or DeepSleep, the user callback function can_try_pm_state is invoked to get the approval to enter a particular state.

  5. User hook functions - A reference implementation of the user hook functions are provided along with the package (middleware\soc\cc_pm_ops). These APIs can be overridden by the applications as deemed fit. The key user hook function to be implemented are:

Timer framework

Overview

Timer framework provides a software timer infrastructure built on top of 2 of the hardware resources (Slow clock counter and GeneralPurposeTimer (GPT)) available in the CC3200 device.

Real Time Clock (RTC) Infrastructure: Low precision, aids power management

Monotone Clock infrastructure: High precision

Exercising Low Power Modes

The low power modes discussed in this section are HIBernate and LowPowerDeepSleep.

Exercising low power modes involves

Backing up information

Setting up the wake sources

Entering the low power mode

Restoring the information on wakeup

The PM framework abstracts out the information mentioned above and is indirectly derived by the choices the user application. The same are described in the diagram and subsection below.

Low Power Deep Sleep

GPIO as wake source

Applications have to use the gpio_hal.c APIs for the usage of GPIOs. Notifications have to be enabled for the GPIO to be used as a wake source.

// Setting up GPIO as a wake source
tGPIOHndl = cc_gpio_open(GPIO_SRC_WKUP, GPIO_DIR_INPUT);
cc_gpio_enable_notification(tGPIOHndl, GPIO_SRC_WKUP, INT_FALLING_EDGE, (GPIO_TYPE_NORMAL | GPIO_TYPE_WAKE_SOURCE));

This selection by the application is used by the PM framework to configure the GPIO as a wake source anytime the system can enter LPDS. On wake from LPDS, the registered application callback is invoked.

RTC as wake source

Applications have to use the cc_timer.c, rtc_hal.c APIs for the usage of RTC as wake source.

The PM framework internally manages the setting up of LPDS waketimer value before entering LPDS.

// Setting up timer as a wake source

/* Setup the RTC initial value - This can be obtained from NTP too */
init_time.secs = 0;
init_time.nsec = 0;
cc_rtc_set(&init_time);

/* Create a real time timer */
realtime_timer.source = HW_REALTIME_CLK;
realtime_timer.timeout_cb = timer_intr_hndlr;
realtime_timer.cb_param = NULL;

timer_hndl = cc_timer_create(&realtime_timer);

/* Configure the timer for a periodic wakeup */
interval_time.secs = LPDS_DUR_SEC;
interval_time.nsec = LPDS_DUR_NSEC;
cc_timer_start(timer_hndl, &interval_time, OPT_TIMER_PERIODIC);

In the above sequence, after the timer is setup, the PM framework internally manages the entry into LPDS for (interval_time - WAKEUP_TIME_LPDS). Then the timer fires and the application can perform its desired action. This loop continues periodically.

Network activity as wake source

Once the sl_start API is invoked by the application (and HostIRQ enabled), thereafter anytime the APPs processor enters LPDS, the wake on network activity is always enabled. 

Hibernate

GPIO as wake source

Applications have to use the gpio_hal.c APIs for the usage of GPIOs. Notifications have to be enabled for the GPIO to be used as a wake source.

//Setting up GPIO as a wake source
tGPIOHndl = cc_gpio_open(GPIO_SRC_WKUP, GPIO_DIR_INPUT);
cc_gpio_enable_notification(tGPIOHndl, GPIO_SRC_WKUP, INT_FALLING_EDGE, (GPIO_TYPE_NORMAL | GPIO_TYPE_WAKE_SOURCE));

This selection by the application is used by the PM framework to configure the GPIO as a wake source anytime the system can enter HIB. On wakeup from HIB, the application execution resumes from the reset vector.

RTC as wake source

Applications have to use the cc_timer.c, rtc_hal.c APIs for the usage of RTC as wake source.

The PM framework internally manages the setting up of HIB SlowClockMatch value before entering HIB.

// Setting up Timer as a wake source
/* Setup the RTC initial value - This can be obtained from NTP too */
sInitTime.secs = 0;
sInitTime.nsec = 0;
cc_rtc_set(&sInitTime);

/* Create a real time timer */
sRealTimeTimer.source = HW_REALTIME_CLK;
sRealTimeTimer.timeout_cb = NULL;
sRealTimeTimer.cb_param = NULL;
tTimerHndl = cc_timer_create(&sRealTimeTimer);

/* Configure the timer for a absolute wakeup */
sIntervalTimer.secs = HIB_DUR_SEC;
sIntervalTimer.nsec = HIB_DUR_NSEC;
cc_timer_start(tTimerHndl, &sIntervalTimer, OPT_TIME_ABS_VALUE);

In the above sequence, after the timer is setup, the PM framework internally manages the entry into HIB for (sIntervalTimer - WAKEUP_TIME_HIB). On wakeup from HIB, the application execution resumes from the reset vector.

IO Parking while entering LPDS

In order to save power (to avoid any leakage currents) when the system enters LPDS, it is recommended to park the IOs appropriately. The application is expected to specify the IO parking scheme. The various options available are:

An example of IO parking scheme table is as below:

struct soc_io_park cc32xx_io_park[] = {
{PIN_01, "GPIO_10", WEAK_PULL_DOWN_STD},
{PIN_02, "GPIO_11", WEAK_PULL_DOWN_STD},
{PIN_03, "GPIO_12", WEAK_PULL_DOWN_STD},
{PIN_04, "GPIO_13", WEAK_PULL_DOWN_STD},
{PIN_05, "GPIO_14", WEAK_PULL_DOWN_STD},
{PIN_06, "GPIO_15", WEAK_PULL_DOWN_STD},
{PIN_07, "GPIO_16", WEAK_PULL_DOWN_STD},
{PIN_08, "GPIO_17", WEAK_PULL_DOWN_STD},
{PIN_15, "GPIO_22", WEAK_PULL_DOWN_STD},
{PIN_16, "GPIO_23/JTAG_TDI", WEAK_PULL_DOWN_STD},
{PIN_17, "GPIO_24/JTAG_TDO", WEAK_PULL_DOWN_STD},
{PIN_18, "GPIO_28", WEAK_PULL_DOWN_STD},
{PIN_19, "GPIO_28//JTAG_TCK", WEAK_PULL_DOWN_STD},
{PIN_20, "GPIO_29/JTAG_TMS", WEAK_PULL_DOWN_STD},
{PIN_21, "GPIO_25/SOP2", WEAK_PULL_DOWN_STD},
{PIN_45, "DCDC_FLASH_SW_P", WEAK_PULL_DOWN_STD},
{PIN_50, "GPIO_00", WEAK_PULL_DOWN_STD},
{PIN_53, "GPIO_30", WEAK_PULL_DOWN_STD},
{PIN_55, "GPIO_01", WEAK_PULL_DOWN_STD},
{PIN_57, "GPIO_02", WEAK_PULL_DOWN_STD},
{PIN_58, "GPIO_03", WEAK_PULL_DOWN_STD},
{PIN_59, "GPIO_04", WEAK_PULL_DOWN_STD},
{PIN_60, "GPIO_05", WEAK_PULL_DOWN_STD},
{PIN_61, "GPIO_06", WEAK_PULL_DOWN_STD},
{PIN_62, "GPIO_07", WEAK_PULL_DOWN_STD},
{PIN_63, "GPIO_08", WEAK_PULL_DOWN_STD},
{PIN_64, "GPIO_09", WEAK_PULL_DOWN_STD}
};

Recommendations for use of PM framework

Choice of low power mode

Some of the key considerations for the choice of the low power mode can be the following (These are generic suggestions only):

Choice of wake source

The choice of wake source is dependent on the application usecase. Summarizing the wake sources below:

  1. Sleep - Any interrupt
  2. Deepsleep - Any interrupt
  3. LowPowerDeepSleep - Waketimer (specific counter that ticks only during LPDS), Any 1 GPIO (2,4,11,13,17,24), Network activity based wakeup - HostIRQ (This is in response to an API issued by the application before entering LPDS (for ex., sl_recv()))
  4. HIBernate - SlowClockCounter (match value is set, the slow clock counter once started in PRCMCC3200MCUInit, continues to tick), Any combination of GPIOs (2,4,11,13,17,24)

Note: In case of HIBernate, the source of the wakeup cannot be determined.

Working with time of day (real time)

The time of day information can be obtained using NTP. This information can be passed to the timer framework and then can be used as the basis of having timed events based on time of day. Many usecases can be realized using this feature (alarms…).

Working with time of day requires setting up of the initial RTC time. Thereafter, the framework maintains the synchronization between the Real time and the free running SlowClockCounter.

The code could be like below:

// Setting up timer as a wake source

/* Setup the RTC initial value obtained from NTP */
init_time.secs = NTP_TIME_SECS;
init_time.nsec = NTP_TIME_NSECS;
cc_rtc_set(&init_time);

/* Create a real time timer */
realtime_timer.source = HW_REALTIME_CLK;
realtime_timer.timeout_cb = timer_intr_hndlr;
realtime_timer.cb_param = NULL;
timer_hndl = cc_timer_create(&realtime_timer);

/* Configure the timer for a periodic wakeup */
interval_time.secs = WAKEUP_SEC_TIMEOFDAY;
interval_time.nsec = WAKEUP_NSEC_TIMEOFDAY;
cc_timer_start(timer_hndl, &interval_time, OPT_TIMER_PERIODIC);

There precision of the timer is only in the order of milliseconds. The input of nanoseconds is retained to be able to pass the values obtained over NTP to the API directly.

Note:

Disabling PM framework

The APIs to control the enabling and disabling of PM framework are: cc_app_resume_pm and cc_app_putoff_pm. These APIs are reference counted and the resumption of PM framework happens accordingly.

The intervention from the PM framework can be controlled by using these APIs. An example is as below:

SELECT_LPDS_LOW_POWER_MODE();

while(FOREVER){
    /* Resume the PM framwork operations before entering the Idle wait in the application */
        cc_app_resume_pm();
        /* Enter the Wait for registered event (for ex., sl_recv) */
        WAIT_HERE();  /* --------- Application will enter LPDS here on executing IDLE loop ----*/
        /* Put off the PM framework the process the event */
        cc_app_putoff_pm();

        /* --------- Application will remain ACTIVE here ----*/
        ..... /* Processing */
}

Extending/Customizing PM framework

A reference implementation of the user hook functions have been provided in the file cc3200-sdk\middleware\soc\cc_pm_ops.c. While this may suffice for most of the implementations, the applications can choose to override this implementation by hooking an alternate function.

The default user hook registration function will be as below:

lp3p0_pm_ops->set_up_wkup_srcs = cc_set_up_wkup_srcs;
lp3p0_pm_ops->handle_S3_wakeup = cc_handle_S3_wakeup;
lp3p0_pm_ops->are_irqs_pending = cc_are_irqs_pending;
lp3p0_pm_ops->can_try_pm_state = lp3p0_can_try_pm_state;
lp3p0_pm_ops->enter_S4 = cc_enter_S4;
lp3p0_pm_ops->enter_S3 = cc_enter_S3;
lp3p0_pm_ops->enter_S2 = cc_enter_S2;
lp3p0_pm_ops->enter_S1 = cc_enter_S1;
lp3p0_pm_ops->back_up_soc_data = lp3p0_back_up_soc_data;
lp3p0_pm_ops->restore_soc_data = lp3p0_restore_soc_data;
lp3p0_pm_ops->dsbl_sys_irq = osi_EnterCritical;
lp3p0_pm_ops->enbl_sys_irq = osi_ExitCritical;

The application is expected to implement the following functions consciously:

PM framework details

LPDS entry-exit sequence

Folder structure

The folder structure of the middleware component is as below:

Core PM framework APIs

API Description
cc_pm_framework_init Initialize the power management framework
cc_pm_platform_ops_register Register the user hook functions with the PM framework
cc_modules_load Load the registered modules
cc_module_drv_register Register a new module driver with the PM framework
cc_module_drv_unregister UnRegister a module driver from the PM framework
cc_module_clk_enable x
cc_module_clk_disable x
cc_app_putoff_pm Put off the PM framework
cc_app_resume_pm Resume the PM framework

Platform Service APIs

API Description
cc_set_up_wkup_srcs Sets up wake-up sources for indicated power mode
cc_handle_S3_wakeup Process events that have woken up system from S3 (LPDS) by triggering a software interrupt
cc_are_irqs_pending Check if any interrupts are pending in the system
cc_enter_S4 Enter HIBernate
cc_enter_S3 Enter LPDS
cc_enter_S2 Enter DeepSleep
cc_enter_S1 Enter Sleep
cc_back_up_soc_data Enables the SRAM retention, Saves the NVIC registers
cc_restore_soc_data Restores the NVIC registers, Acquires the I2C and GPIO semaphore
wake_interrupt_handler Handles the Power and Reset Control Module (PRCM) wake events

Reference Implementation

Reference implementations using the power management framework is available in the SDK package. The example apps are the following:

  1. Idle profile: the CC3200 device is connected to an AP and is continuously waiting for a packet over the air (UDP Rx) to wakeup. For all the times when the application is idling, it enters LPDS. In order to showcase all wake sources, GPIO13 and timer based wakeup from LPDS is also supported. See the Idle Profile example for more detail and implementation.

  2. Sensor profile: the CC3200 device periodically wakes up from HIBernate, broadcasts a message and then enters HIBernate. The application also allows for wakeup from HIBernate based on GPIO13. See the Sensor Profile example for more detail and implementation.

Limitations and known issues

  1. This is a feature complete version of the PM framework. System tests have been performed successfully. The production version of the framework would be released after system test cycles on ES 1.33 device.
  2. ARM CM-4 Clock gating (WFI/WFE instructions) cannot be invoked if Low power deep sleep is invoked in the user application. Above restriction would be relaxed with production devices.
  3. Usage of Deepsleep while using peripherals other than GPIO is not recommended due to the variation in clock frequency during the transition to the power state.
  4. The drivers have not been tested for all possible input configurations.
  5. Power Management framework would not work with ES 1.21 devices