STM32F303CC TIM2 needs a counter overflow before ARR match
Hi and happy new year,
Migrating from STM32F103 to STM32F303, I mostly copy&paste my code from STM32103 to STM32F303, and only adjust what's necessary. However, I am having troubles with the TIM2 peripheral. Before starting the counter, the CNT register shows the correct reset value of 0x0000. My ARR register is set to 499. When I start the timer, I do not enter my ISR. When I halt the program, I see that the counter has incremented far beyond my ARR value (11052779 when I halted the program). The ISR was not entered between CNT=0 and CNT=11052779).
When I let the program run for a while (couple of minutes), the counter keeps incrementing until an overflow occurs (counter value > 2^32), starting from 0 again. When this happens, I enter the ISR, service it and leave the ISR again. Then, my ISR gets entered every 500ms, as supposed.
Can anyone tell me, why the counter misses the first ARR, needs to go all the way up to 2^32, overflows, and then matches the ARR regularly in the required 500ms intervals? Comparing the ref manuals of these two microcontrollers, the only difference I notice is that TIM2 on the F303 is a 32bit counter.
To answer the question where the 500ms might come from:
I use internal 8MHz clock and a prescaler of 7999. This gives a counter frequency of 8MHz/(7999+1) = 1000. This yields a 1ms timer increment. Counting to 499 gives 500ms.
/**
* STM32F303CC General Purpose Timer
* Uses TIM2_CH2 (PA1): Triggers every 500ms and toggles an LED on PC13
* OC2M configuration: 000 Frozen Comparison between CCR2 and CNT does not affect OC2REF
*/
#include <stdint.h>
#include "stm32f3xx.h"
int main(void)
{
__NVIC_EnableIRQ(TIM2_IRQn);
// Check which bus PC13 sits on
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
uint8_t i = 0;
for(;i<255;i++);
i=0;
GPIOC->MODER |= GPIO_MODER_MODER13_0;
// Enables TIM2 bus
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
for(;i<255;i++);
i=0;
TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_URS;
TIM2->DIER |= TIM_DIER_UIE;
TIM2->PSC = 7999;
TIM2->ARR = 499;
TIM2->CR1 |= TIM_CR1_CEN;
/* Loop forever */
for(;;);
}
void TIM2_IRQHandler(void)
{
static char flag = 0;
TIM2->SR &= ~TIM_SR_UIF;
if(flag)
{
GPIOC->BSRR = GPIO_BSRR_BR_13;
flag = 0;
}
else
{
GPIOC->BSRR = GPIO_BSRR_BS_13;
flag = 1;
}
}