2025-06-13 9:54 AM
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+)