cancel
Showing results for 
Search instead for 
Did you mean: 

Proper standby mode enter and exit

lprzenioslo
Associate II

Hello,

I am trying to properly implement the standby mode entry routine on an STM32L0 MCU. I have this exemplary minimum working example that does not work as expected:

/* USER CODE BEGIN 2 */
 
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
 
  const char tx1[] = "Application start from RESET \r\n";
  const uint32_t size1 = sizeof tx1;
  const char tx2[] = "Application start from STANBY \r\n";
  const uint32_t size2 = sizeof tx2;
 
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB))
  {
	  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
	  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
 
	  HAL_UART_Transmit(&huart2, (uint8_t*)tx2, size2, 1000);
  }
  else
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)tx1, size1, 1000);
  }
 
  HAL_Delay(1000);
 
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
 
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
 
  /* Enable the WAKEUP PIN */
  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2);
 
  HAL_Delay(1000);
 
  HAL_PWR_EnterSTANDBYMode();
 
  /* USER CODE END 2 */

When I power on the board, in the terminal I can see:

Application start from RESET
Application start from STANBY

The first line is expected, but the second one not. It means that the MCU started, then entered standby mode, reset and finally went to standby mode and stayed there.

Now when I press and release the wake up button I will see:

Application start from STANBY

Which is also expected. The issue occurs when in standby and I issue a reset:

Application start from STANBY
Application start from STANBY

So the application resets somewhere again.

I feel that I am missing something in the configuration/ handling. The expected behavior would be for the application to not reset during the code execution after woken up from standby via reset pin (1 print instead of 2 in the last snippet). I suspect that the reset occurs during the HAL_PWR_EnterSTANDBYMode function call.

I would appreciate all help!

4 REPLIES 4
Piranha
Chief II

On L4 I've found out an undocumented requirement or hardware bug. For PWR peripheral all of the wake-up flags must be cleared after configuring wake-up features. Let's find out if it's true for L0 also!

Hi @Piranha​ , thank you for the answer. I have changed the code the following way:

  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
 
  const char tx1[] = "Application start from RESET \r\n";
  const uint32_t size1 = sizeof tx1;
  const char tx2[] = "Application start from STANBY \r\n";
  const uint32_t size2 = sizeof tx2;
 
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB))
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)tx2, size2, 1000);
  }
  else
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)tx1, size1, 1000);
  }
 
  HAL_Delay(1000);
 
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
 
  HAL_Delay(1000);
 
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_PVDO);
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_VREFINTRDY);
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_VOS);
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_REGLP);
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
 
  /* Enable the WAKEUP PIN */
  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2);
 
  HAL_PWR_EnterSTANDBYMode();

But the MCU still resets "twice" when in standby mode and reset pin is pressed. Do you have any other suggestions?

Line 32 configures wake-up pin. Clearing must be done after that line. By the way, contrary to this HAL monster, with registers such an operation takes a single line of code and is compiled into single store instruction instead of multiple...

lprzenioslo
Associate II

Line 32 configures wake-up pin. Clearing must be done after that line.

Indeed, the code works as expected now! Thank you a lot. But I don't think this is about clearing all flags, but just clearing the WU after the WKUP pin is enabled:

  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
 
  const char tx1[] = "Application start from RESET \r\n";
  const uint32_t size1 = sizeof tx1;
  const char tx2[] = "Application start from STANBY \r\n";
  const uint32_t size2 = sizeof tx2;
 
  if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB))
  {
	  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
	  HAL_UART_Transmit(&huart2, (uint8_t*)tx2, size2, 1000);
  }
  else
  {
	  HAL_UART_Transmit(&huart2, (uint8_t*)tx1, size1, 1000);
  }
 
  HAL_Delay(1000);
 
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
 
  HAL_Delay(1000);
 
  // Enable the WAKEUP PIN
  HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2);
 
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
 
  HAL_PWR_EnterSTANDBYMode();

By the way, contrary to this HAL monster, with registers such an operation takes a single line of code and is compiled into single store instruction instead of multiple...

Yes, this is understandable. Doing it this way has the great advantage of improved code readability. There are no real time requirements there.