cancel
Showing results for 
Search instead for 
Did you mean: 

How to enter SLEEP/STOP mode on STM32WB device ?

JGUIT.1
Associate III

Hello,

I wonder how the STM32WB device should be entered in SLEEP or STOP mode. Any specific actions to reduce the total consumption to the minimum, particularly thinking to the radio? When is it good to enter SLEEP or STOP mode ?

If anyone can point a working example, it will be great 🙂

Context : I have Thread (and in near future BLE+Thread) running on my device. I would like to put the total consumption to the minimum because the board is supplied with a small battery. Then periodically the device is wake-up, processing, sending data to the Thread network and finally goes to STOP mode again.

Thanks,

Joel

16 REPLIES 16
Piranha
Chief II

SLEEP is used while everything is working, but the CPU has nothing to do for some time. STOP is used when you turn off at least some part of the hardware.

JGUIT.1
Associate III

Hello @Piranha​ 

I'm aware of that, I just want to know how I can do it with the STM32WB 🙂 I want to sleep properly the radio core too. Then when the MCU wakes up, turn on the radio again and connect to my thread network to send data.

I have tried some playing with "HAL_PWR_EnterSLEEPMode" function but with no success, even the main core does not enter sleep mode. I suppose I have to turn off the radio and then use "HAL_PWR_EnterSLEEPMode" but I have not found any example...

Thanks,

Joel

JGUIT.1
Associate III

Updates : I have used the example "Thread_Udp" in which the function "UTIL_SEQ_Idle" has the following content:

void UTIL_SEQ_Idle( void )
{
#if ( CFG_LPM_SUPPORTED == 1)
  UTIL_LPM_EnterLowPower( );
#endif
  return;
}

So I have defined CFM_LPM_SUPPORTED to enter low power mode. Seems the program enters this function but the best I have reach is 14mA on my P-NUCLEO-WB55 (open JP2 to measure CPU consumption).

This is not really the expected result. This document https://www.stmicroelectronics.com.cn/content/ccc/resource/training/technical/product_training/group0/38/e8/fa/59/e8/38/46/63/STM32WB-System-Power-control-PWR/files/STM32WB-System-Power-control-PWR.pdf/_jcr_content/translations/en.STM32WB-System-Power-control-PWR.pdf indicates 2µA in STOP2 mode.

Piranha
Chief II
JGUIT.1
Associate III

Thanks this suggestion is great and make some progress!

I have written the following in a blank project :

DBGMCU->CR = 0;
HAL_SuspendTick();
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
LL_LPM_EnableDeepSleep();
__WFI();
SystemClock_Config();
HAL_ResumeTick();

The MCU goes in STOP2 and the power consumption is about 2µA which is conformed with the specification.

Now trying to add this in a Thread application. Still using "Thread_Udp" as a basis to make some testing.

Christophe Arnal
ST Employee

Hello,

Generally speaking, the CPU1 shall never write CPU2 registers with LL_C2_***().

This can be done only in specific corner case under specific conditions.

The workaround described that recommends to use LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); is required only in case CPU2 is not started.

In that case when CPU2 is not started ( which is not the case in all ST BLE examples), and only CPU1 is running , the reset value of the low power mode of CPU2 is set to Stop Mode 0. This will limit the full device to Stop Mode 0 at best.

So, the workaround is to use LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2) before CPU2 is started with C2BOOT. As soon as CPU2 has been started, LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); shall not be used anymore as this will break the power management implemented on CPU2.

Each CPU subsystem on STM32WB has its own low power management and each CPU subsystem shall take care only of its own low power mode.

As soon as CPU2 is started, CPU1 has nothing to do to control low power mode on CPU2.

Basically, CPU1 shall handle sleep/stop low power mode has this will be done on any STM32 single core product with no worry of CPU2.

The only difference is that you should use the implementation of stm32_lpm_if.c as there are some RCC registers that may be accessed by both Cores when entering low power mode at the same time  so it is required to use some semaphore.

stm32_lpm_if.c implements the algorithm to use.

Regarding Thread project, you should start from a Thread_SED_*** application that implements the low power mode.

Regards.

@Christophe Arnal​ , thank you for taking the time to make this valuable addition to understanding of the power modes between CPU1 and CPU2!

Now I fully appreciate the order of steps in the sample apps, and now fully understand the importance of once, before running CPU2 interface intialization, configuring the LL_C2_PWR_SetPowerMode().

But wrt the algorithm to use in stm32_lpm_if.c, it looks suspicious to me, referencing v1,8.0 code, PWR_EnterStopMode() function will attempt to enter STOP2 even if it fails to get the semaphore, CFG_HW_ENTRY_STOP_MODE_SEMID, and even if the CPU2 says it is busy by LL_PWR_IsActiveFlag_C2DS(). No matter what, the code flows down to invoke LL_PWR_SetPowerMode( LL_PWR_MODE_STOP2 );

It looks like a bug, because if it is always ok to just enter STOP2 on the CPU1, then why keep all of that code pretending to check if it is ok?

Scott Löhr
Senior II

Man-o-man, I am sorry to throw a monkey wrench into this discussion, but running with v1.8.0, it is more simple than you can imagine to get this beast into and out of STOP2. I am running from the HSE xtal, configuring the system clock to use the PLL, and before entering STOP2, I do not manually re-configure the clock for HSI (i.e. calling Switch_On_HSI() is unnecessary) and I do not try to get any of the semaphores shown in the stm32_lpm_if.c code. As I pointed out in a response above, that code looks suspect because regardless of the outcome of checks if STOP2 is ok with CPU2, it enters/attempts STOP2 anyway (and that is what inspired me to just go for it, without all of that rigamarow). Now that being said, it is obvious that this beast puts itself into HSI mode after wake from STOP2, so you do have to reconfig for the clock source and setup that you want for running full speed after STOP2. So its literally 4 lines to get in and out of STOP2:

   LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);

   LL_LPM_EnableDeepSleep();

   __WFI();

   sysClkCfg();

With the function sysClkCfg() implementing whatever clock configuration that you are running with, a subset of the clock initialization stuff that you do at powerup.

Also, of course, as Christophe Arnal (how to mention a community member "in-line" like right here? @Christophe is not doing anything for me using the Microsoft Edge browser) points out above, once at powerup, before starting the CPU2, you need to call LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);

Can anyone confirm my observation of STOP2 simplicity running on the STM32WB Nucleo board and v1.8.0 stm32wb5x_BLE_Stack_full_fw.bin?

Scott Löhr
Senior II

Ok, so just to keep this little conversation with myself going, I'll share a little gotcha with you wrt STOP2 and the IWDG (maybe it didn't/wouldn't get you, but it got me):

Although I configured the IWDG to freeze in STOP by clearing the IWDG_STOP bit in the FLASH_OPTR (a non-trivial effort), I discovered that even as CPU1 is in STOP2 with no reason to wakeup, if the BLE is connected, then apparently by the activity on CPU2, the IWDG continues to run and will reset the board if CPU1 doesn't pet it. I know, I know, it begs the question for you: why does CPU1 not just terminate the BLE connection if there is nothing to do but save battery in STOP2 ... it's a bit of an albatross of a scenario in our system that I would like to not to have to support, but I do.