cancel
Showing results for 
Search instead for 
Did you mean: 

BLE low power mode STOP2

rbenv.3
Associate II

I'm looking for an AppNote or example showing how to enter STOP2 mode with BLE advertising enabled (low consumption, but BLE advertising). And how to : on any BLE connection, exit from STOP2.

1 ACCEPTED SOLUTION

Accepted Solutions
Alexander1
Associate II

Hi,

glad to hear that.

ad.1. there are also two different modes of advertising. Fast and LowPower advertising.  Adv_Request(APP_BLE_FAST_ADV)//Adv_Request(APP_BLE_LP_ADV) which can come in handy for different tasks or quick reconnections.

ad. 2. I never used anything else as the STM32Cube_FW_WB 1.3.0 and haven't had enough time to check the 1.4.0.

ad. 3. Yeah, they are both awake at that time because of that timer interrupt that was generated for connection or advertising. If there is no Task pending in the scheduler the M4 should be in STOP2 mode quite quickly again.

Yeah you can disable the entry to STOP2 Mode at all times. I did it in my DEBUG config to not lose the connection. You'll gonna waste some energy though... I do not know your application so I also do not know if that is necessary. In my application for example, the Core is only awake when there is work to do. Don't forget to disable the flag again.

I think you can flag this question as answered.

Best Regards.

View solution in original post

6 REPLIES 6
Alexander1
Associate II

Hi,

you can use the integrated lpm module with some extensions. I for myself implemented the STOP2 mode in app_entry.c. Any interrupt will wake the µController again and it will continue until UTIL is idle again. This includes the timer interrupts that the BLE stack uses to advertise or establish a connection.

void UTIL_SEQ_Idle(void)
{
 
#ifdef DEBUG
  return;
#else
 
    /* In case of debugger probe attached, work-around of issue specified in "ES0394 - STM32WB55Cx/Rx/Vx device errata":
     2.2.9 Incomplete Stop 2 mode entry after a wakeup from debug upon EXTI line 48 event
     "With the JTAG debugger enabled on GPIO pins and after a wakeup from debug triggered by an event on EXTI
     line 48 (CDBGPWRUPREQ), the device may enter in a state in which attempts to enter Stop 2 mode are not fully
     effective ..."
     */
    LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
    LL_C2_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
    HAL_SuspendTick();
 
    UTIL_LPM_ENTER_CRITICAL_SECTION( );
 
    PWR_EnterStop2Mode();
      // --> here it stops
    PWR_ExitStop2Mode();
 
    UTIL_LPM_EXIT_CRITICAL_SECTION( );
    /* Configure the system clock for the RUN mode */
    /* Resume Tick interrupt if disabled prior to Low Power Sleep mode entry */
    HAL_ResumeTick();
    return;
#endif
}

You can probably get rid of the HAL_SuspendTick() and HAL_ResumeTick() since the clock is stopped anyway.

void PWR_EnterStop2Mode( void )
{
/* USER CODE BEGIN PWR_EnterStopMode */
  /**
   * This function is called from CRITICAL SECTION
   */
 
  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( ) )
    {
      /* Release ENTRY_STOP_MODE semaphore */
      LL_HSEM_ReleaseLock( HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0 );
 
      /**
       * The switch on HSI before entering Stop Mode is required on Cut2.0
       * It is useless from Cut2.1
       */
      Switch_On_HSI( );
    }
  }
  else
  {
    /**
     * The switch on HSI before entering Stop Mode is required on Cut2.0
     * It is useless from Cut2.1
     */
    Switch_On_HSI( );
  }
 
  /* Release RCC semaphore */
  LL_HSEM_ReleaseLock( HSEM, CFG_HW_RCC_SEMID, 0 );
 
  /************************************************************************************
   * 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 END PWR_EnterStopMode */
}
void PWR_ExitStop2Mode( void )
{
/* USER CODE BEGIN PWR_ExitStopMode */
  /**
   * This function is called from CRITICAL SECTION
   */
 
  /* 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)
  {
    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);
  }
  else
  {
    /**
     * As long as the current application is fine with HSE as system clock source,
     * there is nothing to do here
     */
  }
 
  /* Release RCC semaphore */
  LL_HSEM_ReleaseLock( HSEM, CFG_HW_RCC_SEMID, 0 );
/* USER CODE END PWR_ExitStopMode */
}
static void Switch_On_HSI( void )
{
  LL_RCC_HSI_Enable( );
  while(!LL_RCC_HSI_IsReady( ));
  LL_RCC_SetSysClkSource( LL_RCC_SYS_CLKSOURCE_HSI );
  LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI);
  while (LL_RCC_GetSysClkSource( ) != LL_RCC_SYS_CLKSOURCE_STATUS_HSI);
}

rbenv.3
Associate II

Hi Alexander :

Thank you for your info. I think your answer is exactly what I was missing.

My app is based on "Cable Replacement", today I tested without the BLE (and the C2 = M0+), and my call to STOP2 mode

resulted in approx. 2uA of current.

Activating BLE, I get 7.5mA.

I 'll try your code to put C2 (M0+) in low power and write the results.

rbenv.3
Associate II

Hi,

I tried your suggestion, but get at minimum 1 milliamp of current.

If I don't call " UTIL_SEQ_Run( UTIL_SEQ_DEFAULT ); " on my main loop (BLE not running),

I can put it in STOP2, and current = 2uA (this means my external hardware is not the consumer).

If BLE running, I have about 10mA, and after some time I call your suggested routines, the consumption gets down, but

remains 1mA. BLE advertising, and if I connect, the consumption goes to approx. 5mA (something running again).

Maybe there is some configuration, or some peripheral or oscillator is running.

Alexander1
Associate II

Hi,

so I took some recordings with the STM32CubeMonitor-Power tool.

This is recorded with 100kHz sample rate. The STM32WB is supplied via a step down converter converting 3V3 to 1.8V. The current messurements are taken on the 3V3 side.

  1. Advertising every 2.5seconds without any power down mode:

You can see the advertising events and the base current consumption of both cores is at about 3.5mA at the 3.3V side (should be arround twice that much on the 1.8V side (calculated with a very conservative 90% efficiency ).

0690X00000BwadYQAR.png

2. Advertising: 2.5 seconds with enabled Sleep mode in the same routine as mentioned above:

you can see that the current goes back to almost half the previous value when there is nothing to do.0690X00000BwaevQAB.png

3. Advertising 2.5 seconds with enabled stop 2 mode: This is measured with the debugger disconnected. It draws additional current.

Now the two cores are in stop2 mode consuming only about 6uA on the 3.3V side (my step down regulator has arround 80% efficiency at this point).

0690X00000BwafFQAR.png

0690X00000BwafZQAR.png

4. Establishing a connection with Stop2 mode. Here you can see the current consumption while establishing a connection. Please bear in mind that this changes the interval from advertising interval to connection interval. At the start the interval is usually at arround 50ms which increases your current consumption.

This could explain your higher current as soon as you connect your device.

The 1mA while advertising can be a effect of your current messurement method as well as the use of a short advertising interval.

0690X00000BwadTQAR.png

Yours

Alex

rbenv.3
Associate II

Hi Alex, good news

I get it in STOP2 at low current.

I don't know exactly the current value, I'm using a digital multimeter, and the

display stays varying, but most time showing 0 (zero) (less than 10uA).

  1. advertising interval was 100ms, I changed in app_conf.h
  2. I'm using STM32Cube_FW_WB_V1.2.0, do you see rev 1.3.0. or now 1.4.0 different ?
  3. only now I realized the M4 core gets out of STOP2 each advertising, so I was not prepared to

Do you think is appropriated to include a condition in the function void "UTIL_SEQ_Idle( void )" to only

proceed to STOP2 if my app is free to do so ?

I'm thinking of only enter STOP2 mode after I complete some tasks and wait for a timeout. And also no more enter

STOP2 if someone is connected, testing for a flag generated at app_ble.c (function SVCCTL_App_Notification( void *pckt )),

case EVT_LE_CONN_COMPLETE: myflag = 1;

Best Regards

Alexander1
Associate II

Hi,

glad to hear that.

ad.1. there are also two different modes of advertising. Fast and LowPower advertising.  Adv_Request(APP_BLE_FAST_ADV)//Adv_Request(APP_BLE_LP_ADV) which can come in handy for different tasks or quick reconnections.

ad. 2. I never used anything else as the STM32Cube_FW_WB 1.3.0 and haven't had enough time to check the 1.4.0.

ad. 3. Yeah, they are both awake at that time because of that timer interrupt that was generated for connection or advertising. If there is no Task pending in the scheduler the M4 should be in STOP2 mode quite quickly again.

Yeah you can disable the entry to STOP2 Mode at all times. I did it in my DEBUG config to not lose the connection. You'll gonna waste some energy though... I do not know your application so I also do not know if that is necessary. In my application for example, the Core is only awake when there is work to do. Don't forget to disable the flag again.

I think you can flag this question as answered.

Best Regards.