2020-09-07 07:49 AM
Good Day
I am programming a stm32wb55rg to
start up
Do some ADC sampling
Start up BLE using APPE_Init();
Load all values in characteristic.
And then i sit in loop running:
UTIL_SEQ_Run( UTIL_SEQ_DEFAULT );
After 60 seconds I put device in standby mode. I am happy using standby mode and have device have to reset completely when wakeup. I Use a check on power up to see if device is woken up from standby, NVIC_SystemReset();
The device works great and my standby wakeup is RTC clock for 15 minutes.
I also want to wake up device using wakeup pin 3.
I have a 100k external pull down resistor on this pin.
When I use a bare program wakeup pin works 100%
As soon as i add UTIL_SEQ_Run( UTIL_SEQ_DEFAULT ); to my while loop , wakeup pin does NOT wake up mcu anymore. While RTC wakeup from standby works.
Here is my standby code ,partly taken from standby example:
/-------------------------
/* The Following Wakeup sequence is highly recommended prior to each Standby mode entry
mainly when using more than one wakeup source this is to not miss any wakeup event.
- Disable all used wakeup sources,
- Clear all related wakeup flags,
- Re-enable all used wakeup sources,
- Enter the Standby mode.
*/
/* Disable all used wakeup sources*/
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
/* Clear all related wakeup flags */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, storedValueWakeUpTimer, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); //Set wakeup timer in seconds
if( (LL_PWR_IsActiveFlag_C1SB() == 0) || (LL_PWR_IsActiveFlag_C2SB() == 0))
{
/* Set the lowest low-power mode for CPU2: shutdown mode */
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
}
HAL_GPIO_WritePin(Out_GPIO_Port, Out_Pin,GPIO_PIN_RESET); //pull output CLR pin low again
HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A,PWR_GPIO_BIT_4);
HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A,PWR_GPIO_BIT_6);
HAL_PWREx_EnablePullUpPullDownConfig();
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3_HIGH);
/* Enter the Standby mode */
HAL_PWR_EnterSTANDBYMode(); //standby mode has been triggered by either rotational trigger timer or BLE comms timeout or command from Edge Computer.
//code should never get past this point.
/----------------------------------------------
What am i missing
Solved! Go to Solution.
2020-09-15 08:41 AM
Hello,
Best would be to stop properly the advertizing and to disconnect the link with the dedicated aci_gap_set_non_discoverable() and aci_gap_terminate() command.
Alternatively, it is possible to call aci_hal_stack_reset() but this will suddenly switch off verything and when connected, the remote device will have to wait for a connection timeout to be aware there is no more connection.
Do you have the UTIL_SEQ_Idle() implemented in your code ? If this si the case, just remove it and keep the weak implementation provided in stm32_seq.c.
Once done, you should be back to the same behavior that your bare program.
Regards
2020-09-08 01:19 AM
I have stepped in debug mode and stopped debugger on HAL_PWR_EnterSTANDBYMode();
IT does seem i have everything set up correctly?
PWR-CR3 = Binary:1000010000000100
Bit 15 EIWUL: Enable internal wakeup line for CPU1
1: Internal wakeup line interrupt to CPU1 enabled
Bit 10 APC: Apply pull-up and pull-down configuration from CPU1
Bit 2 EWUP3: Enable Wakeup pin WKUP3 for CPU1
PWR-CR4 = Binary:1000000000000000
it 2 WP3: Wakeup pin WKUP3 polarity
This bit defines the polarity used for an event
0: Detection on high level (rising edge)
2020-09-10 04:35 AM
Further testing shows that if I HOLD pin wkup3 high.
The Device go into standby very briefly and wake up immediately.
wkup3 has a 100k pulldown resistor externally on board.
If that is a clue that anyone can provide some inputs it would be greatly appreciated.
2020-09-14 04:24 AM
Hi All , I'm really hoping someone reads my questions and has some sort of idea even if it seems obvious , please lay it on me.
I have retried this test using wkup5 on a nucleo-wb55 with jumper wire and i get exactly the same results.
RTC wake up works 100% but wkup pins does NOT wake up device.
holding wkup pin high will wake up device immediately.
This code seems a bit weird to me inside utilities_conf.h?
------------------------------------------------------------------------
#define UTILS_ENTER_CRITICAL_SECTION( ) uint32_t primask_bit = __get_PRIMASK( );\
__disable_irq( )
#define UTILS_EXIT_CRITICAL_SECTION( ) __set_PRIMASK( primask_bit )
-----------------------------------------------------------------------
2020-09-14 08:57 AM
Hello,
The Sequencer is a bare metal implementation so it shall not be different than your own bare program. In Addition, the Sequencer has nothing to do with low power mode. It just schedules tasks and goes into Idle when there is nothing to do. The issue should not be there.
Although this has nothing to do with your problem, LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); shall never be called after CPU2 has started or you may collide with the CPU2 low power management. This should be called at startup ( and in all cases before CPU2 is started) is case you plan to enter standby without any use of CPU2.
Regarding the last question
------------------------------------------------------------------------
#define UTILS_ENTER_CRITICAL_SECTION( ) uint32_t primask_bit = __get_PRIMASK( );\
__disable_irq( )
#define UTILS_EXIT_CRITICAL_SECTION( ) __set_PRIMASK( primask_bit )
-----------------------------------------------------------------------
This is required to handle nested critical section
E.g
Fct1()
{
code...;
_disable_irq();
Fct2();
code …;
_enable_irq();
}
Fct2()
{
_disable_irq();
code …;
_enable_irq();
}
In that case, you will get out of critical section on exit from Fct2() whereas Fct1() still expects to be in critical section.
The macro basically store the information whereas the fw is already in critical section or not and restore that context on exit.
Now getting back to you main issue, here is my guess
You likely implemented something like
while(1)
{
UTIL_SEQ_Run( UTIL_SEQ_DEFAULT );
My_Standby_Mode_Entry();
}
I believe in your code , you kept the default implementation of UTIL_SEQ_Idle() that calls UTIL_LPM_EnterLowPower( );
If this is the case, you should move your standby implementation inside stm32_lpm_if.c.
Note that the code provided into PWR_EnterOffMode() and PWR_ExitOffMode() is generic and you may need to remove everything and implement your own code.
When you are entering Standby, do you have BLE activity or did you stop everything. ?
In order to get standby working fine, you mandatory need all CPU2 activity to be stopped.
Regards.
2020-09-14 11:42 AM
Thank you for your help.
"When you are entering Standby, do you have BLE activity or did you stop everything. ?"
The device would still be advertising and could possibly be connected to client when I decide to go into standby.
How do I stop everything?
For the below example my My_Standby_Mode_Entry() code contains code as per my first post.
while(1)
{
UTIL_SEQ_Run( UTIL_SEQ_DEFAULT );
If (60 seconds timer has run out started from wakeup)
{
My_Standby_Mode_Entry();
}
}
My_Standby_Mode_Entry(); contains below:
----------------------------------------------------------------------
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
/* Clear all related wakeup flags */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, storedValueWakeUpTimer, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); //Set wakeup timer in seconds
if( (LL_PWR_IsActiveFlag_C1SB() == 0) || (LL_PWR_IsActiveFlag_C2SB() == 0))
{
/* Set the lowest low-power mode for CPU2: shutdown mode */
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
}
HAL_GPIO_WritePin(Out_GPIO_Port, Out_Pin,GPIO_PIN_RESET); //pull output CLR pin low again
HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A,PWR_GPIO_BIT_4);
HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A,PWR_GPIO_BIT_6);
HAL_PWREx_EnablePullUpPullDownConfig();
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3_HIGH);
/* Enter the Standby mode */
HAL_PWR_EnterSTANDBYMode();
-----------------------------------------------------------------------------
2020-09-15 08:41 AM
Hello,
Best would be to stop properly the advertizing and to disconnect the link with the dedicated aci_gap_set_non_discoverable() and aci_gap_terminate() command.
Alternatively, it is possible to call aci_hal_stack_reset() but this will suddenly switch off verything and when connected, the remote device will have to wait for a connection timeout to be aware there is no more connection.
Do you have the UTIL_SEQ_Idle() implemented in your code ? If this si the case, just remove it and keep the weak implementation provided in stm32_seq.c.
Once done, you should be back to the same behavior that your bare program.
Regards
2020-09-15 10:26 PM
Thank you!
"Best would be to stop properly the advertising and to disconnect the link with"
I implemented my standby code in APP_ble.c after client disconnect and removing restart advertising. This worked and wakeup from wkup3 pin AND RTC worked and not just RTC like before.
This proves the issue was simply that going into standby while busy advertising and possibly connected to client creates this problem.
Thank you for your help and guidance. I will now work on better state machine going into standby mode.
example:
---------
switch (event_pckt->evt)
{
case EVT_DISCONN_COMPLETE:
{
hci_disconnection_complete_event_rp0 *disconnection_complete_event;
disconnection_complete_event = (hci_disconnection_complete_event_rp0 *) event_pckt->data;
if (disconnection_complete_event->Connection_Handle == BleApplicationContext.BleApplicationContext_legacy.connectionHandle)
{
BleApplicationContext.BleApplicationContext_legacy.connectionHandle = 0;
BleApplicationContext.Device_Connection_Status = APP_BLE_IDLE;
APP_DBG_MSG("\r\n\r** DISCONNECTION EVENT WITH CLIENT \n");
}
/* restart advertising */
//Adv_Request(APP_BLE_FAST_ADV); //we do not want to advertise after clean disconnect.
Adv_Cancel();
HAL_GPIO_WritePin(Out_GPIO_Port, Out_Pin,GPIO_PIN_RESET); //pull output CLR pin low again
HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A,PWR_GPIO_BIT_4);
HAL_PWREx_EnableGPIOPullUp(PWR_GPIO_A,PWR_GPIO_BIT_6);
HAL_PWREx_EnablePullUpPullDownConfig();
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN3);
HAL_PWR_EnterSTANDBYMode(); //standby mode
--------------------
"Do you have the UTIL_SEQ_Idle() implemented in your code ?"
I do not implement UTIL_SEQ_Idle() , only UTIL_SEQ_Run( UTIL_SEQ_DEFAULT );
I will probably disable CFG_LPM_SUPPORTED. Since I won't be using those empty routines. They are contstantly getting triggered while BLE is advertising. I understand stop2 mode or higher modes will work well for cpu1 in this case but not really for me.
I have 2 reasons to go into standby mode after ever 15 minutes wakeup.
1: 60 seconds has passed from wakeup.
2: Client has connected and read ADC / FFT measurement data and set shutdown characteristic to 1 and Clean Disconnect.
I use this routine just after HAL_INIT(); to make sure cpu2 starts up correctly:
if((__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) && (__HAL_PWR_GET_FLAG(PWR_FLAG_C2SB) != RESET))
{
/* Clear Standby flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_C2SB);
NVIC_SystemReset(); //we woke up from standby mode. reset so that we are certain cpu2 powers up.
}
2020-09-15 10:33 PM
P.S.
"Although this has nothing to do with your problem, LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); shall never be called after CPU2 has started or you may collide with the CPU2 low power management. This should be called at startup ( and in all cases before CPU2 is started) is case you plan to enter standby without any use of CPU2."
I see now below is implemented in SystemPower_Config in generated code.
/* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
So I have removed this from my code.