2017-11-30 01:53 AM
Hi everyone!
I've been recently using the LPTIMER, along with the compare and autoreload interrupts. Microcontroller is an STM32L073.
It has been working fine, mostly, but I realized that if I remove a delay (which used to be a printf to uart) I get thousands of interrupts one after the other.
To be honest I don't see how I could get so many interrupts if flags are being cleared, and what does it have to do with the delay (race condition?).
Let me show you some code:
This is the init function. Default values for autoreload are 1 second (32767) and half of that for the compare.
// Initializes the Low Power Timer with default values. Timer is ready to be used after calling this function.
void lpTim_Init(void){ //Enable clock to the Low Power Timer RCC->APB1ENR |= RCC_APB1ENR_LPTIM1EN;//Settings can only be changed when the LPTIM is disabled
LPTIM1->CR = 0x00000000; //Set the Configuration Register //Encoder mode disabled, Registers updated after write access, normal polarity, //Set-once deactivated, trigger while running is ignored, Software trigger selected, //ext_trig_0 selcted (though ignored), Divide by 1 prescaler, No digital filter for trigger, //No digital filter for external clock, rising edge of clock polarity, use internal clock LPTIM1->CFGR = 0x00000000; //Clear interrupt clear register from previous use LPTIM1->ICR |= 0x3F; //Enable LPTIM. LPTIM ready to start LPTIM1->CR = LPTIM_CR_ENABLE;//Set the autoreload register to its default value.
//Must only be modified when the LPTIM is enabled LPTIM1->ARR = LPTIM_DEFAULT_ARR;//Set compare value
//Must only be modified when the LPTIM is enabled LPTIM1->CMP = LPTIM_DEFAULT_CMP; //Autoreload match and compare interrupt enable LPTIM1->IER = LPTIM_IER_ARRMIE | LPTIM_IER_CMPMIE; //Set the interrupt priority NVIC_SetPriority(LPTIM1_IRQn,0); //Enable interrupt NVIC_EnableIRQ(LPTIM1_IRQn);TRACE_DBG_H('LPTIMER initialized\n');
}And this is my interrupt handler, where I put some pin up/down just to see the interrupts being triggered.
//Interrupt handler
void LPTIM1_IRQHandler(void){ GPIOH->BSRR = GPIO_PIN_0; //If there was an autoreload if(LPTIM1->ISR & LPTIM_ISR_ARRM) { //If the interrupt was enabled if(LPTIM1->IER & LPTIM_IER_ARRMIE) { //Clear interrupt bit LPTIM1->ICR = LPTIM_ICR_ARRMCF; //Timer_OverflowCallback(); } } //If there was a compare match if(LPTIM1->ISR & LPTIM_ISR_CMPM) { //If the interrupt was enabled if(LPTIM1->IER & LPTIM_IER_CMPMIE) { //Clear interrupt bit LPTIM1->ICR = LPTIM_ICR_CMPMCF; //Timer_CompareCallback(); } } GPIOH->BRR = GPIO_PIN_0;}If I do this, it works fine.
void main(void)
{
//Some init..
lpTim_init();
//Start timer
LPTIM1->CR = LPTIM_CR_ENABLE | LPTIM_CR_CNTSTRT;
while(1);
}
If I do this I get a bazilion interrupts one after the other:
void main(void)
{
//Some init..
lpTim_init();
LPTIM1->ARR = 28000; //Random value 28000
//Start timer
LPTIM1->CR = LPTIM_CR_ENABLE | LPTIM_CR_CNTSTRT;
while(1);
}
But if I do this, it works fine again:
void main(void)
{
//Some init..
lpTim_init();
HAL_Delay(1);
LPTIM1->ARR = 28000; //Random value 28000
//Start timer
LPTIM1->CR = LPTIM_CR_ENABLE | LPTIM_CR_CNTSTRT;
while(1);
}
Any clues as to why I might have this behavior? Seems pretty strange to me. Maybe doing LPTIM1->ARR modifications right after interrupt enable ruins everything?
Cheers, and thanks for your help!
Andrés
2017-11-30 02:53 AM
Another thing that I find very curious:
During init I might set the CMP value at 1000. After init I set the value at 2000.
In the interrupt I see the following:
-CNT value is 1000, meaning the interrupt occured at 1000)
-CMP value is 2000, so it seems that the compare value updated but somehow the interrupt is still firing at 1000 forever, it never changes.
2018-01-18 11:29 AM
Likely because there is an interrupt pending that you are not clearing, and it reenters endlessly. ie IRQ storm
Check what's flagging, and make sure it gets cleared.
ie expect (
LPTIM1->ISR &
LPTIM1->IER) != 0
2018-01-18 11:55 AM
Hi.
You must wait flags arrok or cntok when arr or cnt changed. When this flags is set you must clear its. This values changed after long times... 1-2ms.
BR.
Darius
2018-01-18 02:39 PM
Hi,
I think that, Andreas have interrupt storm with LPTIM->ISR == 0 !!!
Possible cause is that secondary write
LPTIM->ARR register.
BR.
Darius