Skip to main content
ABert.5
Associate
November 26, 2021
Solved

[SOLVED] NUCLEO F207ZG TIM6 timer half speed using CMSIS

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
	}
}

This topic has been closed for replies.
waclawek.jan
waclawek.janBest answer
Super User
November 26, 2021

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

5 replies

waclawek.jan
waclawek.janBest answer
Super User
November 26, 2021

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

ABert.5
ABert.5Author
Associate
November 26, 2021

@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;

Peter BENSCH
ST Technical Moderator
November 26, 2021

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.
ABert.5
ABert.5Author
Associate
November 26, 2021

@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?

Peter BENSCH
ST Technical Moderator
November 26, 2021

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.