RCC Setup System Clocks

To setup the system clocks you have to:


Available Oscillators

ftypical
LSI32 kHzLow speed internal oscillator
LSE32 kHzLow speed external oscillator
HSI16 MHzHigh speed internal oscillator
HSE8 MHzHigh speed external oscillator

Available Clocks

ftypical
PLLCLKvar.PLL clock, used to generate all other clocks
PLL48CLK48 MHzPLL48 clock, used for USB or SDIO
RTCCLKvar.RTC clock, used by real time clock
SYSCLK168 MHzSystem clock, used by CPU
HCLK84 MHzAHB clock, used for AHB peripherals
PCLK142 MHzAPB1 clock, used for APB1 peripherals
PCLK284 MHzAPB2 clock, used for APB2 peripherals
TCLK84 MHzTimer clock, used for the timers

Clock Source

By default the 16 MHz HSI is selected as clock source. For a more accurate clock you can use an external oscillator.
On the Discovery Board is a external 8 MHz oscillator mounted, which should be used (especially for USB applications).





#include "reg_stm32f4xx.h"
 
uint32_t reg;
 
RCC->CR |= (0x1 << 16u);              /* Set HSEON bit. */
reg = RCC->CR & (0x1 << 17u);
while (reg == 0u) {                   /* Wait for HSERDY flag. */
    reg = RCC->CR & (0x1 << 17u);
}


Setup PLL

To get to a system clock of 168 MHz, the PLL has to be used. The PLL can be used either with HSE or HSI.





#include "reg_stm32f4xx.h"
 
uint32_t reg;
RCC->PLLCFGR |= (0x4 << 0u);          /* PLLM: input => 8 MHz / 4 => 2 MHz */
RCC->PLLCFGR |= (168u << 6u);         /* PLLN: VCO => 2 MHz • 168 => 336 MHz */
RCC->PLLCFGR |= (0x0 << 16u);         /* PLLP: PLLCLK => 336 MHz / 2 => 168 MHz */
RCC->PLLCFGR |= (7u << 24u);          /* PLLQ: PLL48CLK => 336 MHz / 7 => 48 MHz */
RCC->PLLCFGR |= (0x1 << 22u);         /* Choose HSE as PLL input clock. */
 
RCC->CR |= (0x1 << 24u);              /* Set PLLON bit. */
reg = RCC->CR & (0x1 << 25u);
while (reg == 0u) {                   /* Wait for PLLRDY flag. */
    reg = RCC->CR & (0x1 << 25u);
}


Clock Ratios

If the SYSCLK is set up correctly, the AHB and APB clocks have to be adjusted.





#include "reg_stm32f4xx.h"
 
uint32_t reg;
 
RCC->CFGR |= (0x8 << 4u);             /* HPRE:  HCLK  => 168 MHz / 2 => 84 MHz */
RCC->CFGR |= (0x4 << 10u);            /* PPRE1: PCLK1 =>  84 MHz / 2 => 42 MHz */
RCC->CFGR |= (0x0 << 13u);            /* PPRE2: PCLK2 =>  84 MHz / 2 => 42 MHz 
                                                TCLK  =>  42 MHz • 2 => 84MHz */
 
RCC->CFGR |= (0x2 << 0u);             /* Choose PLLCLK as input. */
reg = RCC->CFGR & (0x3 << 2u);
while (reg == 0u) {                   /* Wait for SWS status. */
    reg = RCC->CFGR & (0x3 << 2u);
}


Configuration Registers

CR - Control register




HSION0Internal high speed clock enabled
1Internal high speed clock disabled (reset state)
HSIRDY0Internal high speed clock not ready
1Internal high speed clock ready (reset state)
xON0X enabled (reset state)
1X disabled
xRDY0X not ready (reset state)
1X ready

CSR - Control and status register




LSION0Internal low speed clock enabled
1Internal low speed clock disabled (reset state)
LSIRDY0Internal low speed clock not ready
1Internal low speed clock ready (reset state)

PLLCFGR - PLL configuration register




PLLMxxxxxxDivision factor for PLL, choose factor so resulting frequency is between 1..2 MHz.
PLLNxxxxxxxxxMultiplication factor for VCO.
PLLP00SYSCLK ⇒ fPLL / 2.10SYSCLK ⇒ fPLL / 6.
01SYSCLK ⇒ fPLL / 4.11SYSCLK ⇒ fPLL / 8.
PLLQxxxxDivision factor PLL48CLK (for USB / SDIO clock), has to result in 48 MHz frequency.
PLLSRC0Select HSI for PLL input clock.
1Select HSE for PLL input clock.

* Please refer to reference manual (p.162ff) for detailed explanation of register values.

CFGR - Configuration register




SW00Enable HSI as SYSCLK (reset state)
01Enable HSE as SYSCLK
10Enable PLL as SYSCLK
SWS00HSI used as SYSCLK
01HSE used as SYSCLK
10PLL used as SYSCLK
HPRE0xxxSYSCLK not divided (reset state)
1000HCLK ⇒ fSYSCLK / 21100HCLK ⇒ fSYSCLK / 64
1001HCLK ⇒ fSYSCLK / 41101HCLK ⇒ fSYSCLK / 128
1010HCLK ⇒ fSYSCLK / 81110HCLK ⇒ fSYSCLK / 256
1011HCLK ⇒ fSYSCLK / 161111HCLK ⇒ fSYSCLK / 512
PPRE10xxHCLK not divided (reset state)
1000PCLK1 ⇒ fHCLK / 21100PCLK1 ⇒ fHCLK / 64
1001PCLK1 ⇒ fHCLK / 41101PCLK1 ⇒ fHCLK / 128
PPRE2*0xxHCLK not divided (reset state)
100PCLK2 ⇒ fHCLK / 2110PCLK2 ⇒ fHCLK / 8
101PCLK2 ⇒ fHCLK / 4111PCLK2 ⇒ fHCLK / 16

* if PPRE2 not 0xx then TCLK ⇒ fPCLK2 • 2