cancel
Showing results for 
Search instead for 
Did you mean: 

STOP2 low power on STM32WB55 with BLE connection wakeup

ALABR.1
ST Employee

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.

1 ACCEPTED SOLUTION

Accepted Solutions
ALABR.1
ST Employee

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.

View solution in original post

3 REPLIES 3
Remy ISSALYS
ST Employee

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

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
ST Employee

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.