Skip to main content
ALABR.1
ST Employee
May 5, 2023
Solved

STOP2 low power on STM32WB55 with BLE connection wakeup

  • May 5, 2023
  • 2 replies
  • 4467 views

Hello all,

I am running a custom BLE application on STM32WB55 and I want to implement low power STOP2 mode because it's the deepest while RF is still alive.

The idea is to periodically wakeup, procced some data and go back to STOP2. I may also need to wakeup on a BLE connection request.

From my research and what I understund (please do not hesitate to correct me in anyway) :

  • I don't need to care about CPU2 (Cortex-M0+) low power because it will achieve this best available
  • I need to take care of semaphores when going into STOP2 to synchronize between the 2 cores

I've look carefully about the hearth rate project and try to use it as a template.

What I've done:

I am running on HSE_Sys@32MHz, to be able to use function provide in stm32_lpm_if.c whitout modification.

On app_entry.c into MX_APPE_Init():

/**
 * The Standby mode should not be entered before the initialization is over
 * The default state of the Low Power Manager is to allow the Standby Mode so an request is needed here
 */
 UTIL_LPM_SetOffMode(1 << CFG_LPM_APP, UTIL_LPM_DISABLE);

to be able to go into STOP2 (and not OFF Mode).

In app_conf.h:

/**
 * When set to 1, the low power mode is enable
 * When set to 0, the device stays in RUN mode
 */
#define CFG_LPM_SUPPORTED 1
 
......
 
/**
 * When set, this resets some hw resources to set the device in the same state than the power up
 * The FW resets only register that may prevent the FW to run properly
 *
 * This shall be set to 0 in a final product
 *
 */
#define CFG_HW_RESET_BY_FW 0
 
/**
 * keep debugger enabled while in any low power mode when set to 1
 * should be set to 0 in production
 */
#define CFG_DEBUGGER_SUPPORTED 1
 
/**
 * When set to 1, the traces are enabled in the BLE services
 */
#define CFG_DEBUG_BLE_TRACE 0
 
/**
 * Enable or Disable traces in application
 */
#define CFG_DEBUG_APP_TRACE 0

Nothings else than the sequencer is implemented in the main while(1) loop:

/* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 
 /* USER CODE END WHILE */
 MX_APPE_Process();
 
 /* USER CODE BEGIN 3 *
 
 }
 /* USER CODE END 3 */
}

For now I have not change anythings into stm32_lpm_if.c :

PWR_EnterStopMode:

void PWR_EnterStopMode(void)
{
/* USER CODE BEGIN PWR_EnterStopMode_1 */
 
/* USER CODE END PWR_EnterStopMode_1 */
 /**
 * When HAL_DBGMCU_EnableDBGStopMode() is called to keep the debugger active in Stop Mode,
 * the systick shall be disabled otherwise the cpu may crash when moving out from stop mode
 *
 * When in production, the HAL_DBGMCU_EnableDBGStopMode() is not called so that the device can reach best power consumption
 * However, the systick should be disabled anyway to avoid the case when it is about to expire at the same time the device enters
 * stop mode (this will abort the Stop Mode entry).
 */
 HAL_SuspendTick();
 
 /**
 * This function is called from CRITICAL SECTION
 */
 EnterLowPower();
 
 /************************************************************************************
 * ENTER STOP MODE
 ***********************************************************************************/
 LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
 
 LL_LPM_EnableDeepSleep(); /**< Set SLEEPDEEP bit of Cortex System Control Register */
 
 /**
 * This option is used to ensure that store operations are completed
 */
#if defined (__CC_ARM)
 __force_stores();
#endif
 
 __WFI();
 
/* USER CODE BEGIN PWR_EnterStopMode_2 */
 
/* USER CODE END PWR_EnterStopMode_2 */
 return;
}

PWR_ExitStopMode:

/**
 * @brief Exits Low Power Stop Mode
 * @note Enable the pll at 32MHz
 * @param none
 * @retval none
 */
void PWR_ExitStopMode(void)
{
/* USER CODE BEGIN PWR_ExitStopMode_1 */
 
/* USER CODE END PWR_ExitStopMode_1 */
 /**
 * This function is called from CRITICAL SECTION
 */
 ExitLowPower();
 
 HAL_ResumeTick();
/* USER CODE BEGIN PWR_ExitStopMode_2 */
 
/* USER CODE END PWR_ExitStopMode_2 */
 return;
}

My problem:

When CFG_LPM_SUPPORTED = 1 (low power mode enable) I can see my device but with only 1 services (I normally have 5) and I can connect only 1 time (2nd attempt I can't even see the device). Consumption ~3mA.

When CFG_LPM_SUPPORTED = 0, everything work like a charm and get ~10mA consumption.

I will appreciate any help or advises.

Many thanks,

Axel L.

This topic has been closed for replies.
Best answer by ALABR.1

Problem was solve thanks to @Remy ISSALYS​. A bad configuration of the linker file (STM32WBxx_FLASH.ld file) autogenerated by Cube was in cause. In section MB_MEM2 (near the end of the .ld file) I change from *(.MB_MEM2) to *(MB_MEM2) {note that the dot have been remove}. This solves all my issues.

Old linker file section:

....
 
 /* used by the startup to initialize .MB_MEM2 data */
 _siMB_MEM2 = LOADADDR(.MB_MEM2);
 .MB_MEM2 :
 {
 _sMB_MEM2 = . ;
 *(.MB_MEM2) ;
 _eMB_MEM2 = . ;
 } >RAM_SHARED AT> FLASH
}

New one (correct one):

....
 
 /* used by the startup to initialize .MB_MEM2 data */
 _siMB_MEM2 = LOADADDR(.MB_MEM2);
 .MB_MEM2 :
 {
 _sMB_MEM2 = . ;
 *(MB_MEM2) ;
 _eMB_MEM2 = . ;
 } >RAM_SHARED AT> FLASH
}

This should be fixe in a upcoming release (V1.13.0). Hope this could help.

BeST Regards,

Axel L.

2 replies

Remy ISSALYS
ST Technical Moderator
May 10, 2023

Hello,

Your understanding is correct, BLE_HeartRate example available in STM32CubeWB package is the reference example for stop2 low power mode.

In your case to reach the right consumption, you should disable the debugger:

#define CFG_DEBUGGER_SUPPORTED 0

Ensure that the advertising is restarted when a disconnection occurs to see again the device. When CFG_LPM_SUPPORTED = 0, you see all the services?

Which IDE and smartphone application are you using?

Best Regards

ALABR.1
ALABR.1Author
ST Employee
May 10, 2023

Hello @Remy ISSALYS​ ,

First of all, thanks for your time.

When I am running in run mode (CFG_LPM_SUPPORTED = 0) I can see all my services and everythings works perfectly.

I am developing on STM32CubeIDE 1.12.0, using ST BLE ToolBox on my IOS phone.

BLE stack full is used on V1.16.0.4.

Since the time I post I found that if I run in lowpower mode (CFG_LPM_SUPPORTED = 1) with debugger stopping regularly the code at void UTIL_LPM_EnterLowPower(void) (I spray the continue button every 1s) everything work and I am able to see my services, and read characteristics. But if I let the code running by itself without any breakpoints, I only see 1 service (I have 5 in normal condition)

Also note that for the wakeup restoration clock setting I have implement nothings more than the usual HSE:

stm32_lpm_if.c:

/**
 * @brief Restore the system to exit stop mode
 * @param none
 * @retval none
 */
static void ExitLowPower(void)
{
 /* Release ENTRY_STOP_MODE semaphore */
 LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
 
 while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID));
 
 if(LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
 {
/* Restore the clock configuration of the application in this user section */
/* USER CODE BEGIN ExitLowPower_1 */
	LL_RCC_HSE_Enable( );
	__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);
	while(!LL_RCC_HSE_IsReady( ));
	LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
	while (LL_RCC_GetSysClkSource( ) != LL_RCC_SYS_CLKSOURCE_STATUS_HSE);
/* USER CODE END ExitLowPower_1 */
 }
 else
 {
/* If the application is not running on HSE restore the clock configuration in this user section */
/* USER CODE BEGIN ExitLowPower_2 */
 
/* USER CODE END ExitLowPower_2 */
 }
 
 /* Release RCC semaphore */
 LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
 
 return;
}

Is this clock setting after wakeup is correct?

Many thanks for your help.

ALABR.1
ALABR.1AuthorBest answer
ST Employee
May 13, 2023

Problem was solve thanks to @Remy ISSALYS​. A bad configuration of the linker file (STM32WBxx_FLASH.ld file) autogenerated by Cube was in cause. In section MB_MEM2 (near the end of the .ld file) I change from *(.MB_MEM2) to *(MB_MEM2) {note that the dot have been remove}. This solves all my issues.

Old linker file section:

....
 
 /* used by the startup to initialize .MB_MEM2 data */
 _siMB_MEM2 = LOADADDR(.MB_MEM2);
 .MB_MEM2 :
 {
 _sMB_MEM2 = . ;
 *(.MB_MEM2) ;
 _eMB_MEM2 = . ;
 } >RAM_SHARED AT> FLASH
}

New one (correct one):

....
 
 /* used by the startup to initialize .MB_MEM2 data */
 _siMB_MEM2 = LOADADDR(.MB_MEM2);
 .MB_MEM2 :
 {
 _sMB_MEM2 = . ;
 *(MB_MEM2) ;
 _eMB_MEM2 = . ;
 } >RAM_SHARED AT> FLASH
}

This should be fixe in a upcoming release (V1.13.0). Hope this could help.

BeST Regards,

Axel L.