
.. _sec-freertos-power-management:

Power Management
----------------

All power-management functionality is handled by the TI power driver and
are used by the peripheral drivers (e.g. UART, SPI, I2C, etc..). Applications
can prevent, if they choose, the |DEVICE| from entering low power modes by
setting a power constraint.

By default, all the examples in |SDK| will put the |DEVICE| in standby mode if 
there is no task running. This is achieved by configuring the TI power driver and the kernel
to do so, as shown in the following step.

#. In the ``FreeRTOSConfig.h``, set following define:

   .. code-block:: c
      :caption: ``FreeRTOS Kernel`` Power Management Configuration

      #define configUSE_TICKLESS_IDLE         1

   This means we use a built-in FreeRTOS functionality to get the number of ticks 
   until the next tasks need to be executed. Please refer to |FreeRTOS LOW POWER SUPPORT|.
   for more information.

#. When there is no task running within 2 ticks from the future, then 
   the ``vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime)`` will be called, which 
   returns the number of ticks until next task occurs.
   The function can be found in ``{SDK_INSTALL_DIR}\kernel\freertos\dpl\PowerCCxxxx_freertos.c``

#. In ``vPortSuppressTicksAndSleep``, we can see the tick is saved to a global variable 
   and Power_idleFunc() gets called.

   .. code-block:: c
      :caption: ``PowerCCxxxx_freertos.c``:: vPortSuppressTicksAndSleep
      :linenos:

      void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime)
      {
          /* Stash FreeRTOS' expected idle time */
          PowerCCxxxx_idleTimeOS = xExpectedIdleTime;

          /*
           * call Power-driver-specified idle function, to conditionally invoke the
           * Power policy
           */
          Power_idleFunc();
      }

#. ``Power_idleFunc`` takes in policyFxn and policyFxn is defined using SysConfig tool :numref:`freertos_sysconfig_power_policy`. 
   By default, TI sets the ``PowerCCxxxx_standbyPolicy`` as policyFxn. 
   ``Power_idleFunc`` is defined in ``{SDK_INSTALL_DIR}\source\ti\drivers\power\PowerCCxxxx.c`` and
   ``PowerCCxxxx_standbyPolicy`` can be found in ``{SDK_INSTALL_DIR}\kernel\freertos\dpl\PowerCCxxxx_freetos.c``

   .. _freertos_sysconfig_power_policy:
   .. figure:: resources/freertos_sysconfig_power_policy.png
       :align: center

       Configure Power Policy for Idle Function.

#. In the Sysconfig generated files, you will find the following example in ti_drivers_config.c.

   .. code-block:: c
    :caption: ``ti_drivers.c``
    :linenos:

    const PowerCCXXXX_Config PowerCCxxxx_config = {
          .policyInitFxn            = NULL,
          .policyFxn                = PowerCCxxxx_standbyPolicy,
    };

.. ifconfig:: doctarget in ['ble5']

    With |STACK| applications, the power constraint is set in ``main()`` by
    defining the ``POWER_SAVING`` preprocessor symbol. When defined,
    enabled, the device enters and exits sleep as required for |STACK| events,
    peripheral events, application timers, and so forth. When undefined, the
    device stays in active mode.

    Also see `Measuring Bluetooth Smart Power Consumption <https://ti.com/lit/swra478>`_
    for steps to analyze the system power consumption and battery life.
