cancel
Showing results for 
Search instead for 
Did you mean: 

Timer reset using RCC

0xfab
Associate II

The problem: if TIM2 is used prior to my code, then it gets stuck at a certain point, even though all the registers are properly set.

* Here is the configuration of TIM2 registers when it works fine:

(gdb) x/21 $TIM2_BASE
0x40000000: 0x00000001 0x00000000 0x00000000 0x00000003
0x40000010: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000020: 0x00000002 0x00024c10 0x0000059f 0xffffffff
0x40000030: 0x00000000 0x00026e8c 0x00000000 0x00000000
0x40000040: 0x00000000 0x00000000 0x00000000 0x00000001
0x40000050: 0x00000000

where 0x24c10 is the increasing counter, and 0x26e8c the next comparison.

* If I run my code after a bootloader that also uses TIM2, then I get this:

(gdb) x/21 $TIM2_BASE
0x40000000: 0x00000001 0x00000000 0x00000000 0x00000003
0x40000010: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000020: 0x00000002 0x0000249d 0x0000059f 0xffffffff
0x40000030: 0x00000000 0x00004bab 0x00000000 0x00000000
0x40000040: 0x00000000 0x00000000 0x00000000 0x00000001
0x40000050: 0x00000000
It doesn't increase any more, but interestingly, if I disable the Frozen bit in DBGMCU, then it will increase only when the MCU is paused by the debugger.


* At startup of my code (post-bootloader), all registers are null and TIM2 clock is disabled:
(gdb) x/21 $TIM2_BASE
0x40000000: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000010: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000020: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000030: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000040: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000050: 0x00000000
(gdb) x $RCC_BASE + $RCC_APB1ENR
0x40023840: 0x00000000

* Enable TIM2 clock in RCC => registers are non-null, because TIM2 was used beforehand
(gdb) set *(uint32_t*)($RCC_BASE + $RCC_APB1ENR ) = 0x01
(gdb) x/21 $TIM2_BASE
0x40000000: 0x00000001 0x00000000 0x00000000 0x00000002
0x40000010: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000020: 0x00000000 0x005b8da1 0x0000006b 0xffffffff
0x40000030: 0x00000000 0x005b9183 0x00000000 0x00000000
0x40000040: 0x00000000 0x00000000 0x00000000 0x00000001
0x40000050: 0x00000000

* Reset TIM2 via RCC => registers = default values
(gdb) set *(uint32_t*)($RCC_BASE + $RCC_APB1RSTR) = 0x01
(gdb) set *(uint32_t*)($RCC_BASE + $RCC_APB1RSTR) = 0x00
(gdb) x/21 $TIM2_BASE
0x40000000: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000010: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000020: 0x00000000 0x00000000 0x00000000 0xffffffff
0x40000030: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000040: 0x00000000 0x00000000 0x00000000 0x00000000
0x40000050: 0x00000000

* Do the usual configuration -> timer is stuck at 0x249d

(I wondered why register +0x4c (TIMx_DMAR) copies register +0x00 (TIMx_CR1), but the first reply answers it).

In any cases, how am I supposed to reset TIM2 properly so that I can use it again?

4 REPLIES 4

It would help immensely if you'd use some means to display individual register names, e.g. by using the standard CMSIS-mandated device header.

Not all timer registers are visible, viz. preloading. It means, that observing registers alone won't be sufficient to determine the problem. For example, If you set ARR to 0 in a way that it gets active (i.e. either without preload, or with preload and generate an Update), timer stops, and if you then set preload (TIMx_CR1.ARPE=1) and set ARR to 0xFFFF'FFFF, it will show exactly the picture you are presenting to us.

JW

PS. What you say about DMAR is exactly the functionality of DMAR - it's a "window" to (an alias of) other registers, rather than a real register.

Thank you for your answer.

I've edited my message to make it more readable.

Shouldn't those hidden registers be cleaned too by a reset via RCC?
If not, is there any way to start from a fresh configuration?

The code does trigger an update event via the UG bit at the end of the configuration, and the timer indeed starts counting, up to the point where we set the CCR1 register with the next comparison.

After that, the timer counter is stuck, except when the MCU is paused and the Frozen bit not set.

> Shouldn't those hidden registers be cleaned too by a reset via RCC?

They are.

> timer indeed starts counting, up to the point where we set the CCR1 register with the next comparison.

At this point I can only speculate: you are setting that register over and over again in a tight loop, e.g. in interrupt which does not clear its trigger properly thus fires again and again?

Or the method you use to observe the registers' content is incorrect?

This is in your software and/or in your particular setup, so it's up to you to find.

Alternatively, prepare a minimal but complete compilable example which exhibits the problem and post.

JW

The code itself is fine (it works as intended, it's Nuttx by the way, and it simply sets the CC1R a few hundreds counts after the current counter and then idles). There should be an interrupt but obviously it never comes.

Something is clearly not reset properly internally, otherwise there wouldn't be a difference between running the code after a system reset, and running the code after a RCC-reset.

I may try to come up with a reproducible way, if I can get the sources of this bootloader that messes up TIM2.