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

 

0 REPLIES 0