cancel
Showing results for 
Search instead for 
Did you mean: 

Leaving Stop 2 Mode on the STM32L4P5 causes hard faults

dcooperch
Associate II

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+) 

 

2 REPLIES 2
Sarra.S
ST Employee

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).

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

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?