Skip to main content
issamnnl
Associate
February 13, 2026
Solved

TIM2 CNT restart problem

  • February 13, 2026
  • 2 replies
  • 329 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) ?

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
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.

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
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.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
issamnnl
issamnnlAuthor
Associate
February 13, 2026

you are right, it should be 99. thanks