Skip to main content
issamnnl
Associate
February 13, 2026
Solved

TIM2 CNT restart problem

  • February 13, 2026
  • 2 replies
  • 423 views
Hi,
I am struggling with TIM2 to restart its CNT from zero without using hal.
I am using nucleo-f446
TIM2 clock frequency is 21MHz (no prescaler, 1/4clock division)
CNT set for upcounting.
I want to use TIM2 to write a simple us_delay function, so I need to restart its CNT 
whenever us_delay is called. No matter what I do, I can't make it work, here is the code
I am using:
TMR2_Start = 1; //start counter
TMR2_URS = 1; //Only counter overflow/underflow sets UIF bit
TMR2_UDIS = 1; //disable update event generation
TIM2->ARR = 2100; //set 100us delay (tim2 clock frequency = 21MHz)
TMR2_UDIS = 0; //enable update event generation
TMR2_UG = 0x1; //restart counter
while (TMR2_UIF == 0){ //wait until TMR2_UIF is set
}
I put a breakpoint right before while loop is executed, I can see that CNT is enabled,
URS set, delay value loaded to ARR. However CNT is not reset to zero, it has a random
value, sometimes as high as 0x1A9C, plus the UIF and the Capture/Compare flags are
all set for unknown reasons.
Also, TIM2->CNT = 0 does not help
Best answer by waclawek.jan

Timer keeps running when the program stops at the breakpoint, unless you set the respective bit in freeze register.

JW

2 replies

mƎALLEm
Technical Moderator
February 13, 2026

Hello,

I didn't understand something in your code,

How are you setting/resetting bits with this code in the TIM2 register??:

TMR2_Start = 1; //start counter
TMR2_URS = 1; //Only counter overflow/underflow sets UIF bit
TMR2_UDIS = 1; //disable update event generation
TMR2_UG = 0x1; //restart counter

How you defined these variables?

And why you don't use the registers to directly set/reset the bits (TIM2->register = xx) ?

issamnnl
issamnnlAuthor
Associate
February 13, 2026

Post edited by ST moderator to be inline with the community rules for the code sharing. In next time please use </> button to paste your code and a linker script content. Please read this post: How to insert source code.
I use bitbanding:

#define BitBanding(RegAdr, BitNumber) ((uint32_t *)(((uintptr_t)(&RegAdr)-0x40000000)*0x20+BitNumber*4+0x42000000))

//TMR2

#define TMR2_Start *((volatile unsigned long *) BitBanding(TIM2->CR1, 0)) //tmr2 start bit

#define TMR2_UIF *((volatile unsigned long *) BitBanding(TIM2->SR, 0)) //tmr2 Update interrupt flag

#define TMR2_UG *((volatile unsigned long *) BitBanding(TIM2->EGR, 0)) //tmr2 Update generation

#define TMR2_URS *((volatile unsigned long *) BitBanding(TIM2->CR1, 2)) //tmr2 Update request source

#define TMR2_UDIS *((volatile unsigned long *) BitBanding(TIM2->CR1, 1)) //tmr2 Update disable

#define TMR2_ARPE *((volatile unsigned long *) BitBanding(TIM2->CR1, 7)) //tmr2 Auto-reload preload enable

 

mƎALLEm
Technical Moderator
February 13, 2026

@issamnnl wrote:

I use bitbanding:

 

That's an info that you should provide in your first post.

Try using the registers for now and ensure all is working fine before using bit banding.

In next time please use </> button to share your code.

gbm
Principal
February 13, 2026

1. Stop the timer.

2. Generate update event (no need to reload PSC and ARR every time - might be loaded once).

3. Clear the flags.

4. Start the timer.

BTW. To get 100 us delay, set ARR to 100-1.

issamnnl
issamnnlAuthor
Associate
February 13, 2026

you are right, it should be 99. thanks