OVERVIEW
This document shows how to include the PowerLib to enable low power functionality in connectivity software projects that does not include it. It shows step by step instructions on how to import, configure and use this module.
Once you have installed the “Connectivity Software” package, browse for the extracted files (typically located in C:\Freescale\KW40Z_Connectivity_Software_1.0.0). In this location search for the LowPower folder, then copy and paste it into your new project folder.
Open your IAR project and create a new group called “Low Power”. Inside this group add two new groups called “Interface” and “Source”. In the Windows explorer, open the LowPower folder copied in the previous step. Drag and drop the contents of the "Interface" folder to the "Interface" group in IAR. Do the same for the "Source" folder. You can also use the option "Add Files" in the group menu to add the files.
Note: Do not copy the “PWR_Platform.c” and “PWR_Platform.h” files.
Once you have copied the files in their respective folders, you need to add the paths of these files in the project environment. Right click on the project name and select "Options".
In Options go to “C/C++Compiler”, select “Preprocessor” and click on the red square.
The next window will appear. Click on <Click to add> to open the windows explorer. Navigate to the folder PowerLib/Interface in your project to add the "Interface" folder path. Repeat this step with the "Source" folder.
To use low power in your project you need to define the following macros in the “app_preinclude.h” file:
/* Enable/Disable PowerDown functionality in PwrLib */
#define cPWR_UsePowerDownMode 1
/* Enable/Disable BLE Link Layer DSM */
#define cPWR_BLE_LL_Enable 1
/* Default Deep Sleep Mode*/
#define cPWR_DeepSleepMode 4
cPWR_UsePowerDownMode enables the necessary functions to use low power in your project. cPWR_BLE_LL_Enable configures the link layer to work in doze mode when in low power, and cPWR-DeepSleepMode defines the deep sleep mode the MCU will enter when the low power function is executed. There are the six different modes that can be used.
Mode 1: MCU/Radio low power modes:
MCU in LLS3 mode.
BLE_LL in DSM.
GPIO (push button) interrupt using LLWU module.
BLE_LL wake up interrupt(BLE_LL reference clock reaches wake up instance register) using LLWU module.
- BTE_LL wakeup timeout: controlled by the BLE stack(SoC must be awake before next BLE action).
- BTE_LL reference clock source: 32Khz oscillator
- BTE_LL reference clock resolution: 625us
Mode 2: MCU/Radio low power modes:
MCU in LLS3 mode.
BLE_LL in DSM.
GPIO (push button) interrupt using LLWU module.
BLE_LL wake up interrupt(BLE_LL reference clock reaches wake up instance register) using LLWU module.
- BTE_LL wakeup timeout: cPWR_DeepSleepDurationMs by default. Use PWR_SetDeepSleepTimeInMs to change it at run time. Maximum timeout is 40959 ms. BLE suppose to be idle.
- BTE_LL reference clock source: 32Khz oscillator
- BTE_LL reference clock resolution: 625us
Mode 3: MCU/Radio low power modes:
MCU in LLS3 mode.
BLE_LL in idle.
GPIO (push button) interrupt using LLWU module.
DCDC PowerSwitch - available in buck mode only.
LPTMR interrupt using LLWU module
- LPTMR wakeup timeout: cPWR_DeepSleepDurationMs by default. Use PWR_SetDeepSleepTimeInMs to change it at run time. Maximum timeout is 65535000 ms (18.2 h).
- LPTMR clock source: 32Khz oscillator
- LPTMR resolution: modified at run time to meet timeout value.
Mode 4: MCU/Radio low power modes:
MCU in VLLS0/1 mode(VLLS0 if DCDC bypassed/ VLLS1 otherwise ).
BLE_LL in idle.
GPIO (push button) interrupt using LLWU module.
DCDC PowerSwitch - available in buck mode only.
Mode 5: MCU/Radio low power modes:
MCU in VLLS2 (4k Ram retention (0x20000000- 0x20000fff)).
BLE_LL in idle.
GPIO (push button) interrupt using LLWU module.
DCDC PowerSwitch - available in buck mode only.
Mode 6: MCU/Radio low power modes:
MCU in STOP.
GPIO (push button) interrupt using LLWU module.
DCDC PowerSwitch - available in buck mode only.
LPTMR wakeup timeout: cPWR_DeepSleepDurationMs by default. Use PWR_SetDeepSleepTimeInMs to change it at run time. Maximum timeout is 65535000 ms (18.2 h).
- LPTMR clock source: 32Khz oscillator
- LPTMR resolution: modified at run time to meet timeout value.
- LPTMR resolution: modified at run time to meet timeout value.
Radio interrupt LL or 802.15.4
UART
Configuring Wakeup Source
The PowerLib software includes preconfigured wakeup methods for low power. These methods are described below and a couple of examples are included.
Configure Module Wakeup using LPTMR
This example explains how to configure the third deep sleep mode using the LPTMR as wakeup source. The desired low power mode must be configured in the file app_preinclude.h.
/* Default Deep Sleep Mode*/
#define cPWR_DeepSleepMode 3
On the same file, the macro cPWR_DeepSleepDurationMs macro must be added. It defines the time the MCU will be in low power mode before being waken by the low power timer. By default it it set to 10 seconds (10000 milliseconds).
#define cPWR_DeepSleepDurationMs 10000
This defines the time that the device will remain asleep by default. The PWR_SetDeepSleepTimeInMs function can be used to change this period at run time. Consider that the maximum time period is 65535000 ms (18.2 hours).
PWR_SetDeepSleepTimeInMs(10000);
Also the deep sleep mode can be changed at run time with the following function.
PWR_ChangeDeepSleepMode(3);
For further power reduction, all the modules not in use must be turned off . To run in this mode, all the timers except the LPTMR must be turned off. The device enters in low power mode with the following code lines in the main application.
PWR_SetDeepSleepTimeInMs(cPWR_DeepSleepDurationMs);
PWR_ChangeDeepSleepMode(3);
PWR_AllowDeviceToSleep();
Configure GPIO (Push Button) wakeup.
In the “PWRLib.c” file, find the “PWRLib_Init” function. It contains the code to initialize the LLWU pins to be used for wakeup. Chip configuration Reference Manual chapter contains information on which LLWU pins are tied to GPIOs on the MCU. For this example LLWU pins 6 and 7 (which are tied to PTA18 and PTA19 in the MCU) are used.
LLWU_PE1 = 0x00;
LLWU_PE2 = LLWU_PE2_WUPE7(0x03) | LLWU_PE2_WUPE6(0x03);
LLWU_PE3 = 0x00;
LLWU_PE4 = 0x00;
Since the LLWU pin sources work as GPIO interrupts, the propper ports in the MCU must be configured. Following code shows howthese pins are configured in the MCU.
/* PORTA_PCR18: ISF=0,MUX=1 */
PORTA_PCR18 = (uint32_t)((PORTA_PCR18 & (uint32_t)~(uint32_t)(
PORT_PCR_ISF_MASK |
PORT_PCR_MUX(0x06)
)) | (uint32_t)(
PORT_PCR_MUX(0x01)
));
PORTA_PCR19 = (uint32_t)((PORTA_PCR19 & (uint32_t)~(uint32_t)(
PORT_PCR_ISF_MASK |
PORT_PCR_MUX(0x06)
)) | (uint32_t)(
PORT_PCR_MUX(0x01)
));
Once the pins have been defined, it is neccesary to configure them as Keyboard inputs for the Power Lib. Go to "PWRLib.h" and find the next define:
#define gPWRLib_LLWU_KeyboardFlagMask_c (gPWRLib_LLWU_WakeupPin_PTA18_c | gPWRLib_LLWU_WakeupPin_PTA19_c )
In this define you must place the pins that were configured previously as wakeup sources.
Using Low Power in the Project
When you define "cPWR_UsePowerDownMode" in app_preinclude.h, it automatically creates a task in "ApplMain.c" called "App_Idle_Task". When executed by the OS scheduler, this task verifies if the device can go to sleep. This statement is always false unless the next function is called.
PWR_AllowDeviceToSleep();
This function indicates the program that the device can enter in low power and will execute the neccesary code to enter in the power mode configured at that time.
Note: Before you allow the device to sleep, disable all uneccessary modules and turn off all leds.
When the device is ready to enter in low power (all the application layers allows it and the device is in an iddle state) function PWR_EnterLowPower() must be called. This function will enter the MCU into the selected low power mode. On the HID example this is done into the iddle task as shown below.
#if (cPWR_UsePowerDownMode)
static void App_Idle(void)
{
PWRLib_WakeupReason_t wakeupReason;
if( PWR_CheckIfDeviceCanGoToSleep() )
{
/* Enter Low Power */
wakeupReason = PWR_EnterLowPower();
#if gFSCI_IncludeLpmCommands_c
/* Send Wake Up indication to FSCI */
FSCI_SendWakeUpIndication();
#endif
#if gKeyBoardSupported_d
/* Woke up on Keyboard Press */
if(wakeupReason.Bits.FromKeyBoard)
{
KBD_SwitchPressedOnWakeUp();
PWR_DisallowDeviceToSleep();
}
#endif
if(wakeupReason.Bits.DeepSleepTimeout)
{
Led1On();
for(;;)
{}
}
}
}
#endif /* cPWR_UsePowerDownMode */
PWR_CheckIfDeviceCanGoToSleep() function checks that all the application layers are agree on entering in low power mode (checking that PWR_DisallowDeviceToSleep() function hasn't been called). If everything is ok, function PWR_EnterLowPower() enters the device in low power and waits for a wakeup event.