AnsweredAssumed Answered

Huge repetitive LPTIM interrupts

Question asked by Andres Cao on Nov 30, 2017
Latest reply on Jan 18, 2018 by Darius B

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

Outcomes