Skip to main content
Visitor II
January 15, 2018
Question

Premature TIM2 interrupt happening immediately on timer start

  • January 15, 2018
  • 2 replies
  • 3490 views
Posted on January 15, 2018 at 19:53

Hi folks,

I'm having an issue with the TIM2 interrupt firing as soon as I start the timer rather than when the timer overflows -- was hoping someone could help me. I've set up TIM2 to interrupt once every 860 milliseconds or so, but am finding that the timer immediately interrupts about 75 microseconds after I activate it. I'm using the ST peripheral driver library for the STM8S on the STM8s Value Line Discovery board with IAR as the compiler.

Initialization code (slightly modified for clarity):

Note, timer_period = 836

void timebase_init(uint16_t timer_period)

{

/* Set the step time

TIM2 Clock = 16 Mhz

TIM2 Prescaler = 16384

TIM2 Counter Clock = 16 MHz / 16384 = 967 Hz

TIM2 Period range = 0.001 sec - 1 sec

*/

GPIO_WriteLow(GPIOD, GPIO_PIN_2); // For testing with logic analyzer

TIM2_DeInit();

TIM2_TimeBaseInit( TIM2_PRESCALER_16384, timer_period);

TIM2_ITConfig( TIM2_IT_UPDATE, ENABLE );

TIM2_Cmd( ENABLE );

}

Interrupt handler from stm8s_it.c:

INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)

{

GPIO_WriteHigh(GPIOD, GPIO_PIN_2);

time_event(); // User app function - change displayed value

GPIO_WriteLow(GPIOD, GPIO_PIN_2);

}

/* Clear Interrupt Pending bit */

TIM2_ClearITPendingBit(TIM2_IT_UPDATE);

}

I've set up the interrupt handler to toggle a debug pin when it runs. The timer period is set up for approx. 0.86 seconds, however the interrupt happens 75 microseconds after I enter the function that sets up the timer:

After this, it happens every 0.86 seconds as expected (can't see the above pulse in the following image, which is zoomed out a lot):

If I put a breakpoint on the entry to the interrupt handler, the first time it hits (the undesired interrupt), IAR reports the TIM2 registers as this:

I've seen a couple references saying the timer update will cause an interrupt when you change some of the timer's registers, but it seem silly to me that if you set a timer it goes off as soon as you press start rather than at the time you've set the timer for.

Thanks for any help or insight!

    This topic has been closed for replies.

    2 replies

    Visitor II
    January 16, 2018
    Posted on January 16, 2018 at 07:08

    The ST timers 'update events' include overflow, but can be other things too (timer register initialization for example, when you 'update' the ARR as an example).

    That's the way it is about st timers.

    Regarding your code, what is the ARR (auto reload register)? Seems that you use the default, 0x0000, and in that case the timer will start with an update (Remember that the timers are auto-reload on overflow, the overflow 'update' event is when the timer roll-over to zero from ARR. The timer counts as that: 0,1,2,3,4,5,6,0,1,2,... (ARR=6). Overflow update event is at 0).

    I must say here that I'm not using the ST hal library (or whatever it's name is). Why you don't work with registers directly? It's such a simple chip... The hal library is just hiding the information from you. In the end you may be forced to read the manual/datasheets anyway, and you will have a hard time mapping the hal library to the manual. Think of that: why in the manual all the stories are with registers and NOT the hal library functions? I have a rule of thumb: I will use a chip vendor hal library when the manual/datasheet will include clear use of it along with the hardware register normal documentation....

    Visitor II
    January 17, 2018
    Posted on January 17, 2018 at 00:47

    Hi dragomir.raimond, and thanks for the reply. The value of ARR set by to 0xFFFF by TIM2_Deinit(); it is then changed to (a value of approximately)  0x0344 by

    TIM2_TimeBaseInit() before the timer it started:

    void TIM2_DeInit(void)

    {

      TIM2->CR1 = (uint8_t)TIM2_CR1_RESET_VALUE;

      TIM2->IER = (uint8_t)TIM2_IER_RESET_VALUE;

    ...

      TIM2->ARRH  = (uint8_t)TIM2_ARRH_RESET_VALUE;

      TIM2->ARRL  = (uint8_t)TIM2_ARRL_RESET_VALUE;

    ...

    }

     

    void TIM2_TimeBaseInit( TIM2_Prescaler_TypeDef TIM2_Prescaler,

                            uint16_t TIM2_Period)

    {

      /* Set the Prescaler value */

      TIM2->PSCR = (uint8_t)(TIM2_Prescaler);

      /* Set the Autoreload value */

      TIM2->ARRH = (uint8_t)(TIM2_Period >> 8);

      TIM2->ARRL = (uint8_t)(TIM2_Period);

    }

    I have tried clearing the TIM2->SR1 update bit (0x01) immediately before TIM2_Cmd() activates the timer by setting TIM2->CR1's CEN bit as I figured that should block any interrupts due to the preceding setup. It doesn't help though -- I still get that immediate interrupt.

    > Why you don't work with registers directly? 

    This is a one-off project for an external customer and may be the only time I use an STM8; I was using ST's HAL library to expedite the development as I don't have any other STM8-based projects coming up and didn't want to spend too much time poring over register definitions as the whole software development time was only around a week. 

    At the moment I've just used a static bool in the interrupt handler to ignore the first time it runs, but I wanted a better way.

    Thanks again,

    Todd

    Visitor II
    January 17, 2018
    Posted on January 17, 2018 at 07:11

    That's always an unfortunate situation, and it's hard to say what is better to do

    Anyway, probably you are in this situation: The first ARR counts are on the default prescaler which is just /1

    That will be quite close to your measurement (836 counts * 0.0625ns = 52us). The prescaler will get your desired value (16384) at the 'next' update event, in your case just the first one.

    Quote from the user manual:

    'The prescaler value is loaded through a preload register. The shadow register, which

    contains the current value to be used is loaded as soon as the LS Byte has been written.

    The new prescaler value is taken into account in the following period (after the next counter

    update event).'
    Visitor II
    January 16, 2018
    Posted on January 16, 2018 at 20:40

    I  encountered the same problem with Timer2 interrupt. So I ignore the first interrupt in my application and clear the TIM2_SR1 for the next interrupt.

    Visitor II
    January 17, 2018
    Posted on January 17, 2018 at 00:48

    That's what I'm doing at the moment, but I'm tying up RAM with a static bool in the ISR that I have to check each time it runs... it's fine, I suppose, but I was hoping to get away from that. 

    Thanks!

    Todd