cancel
Showing results for 
Search instead for 
Did you mean: 

[SOLVED] NUCLEO F207ZG TIM6 timer half speed using CMSIS

ABert.5
Associate II

Hello,

I need to perform some task without using HAL libraries. I am using CMSIS.

To start, I have set up a blinking led with timer.

I programmed the clock as per attached picture. The source clock of TIM6 should be 60 MHz but the led behaves as it were 30 MHz. It blinks at half the speed.

When I expect 500ms delay, the led stays on (or off) 1s. I don't' understand where this factor 2 comes from.

What am I doing wrong?

Here is the code

#include <stdint.h>
#include "stm32f2xx.h"
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
  #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
static void SystemClock_Config();
void TIM6Config (void);
void Delay_us (uint16_t us);
void Delay_ms (uint16_t ms);
 
int main(void)
{
   // uint32_t i;
	SystemClock_Config();
    //NVIC_SetPriority
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
 
    GPIOB->MODER |= 0x01 << GPIO_MODER_MODER14_Pos;
    GPIOB->OSPEEDR |= 0x01 << 29;
 
 
    //uart (not yet implemented, to be completed)
    //ENABLE PORT D AND USART 3
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
    RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
 
    GPIOD->AFR[1] |= (7<<0); //ALTERNATE PD8
    GPIOD->AFR[1] |= (7<<4); //ALTERNATE PD9
 
    GPIOD->OSPEEDR |= (3<<16) | (3<<18); //HIGH SPEED FOR PD8 AND PD9
 
 
	TIM6Config ();
 
	/* Loop forever */
	while(1) {
		GPIOB->ODR ^= GPIO_ODR_ODR_14;
 
		Delay_ms (500);
	}
}
 
static void SystemClock_Config()
{
#define PLL_M_SETTING 8
#define PLL_N_SETTING 240
#define PLL_P_SETTING 0 //PLLP = 2
 
	// Start HSE in Bypass Mode
	RCC->CR |= RCC_CR_HSEBYP;
	RCC->CR |= RCC_CR_HSEON;
	while(!(RCC->CR & RCC_CR_HSERDY));
 
	RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
 
	RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
	RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
 
	RCC->PLLCFGR |= (PLL_M_SETTING << 0) | (PLL_N_SETTING << 6) | (PLL_P_SETTING << 16) | (RCC_PLLCFGR_PLLSRC_HSE);
 
	RCC->CR |= RCC_CR_PLLON;
	while(!(RCC->CR & RCC_CR_PLLRDY));
 
	RCC->CFGR |= RCC_CFGR_SW_PLL;
	while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
 
 
	SystemCoreClockUpdate();
}
void TIM6Config (void)
{
 
// 1. Enable Timer clock
	RCC->APB1ENR |= (1<<4);  // Enable the timer6 clock
 
// 2. Set the prescalar and the ARR
	TIM6->PSC = 60-1;  //   1 MHz ~~ 1 uS delay
	TIM6->ARR = 0xffff;  // MAX ARR value
 
// 3. Enable the Timer, and wait for the update Flag to set
	TIM6->CR1 |= (1<<0); // Enable the Counter
	while (!(TIM6->SR & (1<<0)));  
}
 
void Delay_us (uint16_t us)
{
	TIM6->CNT = 0;
	while (TIM6->CNT < us);
}
 
void Delay_ms (uint16_t ms)
{
	for (uint16_t i=0; i<ms; i++)
	{
		Delay_us (1000); // delay of 1 ms
	}
}

1 ACCEPTED SOLUTION

Accepted Solutions

If in doubts, read out related registers' content and observe.

> RCC->PLLCFGR |= (PLL_M_SETTING << 0) | (PLL_N_SETTING << 6) | (PLL_P_SETTING << 16) | (RCC_PLLCFGR_PLLSRC_HSE);

The default value of RCC->PLLCFGR is not zero, so after this OR it contains something else than you assume.

Also make sure you change FLASH latency before you switch the system clock source.

JW

View solution in original post

5 REPLIES 5

If in doubts, read out related registers' content and observe.

> RCC->PLLCFGR |= (PLL_M_SETTING << 0) | (PLL_N_SETTING << 6) | (PLL_P_SETTING << 16) | (RCC_PLLCFGR_PLLSRC_HSE);

The default value of RCC->PLLCFGR is not zero, so after this OR it contains something else than you assume.

Also make sure you change FLASH latency before you switch the system clock source.

JW

Peter BENSCH
ST Employee

In line 56 you have set

RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

...which sets the APB1 prescaler to /4 and generates an APB1 timer clock of 30MHz. You should set it to:

RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;

...to generate an APB1 timer clock of 60MHz.

Regards

/Peter

In order 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.

@Peter BENSCH​ 

Thank you for your answer.

Did you have a look at the screenshot I attached?

If it is like you say, why the "APB1 timer clocks" is set to 60MHz, with APB1 prescaler set to 4 and not 2? The APB1 peripheral clock is 30, but the timer clocks is 60 Mhz. Why?

Ah, sorry, I read too quickly and assumed an HCLK = 60MHz. Then I keep looking to see if I can find something...

In order 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.

@Community member​ 

well spotted! Thank you!

It works, now, after I added the lines

	RCC->PLLCFGR  &= ~RCC_PLLCFGR_PLLM_Msk;
	RCC->PLLCFGR  &= ~RCC_PLLCFGR_PLLN_Msk;
	RCC->PLLCFGR  &= ~RCC_PLLCFGR_PLLP_Msk;