Getting started with LPBAM

This article explains the LPBAM feature, when and how to use it, and also provides code examples.

1. Introduction to LPBAM

1.1. Definition

The LPBAM stands for low-power background autonomous mode. It is an operating mode available in the STM32U5 products series that allows peripherals to be functional and autonomous in Stop 2 mode independently from the device power modes without any software running.

LPBAM Feature in U5.png

LPBAM subsystem can chain different operations thanks to DMA linked-list transfers.
The DMA operations can be related to:

  • Peripheral data transfer
  • Peripheral reconfiguration

1.2. Benefits

Two major advantages result from using LPBAM subsystem mechanisms:

  • Power consumption is optimized:

Bus and kernel clocks are distributed only when needed.
Most of the product parts can be shut down.
Analog peripherals or oscillators are powered on only when necessary.

  • CPU bandwidth is offloaded:

Peripheral configurations are done by DMA instead of CPU.
Data transfers are done by DMA instead of CPU.

1.3. Smart Run Domain (SRD)

The STM32U5 is split into two domains: CPU domain (CD) and SmartRun domain (SRD)

SRD smart run domain.png

The SRD architecture relies on a DMA allowing autonomous operation during low-power modes down to Stop 2. This architecture also features a 32-bit AHB bus matrix that interconnects:

  • Two masters:
    • the main AHB bus matrix
    • LPDMA1 (low-power DMA featuring one master port)
  • Two slaves:
    • AHB3 peripherals including AHB to APB bridge connected to APB3
    • internal SRAM4
Info white.png Information
The SRAM4 is the only SRAM that can be accessed by the LPDMA1.

1.4. Peripherals supporting LPBAM

There are 2 types of peripherals:

  • Autonomous peripherals: which have clock request capability and support DMA transfer in STOP mode.
  • Passive peripherals: can only be reconfigured or used as triggers, they do not support DMA or clock requests.

LPBAM is an operating mode that allows peripherals to function autonomously, independently of power modes, and without running any software.
The LPBAM is supported in Stop 2 mode.
So autonomous peripherals can request their clock (kernel or bus clocks), and can then stay functional in Stop mode where the clocks are disabled by default to reduce consumption (except for LSE and LSI low-power low-speed oscillators).
The table below lists all peripherals that support LPBAM.

Low-power mode Stop 2
Autonomous Peripherals ADC4, ADF1, DAC1, LPDMA1, LPTIM1, LPTIM3, LPUART1, I2C3, SPI3
Passive Peripherals LPTIM4, LPGPIO, VREFBUF, COMPs and OPAMPs, RTC/TAMP
Info white.png Information
Refer to AN5652 [1] to know more about peripherals supporting LPBAM.

2. How to use LPBAM to drive LPGPIO

To follow along with this example, you need a NUCLEO-U575 board.
Before starting the hands-on, make sure you have installed the following software:

  • STM32CubeMX 6.5.0 (or a newer version)
  • STM32CubeIDE 1.9.0 (or a newer version)
  • STM32CubeU5 firmware package

2.1. Block Diagram

The purpose of this example is to drive a GPIO pin (PA1) in the low-power domain controlled by linked-list DMA which is triggered by a low-power timer LPTIM with two different frequencies.

  • LPTIM with 50 ms period
  • LPTIM with 100 ms period

LPGPIO Triggered by LPTIM.png

2.2. Objectives

The purpose of this example is to demonstrate how to:

  • Configure LPBAM scenario
  • Measure the power consumption in STOP2 mode

2.3. STM32CubeMX LPBAM Configuration

To create an LPBAM application using the STM32CubeMX tool, you need:

  • The STM32CubeMX standard view. This sets up the main application and code generation.
  • The LPBAM view to build the LPBAM applications.
Info white.png Information
Check AN5816 [2] and this Video [3] as it explains step by step how to configure an LPBAM application in STM32CubeMX.
  • Open STM32CubeMX and choose your board in the board selector menu:

stm32U575 board selection.png

Then choose Start project with no peripheral initialization by pushing on the "NO" button. To avoid the generation of useless project code, the required peripherals are initialized later.

peripheral initialization.png

To build an LPBAM application when TrustZone® is deactivated:

  • Choose "without TrustZone activated".
  • Click on OK.

Without TrustZone activated.png

The STM32CubeMX tool entry point is always the standard view. Opening the project manager and saving the main project is recommended. For this application:

  • Click on the project manager panel.
  • Name the project LPGPIO_drive
  • For the "Project Location", save the project with the other examples in the firmware package.

At this point, the project is configured, and the IOC file is saved under the selected path. To increase the system performance, enabling the ICACHE peripheral in a one-way configuration is recommended. To do this, click on the "System Core" menu, then on the "ICACHE" peripheral, and change "Mode" to "1-way (direct mapped cache)".

ICache Mode .png

In this application, we are using LEDs (PC7 as LED BLUE, PG2 as LED RED, PB7 as LED GREEN) to observe the project runtime status and a user push-button pin (PC13) as an input with an external interrupt.

  • Choose External Interrupt Mode with Rising edge trigger detection as GPIO mode for User Button (PC13)
  • Enable the NVIC

enable NVIC.png

  • Set the state of the USB OTG pins (PA9 to PA12) as GPIO Analog to reduce the power consumption.

PA9 -PA12.png

Choose Systick as a timebase

Time base Source Systick.png

To reach the highest performance, in Clock Configuration, configure the system clock to the highest value. PLL 1 configuration is as follows:

  • PLLM = 1
  • PLLN = 80
  • PLLP = 2
  • PLLQ = 2
  • PLLR = 2

CubeMX-Clock Configuration.png

2.3.1. LPBAM scenario and configuration

At this point, the main project system is configured. In the next step, we build the "LPGPIO driving" application. Click on the "LPBAM Scenario & Configuration" panel

LPBAM scenario & Configuration.png

Click on the “+ Add Application” option to add an LPBAM application
When adding an LPBAM application, the STM32CubeMX tool shows the LBPAM view. As for the standard view, it contains “LPBAM Scenario & Configuration”, “Pinout & Configuration” and “Clock Configuration” panels.

Info white.png Information
The naming chosen in the project should be reused in code-generated APIs and variables. This ensures consistency between STM32CubeMX LPBAM tool views and LPBAM-generated application code.
Warning white.png Warning
It is recommended to carefully choose application naming for clear and readable generated code.

To do so:

  • Change the name of the application from LpbamAp1 to "LPGPIO_drive".
  • Change the name of the Scenario to "TrigGPIO".
  • Change the name of the Queue to "GPIOstate".

In Pinout & Configuration, under the system core, RCC, enable the low-speed clock LSE.

RCC config.png


To reach the lowest power consumption regarding the hardware target, you need to shut off all unused resources through the PWR peripheral. To do so:

  • Click on "Pinout & Configuration", then on "Power and Thermal", then on "PWR".
  • Enable the power-down for all the SRAMs, except SRAM4 and ICACHE.

PWR config.png


Now configure the LPBAM peripherals in Pinout & Configuration:

  • Click on "System Core" then on "GPIO" and configure PA1 as LPGPIO Output

LPGPIO output PA1.png

The next step is to configure the DMA channel that ensures the transfer of the LPTIM signal to trigger the LPGPIO.
In LPBAM mode, the DMA channel must be configured in a linked-list mode.

LPDMA Linked List.png

When DMA transfer is done in an infinite loop, the DMA channel execution mode should be configured in circular mode:

  • Left-click on "System core", then on "LPDMA1". Enable the "Linked-List Mode" for "CH0".
  • Click on "CH0". Then change the "Execution Mode" to "Circular" so that the PWM example runs in an infinite loop.
  • In Transfer Event Generation, choose the TC (and the HT) event generated at the (respectively half) end of the last linked-list item.

500

Next, go to "NVIC Settings" and enable "LPDMA1 SmartRun Channel 0 global interrupt".

LPDMA NVIC.png

All LPBAM peripherals (LPGPIO, LPDMA1, LPTIM) are now configured and ready for scenario queue building.

Info white.png Information
Note that the LPDMA is chosen because it is functional down to Stop2 mode.
  • Click on Timers then "LPTIM1". The "LPTIM1 Mode and Configuration" window appears.
  • Configure the following changes:

To modify the values of the Period and Repetition counter as shown in the figure below, click on this icon Settings No check.png and select No check.

LPTIM configuration.png

In the “User Constants” panel, click on "add "and create three "Constants":

User constants (timer).png

Info white.png Information
Check AN5816 [2] to know how to calculate the user constants

At this point, the LPTIM only needs the LPTIM clock configuration before it can generate a PWM signal.
In clock configuration, select LSE as the LPTIM1 clock source:

LPTIM1 clock config.png

2.3.2. Scenario queue building

STEP1: The LPTIM1 configuration sequence for the first node is as follows:
1. Go to LPTIM1 and click on the "+" in front of Start.
2. Change the function name to "Start_1".
3. Change the start Mode to "Continuous Mode".
5. Under "Trigger Configuration", keep "The Function execution is" as "Not conditioned by a trigger".

LPTIM Start 1.png

STEP2: configure the LPTIM1 configuration sequence for the second node as follows:
1. Go to LPTIM1 and click on the "+" in front of PWM.
2. Change the function name to "PWM_1".
3. Enable the period update state and insert 3270 as the period value.
4. Enable the pulse update state and insert 1630 as the pulse value.
5. Under "Trigger Configuration", keep "The Function execution is" as "Not conditioned by a trigger".

LPTIM PWM 1.png

STEP3: we configure the LPGPIO that is triggered by the previous LPTIM signal with a 100 ms period, We create two nodes; one for the Set and the other for the Reset.

1. Go to LPGPIO1 and click on the "+" in front of "Write Pin".
2. Change the function name to "Write_Pin_1".
3. Choose PA1 as the pin Name.
4. Choose Set as the pin State.
5. Under "Trigger Configuration", change "The Function execution is" from "Not conditioned by a trigger" to "Triggered on the Rising edge of the hardware Signal".
6. Change "Trigger hardware Signal is" from "EXTI line 0" to "LPTIM CH1".

LPGPIO WritePin1.png

STEP 4: For the second node, only do the following changes:
1. Change the function name to "Write_Pin_2".
2. Choose Reset as the pin State.
3. Change The function execution to 'triggered on the falling edge of the hardware signal'.
4. Change "Trigger hardware Signal is" from "EXTI line 0" to "LPTIM CH1".

LPGPIO WritePin2.png

Now, we configure the LPTIM1 with a 50 ms period to trigger the LPGPIO, we chose to configure the LPTIM with 2 different frequencies to show the independence of the queue.
To do so, repeat steps 2, 3, and 4 and only change the period and pulse values in step 2 as following:

  • Enable the period update state and insert 1630 as the period value.
  • Enable the pulse update state and insert 815 as the pulse value.

LPTIM PWM 2.png

Now, click on the queue "GPIOstate" and check Circular mode so put the queue in a while (1) loop and drag the arrow to the LPTIM1: PWM_1 node.
Following these steps, your queue should look like this:

Queue (circular mode) - Copie.png

Info white.png Information
Check UM1718 [4] for queues and nodes managing.
Warning white.png Warning
Respecting the order of function execution: first function, first execution is mandatory to configure the queue parameter.

At this point, the "LPGPIO drive" application is built into the STM32CubeMX LPBAM tool. It is then recommended to check the LPBAM design via the “Check LPBAM design” button. The STM32CubeMX tool checks, in the background, the consistency of the built application. It returns detected issues in the LPBAM log.

Check LPBAM design.png

Note: The below warnings won't affect the generation of your code!

LPBAM design warnings.png

Now, all the LPBAM application dependencies are configured.

2.4. Code configuration

The main and the LPBAM applications are ready to be generated.

  • Click on "GENERATE CODE" or CTRL+ S

For the LPBAM application, the generated files are:
• lpbam_lpgpio_drive.h
• lpbam_lpgpio_drive_config.c
• lpbam_lpgpio_drive_build.c
• lpbam_lpgpio_drive_config.c
They contain all the APIs needed by the main application to manage any LPBAM application correctly.

Go to the main.h file, add «#include <stdint.h>» in the “USER CODE BEGIN Includes” user section. and in the USER CODE BEGIN ET add:

/* USER CODE BEGIN Includes */
#include <stdint.h>
/* USER CODE END Includes */
/* USER CODE BEGIN ET */
typedef enum
{
  PB_NOT_PRESSED =   0,
  PB_PRESSED     =   1,
} PB_State_t;
/* USER CODE END ET */

In the main.c file, add «#include "lpbam_lpgpio_drive.h"» in the “USER CODE BEGIN Includes” user section.

/* USER CODE BEGIN Includes */ 
#include "lpbam_lpgpio_drive.h"
/* USER CODE END Includes */

In the core of the main () API, the LEDs that we are using must be initialized inside the “USER CODE BEGIN PD” user section.

* USER CODE BEGIN PD */

#define LED_GREEN ((uint32_t) (0X0U))
#define LED_BLUE ((uint32_t) (0X1U))
#define LED_RED ((uint32_t) (0X2U))

#define ERROR_NONE ((int32_t) (0x0))
/* USER CODE END PD */

Add the button declaration to the “USER CODE BEGIN PV” user section in main.c.

* USER CODE BEGIN PV */
/* Push Button State */
__IO uint32_t PushButtonState = PB_NOT_PRESSED;
/* USER CODE END PV */

Now, add the functions declarations in the main.c under the user section named “USER CODE BEGIN PFP”.

/* USER CODE BEGIN PFP */
static void Enter_Stop2_Mode(void);
static int32_t LED_On(uint32_t Led);
static int32_t LED_Off(uint32_t Led);
/* USER CODE END PFP */

To reach the lowest power consumption, all pins unused by the LPBAM scenario are configured in analog mode, including the debug pins. After initializing the LEDs and the push-button, you need to call the LPBAM-generated APIs to initialize, build, link, and start the LPBAM application within the “USER CODE BEGIN 2” user section.

Warning white.png Warning
It is mandatory to follow the following call sequence to make any LPBAM application run.
/*  LPBAM_LPGPIO_drive application init */
  MX_LPGPIO_drive_Init();

  /* LPBAM_LPGPIO_drive application TrigGPIO init */
  MX_LPGPIO_drive_TrigGPIO_Init();

  /* LPBAM_LPGPIO_drive application TrigGPIO build */
  MX_LPGPIO_drive_TrigGPIO_Build();

  /*  LPBAM_LPGPIO_drive application TrigGPIO link */
  MX_LPGPIO_drive_TrigGPIO_Link(&handle_LPDMA1_Channel0);

  /*  LPBAM_LPGPIO_drive application TrigGPIOstart */
  MX_LPGPIO_drive_TrigGPIO_Start(&handle_LPDMA1_Channel0);

At this point, the LPBAM application is operating. Stop2 mode must be entered:

 /* Enter Stop2 mode */
  Enter_Stop2_Mode ();

User push-button pin (PC13) is configured as input with external interrupt (EXTI_Line13), falling edge. When it is pressed, the system wakes up from Stop2 mode.
The board LEDs are used to monitor the transfer status:

  • LED_GREEN: ON at the end of the application
  • LED_BLUE ON after waking up from Stop2 mode and before pressing the user push-button.
  /* Reset push button state */
  PushButtonState = PB_NOT_PRESSED;

  /* Turn LED_BLUE on */
  LED_On(LED_BLUE);

  /* Wait for the next push button press to stop the LPBAM LPGPIO_drive application TrigGPIO scenario */
  while (PushButtonState == PB_NOT_PRESSED);

  /* Turn LED_BLUE off */
 LED_Off(LED_BLUE);

For this application, you need to call the following API also in the “USER CODE BEGIN 2” user section. This stops, unlinks, and de-initializes the LPBAM application and the green led turns on.

/*LPBAM_LPGPIO_drive application TrigGPIO scenario stop */
  MX_LPGPIO_drive_TrigGPIO_Stop(&handle_LPDMA1_Channel0);

  /* LPBAM_LPGPIO_driveapplication TrigGPIO scenario unlink */
  MX_LPGPIO_drive_TrigGPIO_UnLink(&handle_LPDMA1_Channel0);

  /* LPBAM_LPGPIO_drive application TrigGPIO scenario de-init */
  MX_LPGPIO_drive_TrigGPIO_DeInit();

  LED_On(LED_GREEN);

Any additional service can be added under user codes in the main.c file. For this application, an application API is needed that:

  • Enters Stop2 mode and checks whether or not the system was in stop mode

These functionalities are added to the “USER CODE BEGIN 4” user section.

/* USER CODE BEGIN 4 */
static void Enter_Stop2_Mode(void)
{
  /* Enter the system to STOP2 mode */
  __HAL_RCC_PWR_CLK_ENABLE ();
  HAL_PWREx_EnterSTOP2Mode (PWR_STOPENTRY_WFI);

  /* Check that the system was resumed from stop 2 */
  if (__HAL_PWR_GET_FLAG (PWR_FLAG_STOPF) == 0U)
  {
    Error_Handler();
  }

  /* Clear stop flag */
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOPF);

  /* Check that the stop flag is cleared */
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOPF) != 0U)
  {
    Error_Handler();
  }
}

Now, add the GPIO_EXTI Callback function, and the LED_On and LED_Off functions.

void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  PushButtonState = PB_PRESSED;

}
static int32_t LED_On(uint32_t led)
{
  int32_t ret = ERROR_NONE;

  if(LED_GREEN == led)
  {
    HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_SET);
  }
  else if (LED_BLUE == led)
  {
    HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_SET);
  }
  else if (LED_RED == led)
  {
    HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET);
  }
  else
  {
    // Do nothing
  }
  return ret;
}
static int32_t LED_Off(uint32_t led)
{
  int32_t ret = ERROR_NONE;

  if(LED_GREEN == led)
  {
    HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET);
  }
  else if (LED_BLUE == led)
  {
    HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_RESET);
  }
  else if (LED_RED == led)
  {
    HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET);
  }
  else
  {
    // Do nothing
  }
  return ret;
}
/* USER CODE END 4 */
Warning white.png Warning
For this application, the DMA channel used can access only SRAM4 in the same power domain. So, change the start address of the RAM to be accessible by the DMA channel

To do so, In the STM32CubeIDE, in Project Explorer > Debug, go to the STM32U575ZITXQ_FLASH.ld and configure the RAM ORIGIN = 0x28000000 and the LENGTH = 16 Kbytes

memory regions.png


2.4.1. Compile and flash

Depending on your application phase, you can either enable or disable the debug configuration.

  • In the development phase, it is better to enable debugging in low-power modes for debug purposes

To do so:

1. click on the debug configuration icon

debug configuration1.png

2. Click on the STM32 C/C++ application

debug configuration2.png

3. Click on the "New launch configuration icon"

debug configuration3.png

4. Enable the debug in low-power modes

Debug Config1.png

  • After developing your application, to reach the optimal power consumption, make sure to disable the debug in low-power modes.

Debug configuration.png

  • Click the Build button Built.png
  • Click the Run button to execute Run.png

After downloading the code, the LPBAM scenario is repeated in an infinite loop.
Using a logic analyzer, we visualized the LPTIM and LPGPIO signals.

LPTIM and LPGPIO signals.png

As shown in the above image, LPGPIO0_PA1 is set or reset following the LPTIM_PC1 signal with 50 and 100 ms periods.

2.5. Power Consumption measurement

To measure the power consumption of the application, the STM32 Power Shield application is used to supply the Nucleo board. To do so, you can use the X-NUCLEO-LPM01A [5] expansion board for power consumption measurement and its user manual [6]

Info white.png Information
Regarding the power consumption using LPBAM, check AN5845 [7] for more details.

The Power Shield is a plug-and-play solution intended to ease power consumption measurements.
Using the power shield with the STM32U575 Nucleo board in stop2 mode, we measured 4.06µA which is aligned with the datasheet [8].

Power consumption.png

3. How to use LPBAM for I2C or SPI transfer

This case is applicable when interfacing with external components like a MEM sensor for example over I2C or SPI. LPBAM and LPDMA can be used to transfer data from the peripheral into memory, and the MCU core only wakes up when the transfer is completed: Wakeup on Complete.
I2C-SPI transfer.png

For an example of SPI or I2C transfer, check the examples in the STM32U5 Cube Firmware following these paths:
1) STM32Cube\Repository\STM32Cube_FW_U5\Projects\NUCLEO-U575ZI-Q\Applications\LPBAM\LPBAM_I2C_TransmitReceive
2) STM32Cube\Repository\STM32Cube_FW_U5\Projects\NUCLEO-U575ZI-Q\Applications\LPBAM\LPBAM_SPI_TransmitReceive

4. How to use LPBAM for ADC or DAC conversion

We can also trigger ADC with a periodic timer and store the data in memory while the rest of the device is sleeping.

ADC triggered by LPTIM.png

For examples of ADC or DAC, check the example in the STM32U5 Cube Firmware following this path:
STM32Cube\Repository\STM32Cube_FW_U5\Projects\NUCLEO-U575ZI-Q\Applications\LPBAM\LPBAM_ADC_TempSense
STM32Cube\Repository\STM32Cube_FW_U5\Projects\NUCLEO-U575ZI-Q\Applications\LPBAM\LPBAM_DAC_OPAMP_SigAmpli

Info white.png Information
Check AN5816 [2] for the STM32CubeMX LPBAM TempSense application description and building.

5. How to use LPBAM for LPTIM PWM ratio change, Input Capture, Pulse Counter

The LPTIM can be used for timing and output generation while the STM32 device is in low-power mode. it provides the basic functions of the STM32 general-purpose timers with the advantage of very low-power consumption. Additionally, when configured in Asynchronous counting mode, the LPTIM keeps running even when no internal clock source is active.

LPTIM Trigger.png

For an example of LPTIM PWM ration change, check the example in the STM32U5 Cube Firmware following this path:
STM32Cube\Repository\STM32Cube_FW_U5\Projects\NUCLEO-U575ZI-Q\Applications\LPBAM\LPBAM_LPTIM_PWMGen

Info white.png Information
Check AN4865 [9] for Low-power timer (LPTIM) applicative use cases on STM32 MCUs and MPUs.

More complex applications can be built using several DMA channels or chaining operations from different peripherals on the same channel as the case in AN5834 [10] which describes the LC sensor metering feature included in the STM32U5 Nucleo board NUCLEO-U575ZI-Q[11].

6. References