STM32F756VGH6 unpredictable basic timer
Hi,
I am at the beginning of my STM32F756VGH6 register programming journey. I have already setup everything, and now I am at the led blink (using a logic analyzer for measuring the time intervals). I decided to make a simple blocking delay function out of a basic timer. The reference manual of STM32F756VGH6 describes the basic timers as really simple and beginner friendly peripheral. I did my best to follow the datasheet and common sense. However, the timer is completely unpredictable right now... Increasing or decreasing the counter prescaler results in some 1.5x or 2.3x incremental steps (prescalers can only by round numbers.) I am not sure is my timer 6 primarily fed with 50 MHz or 100 MHz, because APB1 clock have 2 derivatives, one dedicated only to timer peripherals, so I was going out to find it out by experimenting with the delay value. However, giving the delay function variable of only "1" results in some 6.167 us delay, which is orders of magnitude more than it should be considering even a 50 Mhz clock with the prescaler of 1. Increasing the delay function argument does not make the delay longer proportionally to the increase... I can not find a relation between function variable and the real timer speed. I guess its a beginners mistake and I simply missed something, but at this point I need some help. Thank you in advance. (Code comments explain my core clock setup):
#include "main.h"
void Core_Clock_Setup (void){
RCC->CR |= RCC_CR_HSEON; //Set the clock source to external crystal/resonator (HSE)
while (!(RCC->CR & RCC_CR_HSEON)); //Wait until clock gets stable
RCC->APB1ENR |= RCC_APB1ENR_PWREN; //Enable power interface clock
PWR->CR1 &= ~(1U << 14);
PWR->CR1 &= ~(1U << 15); //Set internal voltage regulator to is reset value (scale 1)
FLASH->ACR &= ~FLASH_ACR_ARTEN; //Disable ART accelerator
FLASH->ACR &= ~FLASH_ACR_ARTRST; //Reset ART accelerator
FLASH->ACR |= FLASH_ACR_PRFTEN; //Enable prefetch
FLASH->ACR |= FLASH_ACR_LATENCY_6WS; //Set 7 CPU clock cycle flash memory access time (in order to get 200 MHz core clock)
//@ 25 MHz crystal, 200 MHz core clock configuration down below
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //Core clock division by 1 (core clock is not devided)
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 Low speed prescaler of 4 (50 MHz, max is 54 Mhz)
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; //APB2 High speed prescaler of 2 (100 MHz, max is 108 Mhz)
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;//HSE is set to be PLL entry
RCC->PLLCFGR |= RCC_PLLCFGR_PLLP_0; //Setting corresponding PLL prescalers (division by 2)
RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_1; //Setting corresponding PLL prescalers (division by 2)
RCC->PLLCFGR &= ~(((1 << (14 - 6 + 1)) - 1) << 6);
RCC->PLLCFGR |= (32 << 6); //Setting corresponding PLL prescalers ( multiplication by 32)
RCC->CR |= RCC_CR_PLLON; //Enable PLL
while (!(RCC->CR & RCC_CR_PLLRDY)); //Wait until PLL gets stable
RCC->CFGR |= RCC_CFGR_SW_PLL; //PLL is set to be core clock
//RCC->CFGR |= RCC_CFGR_SW_HSE; //HSE is set to be core clock
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait until PLL indeed becomes core clock source
}
void GPIO_Setup(void){
RCC->AHB1ENR |= (1 << 4); //Enable clock for GPIO bank E
GPIOE->MODER |= (1 << 8); //Bit 9 is zero (by default), bit 8 is one, resulting in 01 combination which represents the digital output pin mode
GPIOE->OTYPER &= ~(1 << 4); //PE4 configured as push-pull
GPIOE->OSPEEDR |= (1 << 8);
GPIOE->OSPEEDR |= (1 << 9); //PE4 configuration for very high speed ( 1 1 )
}
void Timer_Setup(void){
RCC->APB1ENR |= (1 << 4); //Enable Timer 6 clock
TIM6->PSC = 1; //Timer 6 clock is not devided and is equal to APB1 clock
TIM6->ARR = 0xFFFF; //Auto reload max value of 16 bits (0xFFFF)
TIM6->CR1 |= (1 << 0); //Enable Timer 6 counter
while(!(TIM6->SR & (1<<0))); //Wait until timer update bit is set
}
void delay_us (uint16_t us){
TIM6->CNT = 0;
while (TIM6->CNT < us);
}
int main (void){
Core_Clock_Setup();
Timer_Setup();
GPIO_Setup();
while(1){
GPIOE->BSRR |= (1 << 4);
delay_us(32000);
GPIOE->BSRR |= ((1 << 4) << 16);
delay_us(32000);
}
}
