Skip to main content
Associate II
July 16, 2024
Solved

STM32F4 clock configuration using register programming

  • July 16, 2024
  • 2 replies
  • 2417 views

I am trying to change the system clock on my STM32F410RB using register programming. I have setup an SPI protocol to an external DAC IC which needs a minimum of 100ns (10MHz) clock period. The SPI allows for a maximum of 8MHz (fPCLK/2) at default clock settings.

I cooked up a little code but it doesn't seem to work as expected. When I probe the SCK, all I get is a constant DC type plot or a noisy output. Here is the code:

 

void set_new_system_clock(void)
{
	RCC->PLLCFGR &=~(1U<<22);

	RCC->PLLCFGR &=~(1U<<0);
	RCC->PLLCFGR &=~(1U<<1);
	RCC->PLLCFGR &=~(1U<<2);
	RCC->PLLCFGR |= (1U<<3);
	RCC->PLLCFGR &=~(1U<<4);
	RCC->PLLCFGR &=~(1U<<5);

	RCC->PLLCFGR &=~(1U<<6);
	RCC->PLLCFGR |= (1U<<7);
	RCC->PLLCFGR &=~(1U<<8);
	RCC->PLLCFGR &=~(1U<<9);
	RCC->PLLCFGR |= (1U<<10);
	RCC->PLLCFGR |= (1U<<11);
	RCC->PLLCFGR &=~(1U<<12);
	RCC->PLLCFGR &=~(1U<<13);
	RCC->PLLCFGR &=~(1U<<14);

	RCC->PLLCFGR &=~(1U<<16);
	RCC->PLLCFGR &=~(1U<<17);

	RCC->CR |= (1U<<24);
	while (!(RCC->CR & (1U<<25)));

	RCC->CFGR |= (1U<<4);
	RCC->CFGR &=~(1U<<5);
	RCC->CFGR &=~(1U<<6);
	RCC->CFGR &=~(1U<<7);

	RCC->CFGR &=~(1U<<0);
	RCC->CFGR |= (1U<<1);
}

 

 The steps I followed:

  1. Select the main PLL entry clock source as HSI. 
  2. Set PLLM = 8
  3. Set PLLN = 50
  4. Set PLLP = 2
  5. Enable PLL
  6. Wait for PLL to be locked
  7. Set AHB prescaler as system clock not divided
  8. Select PLL as the system clock

According to theoretical calculations, the system clock should be 16/8*50/2 = 50MHz.

Best answer by waclawek.jan

That changing bit by bit is ehm, very suboptimal, but should work.

However, for higher system frequencies you need to change FLASH waitstates (FLASH_ACR.LATENCY), *before* you switch clocks.

(For even higher system frequencies you would need to change also PWR_CR.VOS, and for that enable PWR in RCC).

JW

2 replies

KnarfB
Super User
July 16, 2024

I wouldn't change those values bit by bit. This causes alot of intermediate PLL states after each line.

When you probed SCK, have you checked that you scope/LA can handle the expected frequencies?

hth

KnarfB

Associate II
July 16, 2024

The scope has a 70MHz bandwidth.

 

About changing the bits all at once, is this right...?

RCC->PLLCFGR |= (110010 << 6);

KnarfB
Super User
July 16, 2024

> RCC->PLLCFGR |= (110010 << 6);

If it is meant to be binary, 0b110010 is correct.  

waclawek.jan
waclawek.janBest answer
Super User
July 16, 2024

That changing bit by bit is ehm, very suboptimal, but should work.

However, for higher system frequencies you need to change FLASH waitstates (FLASH_ACR.LATENCY), *before* you switch clocks.

(For even higher system frequencies you would need to change also PWR_CR.VOS, and for that enable PWR in RCC).

JW