RCC Setup System Clocks

To setup the system clocks you have to:


ftypical
LSI32 kHzLow speed internal oscillator
LSE32 kHzLow speed external oscillator
HSI16 MHzHigh speed internal oscillator
HSE8 MHzHigh speed external oscillator
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

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).




  • Set xxxON bit of desired oscillator.
  • Wait until xxxRDY flag is set.


#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);
}


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.




  • Choose input clock for PLL.
  • Choose PLLM value, so that the resulting frequency is between 1..2 MHz (2 MHz for less jitter).
  • Choose PLLN and PLLP values, so that you reach the desired system clock frequency.
  • If USB is used, choose PLLQ value, so that fPLL48CLK is 48 MHz.


#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);
}


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




  • Choose HPRE, maximum allowed clock on AHB is 168 MHz.
  • Choose PPRE1, maximum allowed clock on APB1 is 42 MHz.
  • Choose PPRE2, maximum allowed clock on APB2 is 84 MHz.
  • Select input source.


#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);
}





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




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)




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.




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

  • stm32/peripherals/rcc_clock.txt
  • Last modified: 2022/12/27 19:27
  • by ruan