Skip to main content
Gpeti
Senior
July 8, 2020
Solved

Behaviour of STM32H743 general purpose timer

  • July 8, 2020
  • 6 replies
  • 2086 views

Hello,

I'm using TIM2 on STM32H743 (Nucleo, rev Y, Keil 5.31).

Just before setting the bit TIM_CR1_EN the setting of the timer is the following:

  • DIER : bit UIE set
  • PSC: expected value (0x4E1F)
  • ARR expected value (0x4E20). it is almost the same as PSC but normal
  • all other registers are 0, including CNT

TIM2 interrupt is enabled. No pending interrupt at this time.

As you can see it is a pretty simple setup.

When I set the bit CEN , I get the first TIM2 interrupt way too quickly (the timer is supposed to trig an update event every 2s).

At this first interrupt the status register is 0x0000001F (bit UIF set + bits CCxIF).

The next interrupts are happening at the correct frequency, around 2s.

I've checked the timer duration using CYCCNT register (and after having set the timer freeze functionality during break). Except for the first interrupt, I indeed measure 800M cycles with CYCCNT (cpu @ 400MHz).

But the first interrupt happens around 40 k cycles after the set of CEN bit.

Any idea ?

This topic has been closed for replies.
Best answer by berendi

PSC is preloaded, so setting it takes effect at the next update event. The first cycle runs effectively with PSC=0, i.e. exactly 0x4e1f+1=20000 times faster as you expect. You can force an update before starting the timer by writing the EGR register, but keep in mind that it causes an update event right then, which you might want to clear before enabling the interrupt, or there is some bit in CR1 that prevents triggering an update interrupt on setting TIM_EGR_UG.

6 replies

berendi
berendiBest answer
Principal
July 8, 2020

PSC is preloaded, so setting it takes effect at the next update event. The first cycle runs effectively with PSC=0, i.e. exactly 0x4e1f+1=20000 times faster as you expect. You can force an update before starting the timer by writing the EGR register, but keep in mind that it causes an update event right then, which you might want to clear before enabling the interrupt, or there is some bit in CR1 that prevents triggering an update interrupt on setting TIM_EGR_UG.

Gpeti
GpetiAuthor
Senior
July 9, 2020

Thank you. I thought the preload was used only when you write PSC while CEN is 1.

berendi
Principal
July 9, 2020

If it sets TIM_EGR_UG but does not clear UIF then it would trigger an interrupt immediately, so the duration between starting the timer and getting the first interrupt would be 0.

It does not matter in the most common use cases, as timer periods would have the same length and interrupts would occur in regular intervals. So it is good enough for HAL.

Gpeti
GpetiAuthor
Senior
July 9, 2020

You're right for the HAL

berendi
Principal
July 9, 2020

The root cause of the weirdness is that PSC is always preloaded. It was a design decision 15+ years ago, and never changed for compatibility reasons. Note that general timer functions are register level compatible across the whole STM32 portfolio and even some 8 bit MCUs.

So we have to live with the fact that setting PSC a multiple step process. Either this (what you actually did)

TIM->PSC = x;
TIM->EGR = TIM_EGR_UG;
while((TIM->SR & TIM_SR_UIF) == 0)
 ;
TIM->SR = ~TIM_SR_UIF;

or

TIM->CR1 |= TIM_CR1_URS;
TIM->PSC = x;
TIM->EGR = TIM_EGR_UG;

would get it done. The first one works only when the update interrupt is not yet enabled, the second one has other side effects, see the description of TIM_CR1_URS in the reference manual.

Setting ARR=0 stops the timer, ARR=1 would generate an update event one cycle later than setting EGR.