Skip to main content
Andres Cao
Associate III
November 30, 2017
Question

Huge repetitive LPTIM interrupts

  • November 30, 2017
  • 4 replies
  • 1729 views
Posted on November 30, 2017 at 10:53

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

    This topic has been closed for replies.

    4 replies

    Andres Cao
    Associate III
    November 30, 2017
    Posted on November 30, 2017 at 11:53

    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. 

    Darius B
    Associate II
    January 18, 2018
    Posted on January 18, 2018 at 19:55

    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

    Tesla DeLorean
    Guru
    January 18, 2018
    Posted on January 18, 2018 at 20:29

    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

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Darius B
    Associate II
    January 18, 2018
    Posted on January 18, 2018 at 22:39

    Hi,

    I think that, Andreas have interrupt storm with LPTIM->ISR == 0  !!!

    Possible cause is that  secondary write 

    LPTIM->ARR register.

    BR.

    Darius