====== RCC Setup System Clocks ====== To setup the system clocks you have to: * Select a [[#clock_source|clock source]]. * Set up the [[#setup_pll|PLL]] (optional). * Configure the [[#clock_ratios|clock ratios]]. \\ ==== Available Oscillators ==== |< 100% 5em 5em >| ^ ^ftypical^^ |LSI|32 kHz|Low speed internal oscillator| |LSE|32 kHz|Low speed external oscillator| |HSI|16 MHz|High speed internal oscillator| |HSE|8 MHz|High speed external oscillator| ==== Available Clocks ==== |< 100% 5em 5em >| ^ ^ftypical^^ |PLLCLK|var.|PLL clock, used to generate all other clocks| |PLL48CLK|48 MHz|PLL48 clock, used for USB or SDIO| |RTCCLK|var.|RTC clock, used by real time clock| |SYSCLK|168 MHz|System clock, used by CPU| |HCLK|84 MHz|AHB clock, used for AHB peripherals| |PCLK1|42 MHz|APB1 clock, used for APB1 peripherals| |PCLK2|84 MHz|APB2 clock, used for APB2 peripherals| |TCLK|84 MHz|Timer 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). \\ {{clock_clocksource.svg}} \\ \\ * 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); } \\ ===== 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. \\ {{clock_pllconfig.svg}} \\ \\ * 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); } \\ ===== Clock Ratios ===== If the SYSCLK is set up correctly, the AHB and APB clocks have to be adjusted. \\ {{clock_clockconfig.svg}} \\ \\ * 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); } \\ ===== Configuration Registers ===== ==== CR - Control register ==== \\ {{clock_reg_cr.svg}} \\ \\ |< 100% 5em 5em >| |HSION|0|Internal high speed clock enabled| |:::|1|Internal high speed clock disabled (reset state)| |HSIRDY|0|Internal high speed clock **not** ready| |:::|1|Internal high speed clock ready (reset state)| |xON|0|X enabled (reset state)| |:::|1|X disabled| |xRDY|0|X **not** ready (reset state)| |:::|1|X ready| ==== CSR - Control and status register ==== \\ {{clock_reg_csr.svg}} \\ \\ |< 100% 5em 5em >| |LSION|0|Internal low speed clock enabled| |:::|1|Internal low speed clock disabled (reset state)| |LSIRDY|0|Internal low speed clock **not** ready| |:::|1|Internal low speed clock ready (reset state)| ==== PLLCFGR - PLL configuration register ==== \\ {{clock_reg_pllcfgr.svg}} \\ \\ |< 100% 5em 5em 15em 5em>| |PLLM|xxxxxx|Division factor for PLL, choose factor so resulting frequency is between 1..2 MHz.||| |PLLN|xxxxxxxxx|Multiplication factor for VCO.||| |PLLP|00|SYSCLK => fPLL / 2.|10|SYSCLK => fPLL / 6.| |:::|01|SYSCLK => fPLL / 4.|11|SYSCLK => fPLL / 8.| |PLLQ|xxxx|Division factor PLL48CLK (for USB / SDIO clock), has to result in 48 MHz frequency.||| |PLLSRC|0|Select HSI for PLL input clock.||| |:::|1|Select HSE for PLL input clock.||| * Please refer to reference manual (p.162ff) for detailed explanation of register values. \\ \\ ==== CFGR - Configuration register ==== \\ {{clock_reg_cfgr.svg}} \\ \\ |< 100% 5em 5em 15em 5em >| |SW|00|Enable HSI as SYSCLK (reset state)|| |:::|01|Enable HSE as SYSCLK|| |:::|10|Enable PLL as SYSCLK|| |SWS|00|HSI used as SYSCLK|| |:::|01|HSE used as SYSCLK|| |:::|10|PLL used as SYSCLK|| |HPRE|0xxx|SYSCLK not divided (reset state)||| |:::|1000|HCLK => fSYSCLK / 2|1100|HCLK => fSYSCLK / 64| |:::|1001|HCLK => fSYSCLK / 4|1101|HCLK => fSYSCLK / 128| |:::|1010|HCLK => fSYSCLK / 8|1110|HCLK => fSYSCLK / 256| |:::|1011|HCLK => fSYSCLK / 16|1111|HCLK => fSYSCLK / 512| |PPRE1|0xx|HCLK not divided (reset state)||| |:::|1000|PCLK1 => fHCLK / 2|1100|PCLK1 => fHCLK / 64| |:::|1001|PCLK1 => fHCLK / 4|1101|PCLK1 => fHCLK / 128| |PPRE2*|0xx|HCLK not divided (reset state)||| |:::|100|PCLK2 => fHCLK / 2|110|PCLK2 => fHCLK / 8| |:::|101|PCLK2 => fHCLK / 4|111|PCLK2 => fHCLK / 16| * if PPRE2 **not** 0xx then TCLK => fPCLK2 • 2 \\ \\