Hello everyone,
I have a problem with WFI instruction and deep sleep mode.Normally everything work correct, but sometimes processor ignore instruction WFI and continue work.
I use ARM Cortex-M0+ (exactly STM32L051), and below is my sleep procedure:
__ASM volatile ("cpsid i" : : : "memory"); // if WKUP pins are already high, the WUF bit will be set PWR->CSR |= PWR_CSR_EWUP2; PWR->CR |= PWR_CR_CWUF | // clear the WUF flag after 2 clock cycles PWR_CR_CSBF | // clear StandBy flag PWR_CR_ULP; // V_{REFINT} is off in low-power mode PWR->CR |= PWR_CR_LPSDSR | // PWR_CR_PDDS; // Enter Standby mode when the CPU enters deepsleep SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode __WFI(); // enter low-power mode while(1) { uprintf("Interrupt loop"); }
I haven't found information on the conditions that must be met before use WFI in deep sleep mode.
In the older version of program yes, I check it in the NVIC_ICPR registry, and sometimes something is there.But I had a problem with disabling reaction NVIC at any interrpupts.
__ASM volatile ("cpsid i" : : : "memory"); SYSCFG->EXTICR[0] = 0; // disable external interrupt prom pin NVIC_DisableIRQ( EXTI2_3_IRQn ); // disable interrupt from pin while(NVIC->ICPR[0]&(1<<EXTI2_3_IRQn)) { Send_USART("Interrupt!"); NVIC->ICPR[0] = 0xFFFFFFFF; // clear all interrupt pending }
In this code loop never ending.
Not sure, but you might have to clear the "active" bit as well.
And, you may need to clear the EXTI pending bit also.
Now I have:
EXTI->IMR = 0; // clear all interrupt mask NVIC_DisableIRQ( EXTI2_3_IRQn ); // disable interrupt from INT pin EXTI->PR |= EXTI_PR_PIF2; // clear interrupt pending flag __disable_irq(); // if WKUP pins are already high, the WUF bit will be set PWR->CSR |= PWR_CSR_EWUP2; PWR->CR |= PWR_CR_CWUF | // clear the WUF flag after 2 clock cycles PWR_CR_CSBF | // clear StandBy flag PWR_CR_ULP; // V_{REFINT} is off in low-power mode PWR->CR |= PWR_CR_LPSDSR | // PWR_CR_PDDS; // Enter Standby mode when the CPU enters deepsleep SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode if(NVIC->ICPR[0]) { Send_USART("Interrupt!->"); USART_unr32(NVIC->ICPR[0]); USART_send( 0x0D ); USART_send( 0x0A ); NVIC->ICPR[0] = 64; USART_send( ' ' ); USART_unr32(NVIC->ICPR[0]); USART_send( 0x0D ); USART_send( 0x0A ); } __WFI(); // enter low-power mode
Now it's working fine, registry NVIC->ICPR[0] newer have penging bits.
I will be watching the operation of the program, but I think that this is the solution to the problem.