Skip to main content
Explorer II
June 13, 2025
Question

Leaving Stop 2 Mode on the STM32L4P5 causes hard faults

  • June 13, 2025
  • 1 reply
  • 308 views

I have been trying to figure out why I keep getting consistent hard faults when trying to access peripheral instances after waking from Stop Mode 2.  Here is the code I am using

For entering stop mode:

static void SystemClockConfig_STOP(void)
{
 /* A) Ensure V_CORE supports 120 MHz again */
 HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);

 /* B) FLASH: raise latency before any SYSCLK jump */
 __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_5);
 while (__HAL_FLASH_GET_LATENCY() != FLASH_LATENCY_5) {}

 /* C) Handle AHB overshoot if needed */
 if ((RCC->CFGR & RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1) {
 MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
 }

 /* D) Bring HSE & PLL back */
 __HAL_RCC_HSE_CONFIG(RCC_HSE_ON);
 while (!__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY)) {}
 __HAL_RCC_PLL_ENABLE();
 while (!__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY)) {}

 /* E) Switch to PLL */
 MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_SYSCLKSOURCE_PLLCLK);
 while ((__HAL_RCC_GET_SYSCLK_SOURCE() & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {}

 /* F) Restore AHB prescaler = /1 */
 MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1);

 /* G) Restore APB1 & APB2 = /1 */
 MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV1);
 MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_HCLK_DIV1 << 3);

 /* H) Re-init the HAL tick if used */
 HAL_InitTick(uwTickPrio);
}


void stop_mode_test()
{
	HAL_SuspendTick();
	__disable_irq();
	
	__HAL_TIM_DISABLE(&htim2);
	__HAL_TIM_DISABLE(&htim3);
	__HAL_TIM_DISABLE(&htim16);
	__HAL_TIM_DISABLE(&htim7);

	__HAL_SPI_DISABLE(&hspi1);
	__HAL_SPI_DISABLE(&hspi2);
	__HAL_DMA_DISABLE(&hdma_spi1_rx);
	__HAL_DMA_DISABLE(&hdma_spi1_tx);
	__HAL_DMA_DISABLE(&hdma_spi2_rx);
	__HAL_DMA_DISABLE(&hdma_spi2_tx);

	__HAL_RCC_SDMMC1_CLK_DISABLE(); 
	__HAL_RCC_TIM2_CLK_DISABLE();
	__HAL_RCC_TIM3_CLK_DISABLE();
	__HAL_RCC_TIM16_CLK_DISABLE();
	__HAL_RCC_TIM7_CLK_DISABLE(); 
	__HAL_RCC_SPI1_CLK_DISABLE();
	__HAL_RCC_SPI2_CLK_DISABLE();
	__HAL_RCC_DMA1_CLK_DISABLE();
	
	/* clear any stale wake‐event on EXTI2 */
	__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_2);
	HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFE);

	SystemClockConfig_STOP();
	
	__HAL_RCC_TIM2_CLK_ENABLE();
	__HAL_RCC_TIM3_CLK_ENABLE();
	__HAL_RCC_TIM16_CLK_ENABLE();
	__HAL_RCC_TIM7_CLK_ENABLE(); 

	__HAL_RCC_SPI1_CLK_ENABLE();
	__HAL_RCC_SPI2_CLK_ENABLE();

	__HAL_RCC_DMA1_CLK_ENABLE(); 
	__HAL_RCC_SDMMC1_CLK_ENABLE();
	
	__HAL_TIM_ENABLE(&htim2);
	__HAL_TIM_ENABLE(&htim3); // <----- HARD FAULT HERE (recorded the sp in TAMP since I cannot get here with the debugger)
	__HAL_TIM_ENABLE(&htim16);
	__HAL_TIM_ENABLE(&htim7); 

	__HAL_SPI_ENABLE(&hspi1);
	__HAL_SPI_ENABLE(&hspi2);

	__HAL_DMA_ENABLE(&hdma_spi1_rx);
	__HAL_DMA_ENABLE(&hdma_spi1_tx);
	__HAL_DMA_ENABLE(&hdma_spi2_rx);
	__HAL_DMA_ENABLE(&hdma_spi2_tx);
	
	HAL_ResumeTick();
	__enable_irq();
}

If I change the code like this:

 if (IS_TIM_INSTANCE(htim3.Instance))
 __HAL_TIM_ENABLE(&htim3);

Then the hard fault does not occur until here:

 __HAL_DMA_ENABLE(&hdma_spi1_rx);
 __HAL_DMA_ENABLE(&hdma_spi1_tx);
 __HAL_DMA_ENABLE(&hdma_spi2_rx); //<---- HARD FAULT HERE
 __HAL_DMA_ENABLE(&hdma_spi2_tx);

which suggests corruption.

At first I thought the faults were due to clock gating or HSE instability, etc, but I can't seem to find any evidence of this.  Unfortunately, this issue does not occur with the debugger attached.  Which make it very hard to troubleshoot.  I have also simply tried this code without any peripheral enabling/disabling like this:

HAL_SuspendTick();
__disable_irq();
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_2);
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFE);
HAL_ResumeTick();
__enable_irq();

but I end up getting faults the first time a peripheral instance is accessed somewhere later in the code.  The only way I can successfully use a Stop mode is to simply reset the MCU:

HAL_SuspendTick();
__disable_irq();
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_2);
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFE);
HAL_ResumeTick();
__enable_irq();
HAL_NVIC_SystemReset();

I want to find a way to recover from stop mode without the MCU reset.  I can confirm the stop mode is working by measure the current, but I must reset the MCU to avoid hard faults.  

 

I am using an 8 MHz ceramic crystal and HSE. and running my clock at 120MHz (STM32L4+) 

 

    This topic has been closed for replies.

    1 reply

    ST Employee
    June 16, 2025

    Hello @dcooperch

    This is a known erratum, check ES0510 section 2.2.7: 

    when debug in low-power mode is enabled, the STM32L4+ may fetch incorrect instructions from flash memory after waking up from Stop Mode 2. This can lead to unpredictable behavior or a CPU exception (hard fault). The conditions for this issue are:

    • At least one of the DBG_SLEEP or DBG_STOP bits in the DBGMCU_CR register is set.
    • Interrupts with wakeup capability are disabled at Sleep or Stop entry.
    • The flash memory interface gating is enabled by clearing the FLASHSMEN bit of the RCC_AHB1SMENR register (only for Sleep mode)

    Workaround

    * Add an ISB just after WFI (or WFE) instruction.
    * Disable the flash memory interface gating, by setting FLASHSMEN bit (valid only for Sleep mode).

    dcooperchAuthor
    Explorer II
    June 23, 2025

    It turns out that SRAM3 is turned off by default.  I had to make sure SRAM3 stays on before going to sleep.  It looks like this only affects the L4+ line?