5.2.5. Driver Power management

5.2.5.1. Introduction

A simple ON/OFF power management is handled in the communication channel configuration, but a more advanced power management should be provided by the drivers, to handle all power capabilities of external modules, and to provide more power control to the application.

This document describes how the driver should behave globally, and how it interfaces with power module. But the main part of the power management is specific to each module, and it can't be detailed in this document.

5.2.5.2. Power mode

This "advanced power management" is controled with orders from HAL power module. But this control is optional, so each driver should implement 2 operational modes: - mode with power control from power module - autonomous mode

To avoid incoherence between configuration of the driver and configuration of the power module, the mode is not a configuration of the driver, it must be retrieved from power module. At startup of the driver, power mode must be retrieved by calling * hal_pwr_ModeGet * function with name of your driver process. It will return: - eHAL_PWR__MODE__AUTONOMOUS: if driver is not controlled by the power manager - eHAL_PWR__MODE__MANAGED: if driver is controled by power manager

Then, in autonomous mode, it is up to the developer to define what should be the behavior of the driver regarding power control.

In controled mode, the driver must wait for first order from power module to define the state of the driver.

5.2.5.3. Power messages

The orders from power module are messages to set the power state (mOSS_MSG__ID(cHAL_PWR__STATE_MSG_INTERNAL, eHAL_PWR__STATE_MSG_INTERNAL__SET)) with structure sHalPwr_ApiStateSet in the message data. This structure contains the power state to set and the Power Id of the driver.

Driver must answer to this order with: - mOSS_MSG__ID(cHAL_PWR__STATE_MSG_INTERNAL, eHAL_PWR__STATE_MSG_INTERNAL__SET_OK) if power state could be set in the driver (or if driver was already in this state) - mOSS_MSG__ID(cHAL_PWR__STATE_MSG_INTERNAL, eHAL_PWR__STATE_MSG_INTERNAL__SET_FAIL) if driver was unable to set the power state

and with data structure sHalPwr_InternalApiStateSetAns in message data, which contains the power Id of the driver. (This power Id should be retrieved from the state set request).

Is is mandatory to handle these messages, in both power modes (autonomous and controled). If the driver is in autonomous mode ande receives a power state set message (even if it should not happen), driver should answer with a "SET_OK" message.

5.2.5.4. Power states

The possible power states are (from the lowest power consumption state to the highest): - eHAL_PWR__STATE__SHUTDOWN - eHAL_PWR__STATE__STANDBY - eHAL_PWR__STATE__STOP - eHAL_PWR__STATE__PAUSE - eHAL_PWR__STATE__SLOWER - eHAL_PWR__STATE__NORMAL - eHAL_PWR__STATE__FASTER

It is not required for the driver to implement different behavior/states for each of these power states (if the driver/module has less capabilities), but it is required to "map" all of them to real internal states of the driver. For example, if a module can only be turned ON or OFF, and no possibilities to fine tune the power consumption, then the mapping can be: HAL Pwr State orders Driver real state eHAL_PWR__STATE__SHUTDOWN OFF eHAL_PWR__STATE__STANDBY OFF eHAL_PWR__STATE__STOP OFF eHAL_PWR__STATE__PAUSE OFF eHAL_PWR__STATE__SLOWER ON eHAL_PWR__STATE__NORMAL ON eHAL_PWR__STATE__FASTER ON

In this case, whatever state from SHUTDOWN to PAUSE received by the driver is translated internally as the internal OFF state. Other states are considered as the internal ON state.

So all orders from power module are accepted.

5.2.5.5. Code samples

5.2.5.5.1. Power mode retrieve

Below an example of power mode retrieve at startup (assuming an ePowerMode variable of type eHalPwr_Mode is defined in the chest structure of the driver)

    mpDRV_XXXX__CHEST()->ePowerMode
    =       (hal_pwr_ModeGet)
            ( cDRV_XXXX__PROC
            );

    if (eHAL_PWR__MODE__AUTONOMOUS == mpDRV_COM_LPWAN_LORA__CHEST()->ePowerMode)
    // If driver is in autonomous mode
    {
            // Behavior to be defined
    }
    else
    // Driver controlled by power manager
    {
            // Driver should wait for first order from power module in the message loop to set the driver state.
    }

5.2.5.5.2. Power state set message handling

Below an example of handling for power state set messages.

    uErr_Code                                               l_uResult;
    sOssMsg_ApiMsg                                  l_sMsgToSend;
    eHalPwr_StateMsgInternal                l_ePwrMsgID;
    sHalPwr_InternalApiStateSetAns  l_sPwrIntApiStateSetAns;

    l_uResult
    = cERR__CODE__OK;

    mOSS_MSG__RECEIVE()
    {
            // Other cases of the driver (APIs, internal messages...)
            // case ...


            // Power internal message
            case mOSS_MSG__ID(cHAL_PWR__STATE_MSG_INTERNAL, eHAL_PWR__STATE_MSG_INTERNAL__SET):
            // Received a power state set request
            {
                    // Check data of message
                    if
                    (       ( NULL                                                  != mpOSS_MSG__BOX_ADDR())
                    &&      ( sizeof(sHalPwr_ApiStateSet)   == mOSS_MSG__BOX_SIZE())
                    )
                    {
                            // Get Power Function Id from message
                            l_sPwrIntApiStateSetAns.eHalPwrFuncId
                            = mpHAL_PWR__API_STATE_SET(mpOSS_MSG__BOX_ADDR())->eHalPwrFuncId;

                            // Check if driver is controled by power manager
                            if (eHAL_PWR__MODE__MANAGED == mpDRV_XXXX__CHEST()->ePowerMode)
                            {
                                    // Handle the power state to set in a specific function of the driver. The content is specific to the module and can't be described here
                                    l_uResult
                                    =       drv_XXXX_power_state_handle
                                            ( mpHAL_PWR__API_STATE_SET(mpOSS_MSG__BOX_ADDR())->eHalPwrState
                                            );

                                    if (cERR__CODE__OK._ == l_uResult._)
                                    {
                                            // Power state was applied
                                            l_ePwrMsgID
                                            = eHAL_PWR__STATE_MSG_INTERNAL__SET_OK;
                                    }
                                    else
                                    {
                                            // Power state couldn't be applied
                                            l_ePwrMsgID
                                            = eHAL_PWR__STATE_MSG_INTERNAL__SET_FAIL;
                                    }
                            }
                            else
                            {
                                    // Driver in autonomous mode, just answer SET OK
                                    l_ePwrMsgID
                                    = eHAL_PWR__STATE_MSG_INTERNAL__SET_OK;
                            }
                    }
                    else
                    {
                            // Could not retrieve data from message
                            l_sPwrIntApiStateSetAns.eHalPwrFuncId
                            = eHAL_PWR_FUNC__ID;

                            l_ePwrMsgID
                            = eHAL_PWR__STATE_MSG_INTERNAL__SET_FAIL;
                    }

                    // Reply to power module with message and info prepared above
                    mOSS_MSG__REPLY_DATA
                    ( mOSS_MSG__ID(cHAL_PWR__STATE_MSG_INTERNAL, l_ePwrMsgID)
                    , (pnU8)&l_sPwrIntApiStateSetAns
                    , sizeof(sHalPwr_InternalApiStateSetAns)
                    );
            }
    }
    mOSS_MSG__LOOP()