cancel
Showing results for 
Search instead for 
Did you mean: 

Hard Fault after exiting Low Power Sleep Mode

Brigei
Associate III

Hi,

I'm using a STM32L031. When I'm entering the low power sleep mode und an interrupt occurs i'm getting a hard fault. The programm counter from the stack frame has ether the value 0x00000000 or is pointing at the __ISB after the __WFI - depending on the version i'm using. At the beginning i was using Enter_LP_Sleep1() getting 0x00000000. Then i found a blog discussion where they described the entering procedure of version Enter_LP_Sleep2(). This worked for my project and i thought the problem was solved. Unfortunately every now and then i got the problem with the hard fault again (depending on temperature?!). Now I stripped the code down to the following where i always get the hard fault.

int main(void){
	FLASH->ACR |= FLASH_ACR_PRFTEN;
	RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
	RCC->APB1ENR |= RCC_APB1ENR_PWREN;
	RCC->APB1SMENR = 0;
	RCC->APB2SMENR = 0;
	RCC->APB2SMENR |= RCC_APB2SMENR_TIM22SMEN; 
	RCC->APB1SMENR |= RCC_APB1SMENR_PWRSMEN;
	RCC->APB2SMENR |= RCC_APB2SMENR_SYSCFGSMEN;
	RCC->APB2SMENR |= RCC_APB2SMENR_DBGSMEN;
	RCC->APB1SMENR |= RCC_APB1SMENR_LPTIM1SMEN;
	RCC->APB1SMENR |= RCC_APB1SMENR_WWDGSMEN;
	RCC->CSR |= RCC_CSR_LSION;
	while(!(RCC->CSR & RCC_CSR_LSIRDY));
	RCC->CCIPR |= RCC_CCIPR_LPTIM1SEL_0;
	RCC->APB1ENR |= RCC_APB1ENR_LPTIM1EN;
	NVIC_EnableIRQ(LPTIM1_IRQn);
	NVIC_SetPriority(LPTIM1_IRQn, 3);
	LPTIM1->CFGR |= 0b101 << 9;
	LPTIM1->IER |= 0b11;
	LPTIM1->CR |= LPTIM_CR_ENABLE;
	LPTIM1->ARR = (1156.25 / 1000)*(1500);
	LPTIM1->CMP = (1156.25 / 1000)*1000;
	LPTIM1->CR |= LPTIM_CR_SNGSTRT;

	Enter_LP_Sleep1();    // or Enter_LP_Sleep2();
	while(1);
}

void Enter_LP_Sleep1(){
	SCB->SCR     &= ~SCB_SCR_SLEEPDEEP_Msk;
	FLASH->ACR   &= ~FLASH_ACR_SLEEP_PD;
	PWR->CR      &= ~PWR_CR_ULP;
	PWR->CR      |= PWR_CR_CWUF;
	while (FLASH->SR & FLASH_SR_BSY) {}
	PWR->CR |= PWR_CR_LPSDSR;
	__WFI();
	status_blockade = 0;
}

void Enter_LP_Sleep2(){
	SCB->SCR     &= ~SCB_SCR_SLEEPDEEP_Msk;
	FLASH->ACR   &= ~FLASH_ACR_SLEEP_PD;
	PWR->CR      &= ~PWR_CR_ULP;
	PWR->CR      |= PWR_CR_CWUF;
	while (FLASH->SR & FLASH_SR_BSY) {}
	PWR->CR |= PWR_CR_LPSDSR;
	__disable_irq();
	__DSB();
	__WFI();
	asm ("nop");
	__ISB();
	__enable_irq();
	status_blockade = 0;
}

 Thanks in advance!

Greetings from Salzburg / Austria

13 REPLIES 13
Brigei
Associate III

I also tried the Enter_LP_Sleep functions as RAM functions with the attribute __attribute__((section(".RamFunc"))) but it didn't work neather.

As a supplement, the missing ISR from the Low Power Timer.

void LPTIM1_IRQHandler(void) {
	if(LPTIM1->ISR & 0b1){
		LPTIM1->ICR = 0b1;
	}
	else{
		LPTIM1->ICR = 0b1 << 1;
	}
}

 

 

Check FLASH wait states.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hi,

wait state is 0 but i just use MSI with 2 MHz, so this should be ok?!

KnarfB
Super User

Do you have more details about the hard fault, e.g from a fault analyzer or following Cortex-M Fault - SEGGER Knowledge Base

hth

KnarfB

Because it's a Cortex M0 i don't have a lot of Hard Fault information (or do i?). I get the following from the debug window.Bildschirmfoto 2025-08-19 um 22.02.35.png

What says the Fault Analyzer tab next to the Debug tab?

Just „Hard Fault Detected“, nothing else. And the Adress 0x20001fd0 at the bottom right is the one from the MSP. So the Stack Frame is:

  • r0 - 0x20000000
  • r1 - 0x20000004
  • r2 - 0x00000000
  • r3 - 0x00000003
  • r12 - 0x00000003
  • LR - 0x0D000000
  • PC - 0x2000005E --> _ISB();
  • xPSR - 0x01000000 --> Thumb bit

Then do it "manually", by opening the SCB peripheral in the debugger, and note the fault register values.
Worst case (your debugger has no such feature) look up the register addresses in the reference manual, and check the respective memory locations.

Are there any for the Cortex M0? I read there aren‘t.

Bildschirmfoto 2025-08-20 um 07.28.37.png