LPTIM compare interruption sometimes is triggered when it should not
Hi. I am working in a project which involves the use of an STM32L443 microcontroller. I am using the IAR for ARM v 9.30.1 and the CMSIS and ST drivers package (STM32CubeL4 Firmware Package V1.17.1). I am using LL drivers (HAL is not suitable for our needs).
I have configured several timers to interrupt when the counter reaches the compare registers (basically, to have different timeouts to do different tasks). The problem comes when I use a LPTIMx timer. It works as expected, triggering an interruption when the counter register value matches the compare register value programmed. But sometimes, it triggers an interrupt in moments in which the counter register are not close to the compare value.
In order to simplify, I create a simple project to show the problem clearer. It consists in an infinite loop which just have two timers (TIM1 and LPTIM1) running in sleep mode with compare interruptions active. The idea is to initialize the LPTIM1 compare register CMP to make LPTIM1 to interrupt 400ms after that initialization. Immediately after, I initialize the compare register CCR1 in order to make TIM1 to interrupt 350ms after that initialization. The correct behavior should be that TIM1 will interrupt 350ms after those initializations, waking up the microcontroller from sleep mode, toogle the PIN PA7, initialize the timers counters and go to sleep again. So, LPTIM1 should never interrupt, because TIM1 should always "win". The signal in the oscilloscope should be a square signal 350ms in high and 350ms in low. But, the reality is that the oscilloscope shows that square signal but with quick "toggles" in some places. These "quick toggles" are produced because in some occasions, LPTIM1 interrupts immediately the enable_irq() is called. I define two arrays to store the values of the registers inside the LPTIM1_IRQHandler routine, showing that LPTIM1 interrupt occurs having the counter register far from the compare register. I want to say that before enabling the interruptions and entering sleep mode, I clear the LPTIM1 CMP flag and the NVIC pending flag too in order to avoid any pending interruption to occur.
The code of my main function is the following:
int main( void )
{
/* Initialize microcontroller peripherals */
InitPWR();
InitClocks();
InitTIM1( TIM1_FREQ );
InitLPTIM1();
InitPorts();
__disable_irq();
for ( ;; ) {
//Initialize LPTIM Compare register 400ms ahead from the current value of the counter
LL_LPTIM_ClearFlag_CMPOK(LPTIM1);
LL_LPTIM_SetCompare(LPTIM1, static_cast<uint16_t>(LL_LPTIM_GetCounter( LPTIM1 ) + MS_TO_TICKS_LPTIM1( 400 ) + 1));
while ( !LL_LPTIM_IsActiveFlag_CMPOK(LPTIM1) ) {
}
LL_LPTIM_ClearFLAG_CMPM(LPTIM1);
NVIC_ClearPendingIRQ( LPTIM1_IRQn );
//Initialize TIM1 Compare channel 1 register 350ms ahead from the current value of the counter
LL_TIM_OC_SetCompareCH1(TIM1, static_cast<uint16_t>(LL_TIM_GetCounter( TIM1 ) + MS_TO_TICKS_TIM1( 350 ) + 1));
LL_TIM_ClearFlag_CC1(TIM1);
NVIC_ClearPendingIRQ( TIM1_CC_IRQn );
//Enable TIM1 Compare channel 1 interrupt, LPTIM1 Compare interrupt and their corresponding IRQs
LL_TIM_EnableIT_CC1(TIM1);
NVIC_EnableIRQ( TIM1_CC_IRQn );
LL_LPTIM_EnableIT_CMPM( LPTIM1 );
NVIC_EnableIRQ( LPTIM1_IRQn );
/* Enter in sleep mode */
LL_LPM_EnableSleep();
LL_LPM_EnableSleepOnExit();
__enable_irq();
__WFI();
//Disable TIM1 Compare channel 1 interrupt, LPTIM1 Compare interrupt and their corresponding IRQs
LL_TIM_DisableIT_CC1(TIM1);
NVIC_DisableIRQ( TIM1_CC_IRQn );
LL_LPTIM_DisableIT_CMPM( LPTIM1 );
NVIC_DisableIRQ( LPTIM1_IRQn );
LL_GPIO_TogglePin( GPIOA, LL_GPIO_PIN_7 ); /* Trace to see timings in the oscilloscope */
}
}The oscilloscope capture is the following:
I will also attach the project, if anyone want to see the init routines and other stuff.
Thanks in advance for your comments to help me understand if there is something that I am doing wrong or to see if it is a non declared errata of these microcontrollers.
