cancel
Showing results for 
Search instead for 
Did you mean: 

Strange timer behaviour when CNT is set before first update

akaiser9
Associate II
Posted on October 30, 2009 at 14:23

Strange timer behaviour when CNT is set before first update

3 REPLIES 3
akaiser9
Associate II
Posted on May 17, 2011 at 13:20

When the CNT register of a timer is explicitly set before it has been automatically updated at least once by hitting ARR, the prescaler does not seem to work.

The attached testcase runs on a STM32F103RBT6 in RAM, w/o PLL at 8MHz crystal frequency. The timer 2 is programmed for 50 interrupts per second when counting up to 10000. With prescaler disabled it results in 800 interrupts per second.

With EnableIntAfterUpdate and ResetCounterAfterUpdate flags both cleared, the CNT register is cleared in any CC1 match interrupt. It results in 800 interrupts per second which suggests that the prescaler is not working.

When either EnableIntAfterUpdate or ResetCounterAfterUpdate are set, the first time the CNT register is cleared is deferred until an automatic counter update has been seen as indicated by the SR.UIF flag. It results in 50 interrupts per second, as should be.

I do know that setting CNT in a timer interrupt is not regular practice and adds interrupt latency to the effective interval. Actually this is the result of an analyzation of someone else's experience, so hints on how to do things better do not hit the point.

Compiler is Crossworks 2.01. The code does not depend on library code besides printf, just the CMSIS include files must be present. The compiler optimization level does not change the behaviour and the generated code appears to be correct.

[ This message was edited by: prx on 08-08-2009 19:51 ]

akaiser9
Associate II
Posted on May 17, 2011 at 13:20

Cosmetic fix: Should be

TIM2->DIER = TIM_DIER_CC1IE;

but it's the same value anyway.

akaiser9
Associate II
Posted on May 17, 2011 at 13:20

OK, a little more explanation. Someone had a weird experience with a timer when he cleared the counter register in the interrupt handler. While this is certainly not the best way to handle timers, I have not seen words denying this capability.

So I wrote a small test program. The timer is set up to interrupt on a compare channel match. In the interrupt handler, the timer's counter is explicitly cleared. The prescaler is set to 16-1, so at 8MHz the timer clock should run at 500KHz. With the compare channel set to 10000, an interrupt rate of 50Hz is to be expected.

However that's not what I measured. I got 800Hz, which suggests that the prescaler runs at /1, not at /16.

However when the the first timer interrupt does not clear the counter, the counter runs to the limit and is automatically reset to the programmed values. When this happened at least once, any subsequent clearing of the counter does not affect the prescaler, so in this case the expected 50Hz are seen.

--

It's been some time since and in the meantime I found an explanation for this behavior - you cannot read the manual often enough as is it described in detail. The value actually used by the prescaler is not updated until the first timer update event occurred. Simply writing to PSC does not update the prescaler. Writing to CNT is not an update event, so the value in PSC is never copied to the prescaler. Unless the counter is allowed to run to the limit at least once.

And that's why the library triggers an update event manually as part of the initialization.

[ This message was edited by: prx on 30-10-2009 19:06 ]