cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476 - Entering Shutdown fails once every 300 runs

filippocheein
Associate

System: STM is set to use a PLL fed by MSI. The PLLM is set to 6 and the MSI to 48 MHz.

Issue: When HAL_PWREx_EnterSHUTDOWNMode is executed, the processor should stop executing instructions after this command. Yet occasionally it goes past it indicating it did not successfully enter shutdown mode. This caused the processor to get stuck in an while(1).

Description:

  • Initially the issue was happening once every 100 runs.
  • Following several forum threads and STM32L476 errata section 2.5.13, I was able to come up with this code that lower the chances of the failure to once every 300.
  • Adding a reset if shutdown mode is not entered assured the system does not get stuck in an idle place and enters shutdown mode on the second try. The second try does not fail (according to my testing).

Fix: 

  • reset initial clock so to use MSII as system clock and lower the MSI frequency to 4 MHz per stm errata 2.5.13.
  • Added __DSB() before entering __WFI() 
  • Added reset if shutdown mode was not entered

Was anyone able to have it flawlessly enter shutdown mode on the first try? 

 

 

void HAL_PWREx_EnterSHUTDOWNMode(void)
{
  
  /* Set Shutdown mode */
  MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_SHUTDOWN);
  
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));

/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM)
  __force_stores();
#endif
	
	// @CABAN EDIT: ensure memory synchronization
	__DSB();
	
  /* Request Wait For Interrupt */
  __WFI();
}

 

 

void hal_deepsleep(void)
{
    // @CABAN EDIT: set MSI to f < 16 MHz, per errata document section 2.5.13
    // reset clocks: MSI sysclock, MSI at 4Mhz
	HAL_RCC_DeInit();
	HAL_Delay(1);
	
	// Disable IRQs
	core_util_critical_section_enter();

	// Stop HAL tick
	HAL_SuspendTick();
	uint32_t EnterTimeUS = us_ticker_read();

	// Request to enter SHUTDOWN mode with regulator in low power mode
#if TARGET_STM32L4
	int pwrClockEnabled = __HAL_RCC_PWR_IS_CLK_ENABLED();
	int lowPowerModeEnabled = PWR->CR1 & PWR_CR1_LPR;

	if (!pwrClockEnabled) {
		__HAL_RCC_PWR_CLK_ENABLE();
	}
	if (lowPowerModeEnabled) {
		HAL_PWREx_DisableLowPowerRunMode();
	}

	// @CABAN EDIT: Use STM Shutdown mode for deep sleep.
	// Upon wake up, the system will be subject to a silicon-forced reset.
	// instruction after HAL_PWREx_EnterSHUTDOWNMode shall not be executed.
	HAL_PWREx_EnterSHUTDOWNMode();
	
	/* CPU should not reach this execution point. Reset if CPU get here */
	NVIC_SystemReset();
	
	/* CPU shall not rech this execution point */
	if (lowPowerModeEnabled) {
		HAL_PWREx_EnableLowPowerRunMode();
	}
	if (!pwrClockEnabled) {
		__HAL_RCC_PWR_CLK_DISABLE();
	}
#else /* TARGET_STM32L4 */
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
#endif /* TARGET_STM32L4 */

	// Restart HAL tick
	HAL_ResumeTick();

	// Enable IRQs
	core_util_critical_section_exit();

	// After wake-up from STOP reconfigure the PLL
	SetSysClock();

	TIM_HandleTypeDef TimMasterHandle;
	TimMasterHandle.Instance = TIM_MST;
	__HAL_TIM_SET_COUNTER(&TimMasterHandle, EnterTimeUS);

#if DEVICE_RTC
	/* Wait for RTC RSF bit synchro if RTC is configured */
#if (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7)
	if (READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) {
#else /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */
		if (__HAL_RCC_GET_RTC_SOURCE()) {
#endif  /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */
			rtc_synchronize();
		}
#endif
	}

 

 

 

1 REPLY 1
Piranha
Chief II