Skip to main content
Associate III
April 22, 2026
Question

STOP mode and BLE

  • April 22, 2026
  • 6 replies
  • 113 views

Hey. I currenlty have a wba55 baord and use it as a ble p2p server. The main idea is to put put the board to stop0/1 mode when disconnected so that it consumes some μ amps and turn it back on when receiving a specific interrupt (eg button, timer etc).
I tried a minimal bare-metal example, where i turned on every peripheral (uart, i2c etc) i would use on my actual project to monitor power consumption and before sleep mode i de-inited each and every one of them and all interrupt sources other than the specific EXTI line. The thing is that the device seemed like unable to even enter stop mode. I turned off the rf module through mx and it worked perfectly. 
So from what i understood, the rf module and be in general produces a ton of interrupts which doesn't let the device to stay in stop mode. Is there any way to disable the rf module/ ble during runtime and re enable it once the device wakes up from the intended interrupt source ? 

6 replies

ST Employee
April 24, 2026

Hello,

if I understand you correctly, you want to have p2p server application with some added features.

As a reference, you can use STM32CubeWBA P2P_Server example. In the app_conf.h file you can choose which low power mode will be used.

All of the BLE examples runs with Sequencer which autonomously choose whether to enter low power mode and does that so when there no task to perform.

If you want to achieve something like disconnection -> device goes to stop mode -> you press the button -> device starts advertising again, you need to cancel advertising after the disconnection.

 

For more information, you can refer to STM32WBA_Peer_To_Peer or STM32CubeWBA_Low_Power_Management 

Hope this helps

Best regards,

grohmano

AlexESAuthor
Associate III
April 27, 2026

Hello. Thanks for your anwser. I want to use the threadx p2p server with added features, but without using the sequencer. Is there a way to implement the low power modes using the settings you mentioned above but without the sequencer ? 

ST Employee
April 27, 2026

Hello,

in that case, you can refer to BLE_p2pServerThreadX example.

Low power modes are implemented in the same way how they are in other examples -> in the app_conf.h file, set CFG_LPM_LEVEL macro according to your needs.

 

Best regards,

grohmano

AlexESAuthor
Associate III
April 27, 2026

Thank you. Just tried it. For some reason the expansion for that specific macro seems to fail. Even though i set it as 1 or two it always seems to expand to 0. The rest of the macros expand as they should. SHould i try to hard code the macro on each file it is being used to at first ? 

ST Employee
April 27, 2026

That is strange. May I ask how did you find that the macro is not working?
It works on my side. Only problem is that there is not included tx_low_power.h file in include paths and you have to add it manually.

 

Best regards,

grohmano

AlexESAuthor
Associate III
April 27, 2026

I hovered my cursor over the macro on the if def section of various .c file and the result was macro expansion = 0, even though it was defined as 2 in the app_conf.h file . I defined it as 2 on the files that it was used, but still the device wouldnt enter stop mode at all. So i have the following questions

1) Do all threads need to be innactive for the device to entrer stop mode? (either wait forever statement or sleep)
2) Do i also need to include the header file you mentioned for the LPM to work ?
3) Why does the expansion for the specific macro fail whereas the rest of the macros expand correctly ?

ST Employee
April 27, 2026

Hello,

to your questions:

1) Yes, operating system manages task queue and if there is no task to be done, it sets Idle Task in which entering low power mode is implemented.

2) Yes, the mentioned file needs to be included because it implements ThreadX low power behavior

3) I honestly do not know, it works for me. If you use EWARM, indexes should change after building project, in CubeIDE you need to build indexes on their own.

One more piece of information, please do not forget to choose low power mode by setting respective macro:

/******************************************************************************
 * Low Power
 *
 * When CFG_LPM_LEVEL is set to:
 * - 0 : Low Power Mode is not activated, RUN mode will be used.
 * - 1 : Low power active, mode(s) selected with CFG_LPM_mode_SUPPORTED
 * - 2 : In addition log and debug are disabled to reach lowest power figures.
 ******************************************************************************/
#define CFG_LPM_LEVEL (1U)

#define CFG_LPM_STOP1_SUPPORTED (1U)
#define CFG_LPM_STANDBY_SUPPORTED (0U)

 

Best regards,

grohmano

AlexESAuthor
Associate III
April 27, 2026

/******************************************************************************
 * Low Power
 *
 * When CFG_LPM_LEVEL is set to:
 * - 0 : Low Power Mode is not activated, RUN mode will be used.
 * - 1 : Low power active, mode selected with CFG_LPM_STDBY_SUPPORTED
 * - 2 : In addition log and debug are disabled to reach lowest power figures.
 *
 * When CFG_LPM_STDBY_SUPPORTED is set to:
 * - 2 : Stop mode 2 is used as low power mode (if supported by target)
 * - 1 : Standby is used as low power mode.
 * - 0 : Stop mode 1 is used as low power mode.
 *
 ******************************************************************************/
#define CFG_LPM_LEVEL (2)
#define CFG_LPM_STDBY_SUPPORTED (0)
​

Only these 2 macros are the relevant ones reguarding mode selection. I chode 0 for the second one since i want my device to enter stop1 mode. 
I've also added a flag to block the threads when a specific event (eg disconnection happens). 

void main_thread_entry(ULONG thread_input) {
	main_setup();

	while (1) {
		if (go_to_sleep)
				tx_thread_sleep(TX_WAIT_FOREVER);
		main_loop();
	}
}

I've also included the tx_low_power header manually. Still my device seems to not enter low power mode. Do i also need to disable my peripherals before blocking the threads? (uart and i2c with dma enabled).
Last but not least do i need to check any other setting on the .ioc / app_conf.h file?

ST Employee
April 27, 2026

Hello,

from your code snippet of low power mode choice, I assume that you do not use the latest SDK since this approach was used in STM32CubeWBA V1.7.0 for the last time, the latest is 1.9.0. This may result in malfunctioning and misunderstanding between us. 

Since I do not know your application, I can only recommend you download the latest package and start adding your proprietary features into the working ST example 1.9.0 version. 

 

Best regards,

grohmano

AlexESAuthor
Associate III
April 27, 2026

Unfortunatelly i can't update to the latest fw version since that i cannot update my cubeIDE version. I've tried to edit my .ioc and threadx_app.c file according to your (ST) threadx_low_power example. 
I copied and pasted the following function, replacing their __weak declaration. 

void App_ThreadX_LowPower_Enter(void)
{
 /* USER CODE BEGIN App_ThreadX_LowPower_Enter */
	/* USER CODE BEGIN App_ThreadX_LowPower_Enter */
	 /* Deactivate Debug of Stop mode */
	 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
	 HAL_DBGMCU_DisableDBGStopMode();
	 __disable_interrupts();
	 /* Deactivate Debug of Standby mode */
	 HAL_DBGMCU_DisableDBGStandbyMode();

	 /* Enter to the stop mode */
	 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
	 go_to_sleep = 0;

 /* USER CODE END App_ThreadX_LowPower_Enter */
}

/**
 * @brief App_ThreadX_LowPower_Exit
 * @PAram None
 * @retval None
 */
 void App_ThreadX_LowPower_Exit(void)
{
 /* USER CODE BEGIN App_ThreadX_LowPower_Exit */
	 __enable_interrupts();
	 SystemClock_Config();
	 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
 /* USER CODE END App_ThreadX_LowPower_Exit */
}

I've also set a flag to 1 during the disconnection event on the ble_app fsm and added this statement into every thread loop to block them and enter the idle entry.

static void app_main_thread_entry(ULONG thread_input) {
	app_main_setup();

	while (1) {
		if(go_to_sleep)
				 tx_thread_sleep(TX_WAIT_FOREVER);
		app_main_loop();
	}
}

Am i at the right direction? I will try to stop the various peripherals next but, what am i missing here ?