cancel
Showing results for 
Search instead for 
Did you mean: 

How to achieve low power Bluetooth advertising with STM32WB

ChrisLB
Associate III

I'm having issues getting the low power sleep to work with Bluetooth enabled on the STM32WB

Is there any guide or app note on steps needed to achieve lowest power level BLE advertising?

Basically no matter what I do - if I enable bluetooth advertising (code extracted from the iBeacon cubemx example) and enter stop2 mode, the stm32 takes about 5.5mA

If I comment out the call to aci_gap_set_discoverable(...) and then enter STOP2 mode, the board goes to ~50uA (most of that is the other hardware we have on this board)

So far, I have:

  • confirmed the main core is indeed going to sleep between bluetooth events (measuring the sleep time = advertising interval, also it's easy to see with the debugger)
  • tried "forcing" sleep with LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2) (my understanding is that I should not need to do this)
  • changing various #defines relating to power, dbg and sleep in the ble header files

I think I might be missing something obvious... Is there any way of seeing why the second core isn't going to sleep? My best guess is that it's a configuration thing but I'm at a loss with what else to try.

Perhaps I need to be using standby mode to force the m0 off between advertising events?

Any help would be greatly appreciated!

Thanks

16 REPLIES 16
Christophe Arnal
ST Employee

​Hello,

You shall never try to force the LOW power mode of CPU2 using any LL_C2_*** API and there is nothing you need to do on CPU1 side to force any CPU2 low power mode.

The CPU2 manage on its own the best low power mode to be applied and the application shall only take care of the CPU1 low power mode n the same way that you would do on any STM32 single core platform.

There are only two exceptions compare to what you would have done on a single core STM32 platform

1/ LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); is called one time at startup in SystemPower_Config() to overwrite the reset value in case you plan to enter low power mode on CPU1 without starting yet CPU2.

2/ The entry/exit of low power mode ( expecially Stop Mode) need to use/check semaphores to handle synchronization with the CPU2.

These algorithm are described in AN5289 rev4 - chapter 4.3 Shared peripherals.

These algorithm are implemented in stm32_lpm_if.c.

Either you are using HSE as system clock and you should use stm32_lpm_if.c. with NO modification and call or you decide to use another system clock. In that case, you just need to update the following piece of code in stm32_lpm_if.c. - PWR_ExitStopMode() according to your need

    LL_RCC_HSE_Enable( );
    while(!LL_RCC_HSE_IsReady( ));
    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
    while (LL_RCC_GetSysClkSource( ) != LL_RCC_SYS_CLKSOURCE_STATUS_HSE);

Regards.

ChrisLB
Associate III

Thanks for this, really useful to get definitive answers!

I believe however I am already doing everything you describe:

1) SystemPower_Config() in app_entry.c

  LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
  UTIL_LPM_Init();
  /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
  LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);

2) I have left the PWR_EnterStopMode() & PWR_ExitStopMode() unchanged (we are using HSE)

EnterStopMode (comments removed for upload):

 HAL_SuspendTick();
  while( LL_HSEM_1StepLock( HSEM, CFG_HW_RCC_SEMID ) );
  if ( ! LL_HSEM_1StepLock( HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID ) )
  {
    if( LL_PWR_IsActiveFlag_C2DS( ) )
    {
      LL_HSEM_ReleaseLock( HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0 );
      Switch_On_HSI( );
    }
  }
  else
  {
       Switch_On_HSI( );
  }
 
  LL_HSEM_ReleaseLock( HSEM, CFG_HW_RCC_SEMID, 0 );
 
 
  LL_PWR_SetPowerMode( LL_PWR_MODE_STOP2 );
  LL_LPM_EnableDeepSleep( ); /**< Set SLEEPDEEP bit of Cortex System Control Register */
 
  __WFI();

Is there any way of seeing why the second core isnt going to sleep on its own? Maybe it's something to do with the debugger interface? I am able to attach the debugger and wake the device from sleep which I was not expecting given my configuration

ChrisLB
Associate III

Follow up thought... is it possible I'm wrong in saying that C1 is definitely asleep? I've assumed that the time spent inside _WFI() = sleep time, but maybe that's not the case? Is there anything that C2 would do that would keep C1 from sleeping? (I dont mean can c2 wake up c1- that is very clearly the case - but actually is there anything preventing sleep)

​Hello,

No, I do not see how C2 could prevent C1 going to sleep mode.

You may toggle GPIO before and after UTIL_LPM_EnterLowPower() in UTIL_SEQ_Idle() to check if C1 enters sleep mode. You will need a digital analyser to check the GPIOs.

Regards

​Hello,

As long as you are able to enter Stop Mode 2 when commenting out aci_gap_set_discoverable(), I am wondering if you just did not crash the CPU2 which would explain in some way in stays in run mode. 5.5mA means likely both CPU2 and BLE IP Core are in run mode (provided CPU1 is in sleep)

Although it burns 5.5mA, does the product works properly ?

Alternatively, I would load the p2p_server example as provided and check how much power you are measuring to make sure your tooling is fine. p2p_server is first advertising for 60s and then it stops.

In order to get some insigth of what is currently doing the CPU2 and provided you have a digital analyser, you may refer to AN5289 rev4 chapter 4.8 where it is described it is possible to monitor most real time activity on CPU2.

Everything is configured from app_debug.c.

Regards.

So I've continued experimenting and changed all clock settings to match the example and added a call to APPD_init() to APPE_init() (copied from beacon example, not present in generated code) and it is now taking ~3mA and is advertising correctly.

If I comment out the aci_gap_set_discoverable now, but leave APPE_Init the processor takes about 2.7mA, which I think indicates advertising is taking roughly the amount of power I would expect, but we still have that confusing baseline consumption

I tried the p2p_server previously with no change (ie it worked but still high consumption) but will retry. I had also tried the heartrate and beacon profiles, all with same results.

The biggest clue I've found so far is that when I have CPU2 on, the debugger never detaches, despite setting DBGMCU->CR = 0 and C1 being put into stop2 mode. If I comment out all ble code (APPE_init and scheduler loop) and set C2 into shutdown mode, the debugger detaches as expected.

Not sure if any of this helps narrow down the problem. Thanks for the monitoring tip from AN5289 - I'll get hold of an analyser and see what I can do

Your point about crashing C2 seems feasible too. When experimenting, I often have to disconnect and reconnect power on the board to get advertising to work again. When "crashed", the power consumption is still the same (3mA) but no advertising occurs.

I'm using the RTC timer to count time in sleep mode - I think this works too? Effectively read the RTC counter before and after EnterLowPower and print the difference.

Interestingly sometimes the core wakes up at the advertising interval, sometimes using the RTC Wakup timer (5000ms) I'm using. I'm sure this comes down to my interrupt configuration (I've tried a lot of different code examples..) but as far as I can tell it does not matter (in that waking every 5s does not prevent C2 from advertising at 1000ms interval)

Mathieu Wernsen
Associate II

Hi there,

@ChrisLB Did you ever manage to find a solution to this problem? I've been running into the exact same issue where calling aci_gap_set_discoverable(..) results in the CPU2 not returning to LPM when needed (i.e. after a call to aci_hal_stack_reset()). I believe this then prevents CPU1 from also entering Standby/Shutdown mode and unexpected high power consumption (5.5mA)

When not having called aci_gap_set_discoverable(), CPU2 nicely returns to Deepsleep mode (checked using PWR_EXTSCR_C2DS), after resettinng the ble stack (aci_hal_stack_reset). Measured power consumption is then 20 uA (Ok considering peripherals).

Hope you can help me out!

ChrisLB
Associate III

Hi Mathieu,

Sorry this is now so long ago that I can't really give you a complete answer, but I do remember it was a bug in the chip. Something totally unrelated and many many steps to ensure everything was just right.

From what I can remember:

  • be very careful with your debugger and settings (debug sleep enable causes higher power consumption, sometimes. Sometimes with it disabled but booting up with debugger I had 0.9ma. I always power cycled with debugger disconnected before testing). You can get it to work, it's just unreliable at best (using segger Jlink plus with ozone at least)
  • ADC clock needs to be disabled in sleep. Don't ask me why..
  • make sure your calls to the sequencer are running reliably (that loop is critical to getting CPU2 to do what it's supposed to)
  • test out disabling core 2 fully. In my case sending powerdown to C2 still didnt solve my problems reliably

Essentially, I never figured out if it was actually a core 2 / bluetooth issue, or more of a total system issue. Seemed to be something with shared clock signals, but once I got it working I didnt really look back!