2023-05-05 06:56 AM
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'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.
Solved! Go to Solution.
2023-05-13 10:58 AM
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.
2023-05-10 12:58 AM
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
2023-05-10 01:20 AM
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.
2023-05-13 10:58 AM
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.