Reset and Clock Control Reference-manual-style chapter

STM32F103 RCC Clock Control Reference Chapter

Clock source selection, SYSCLK distribution, prescalers, and enable registers

Document ID
RCC-RM001
Revision
Rev 2.0
Primary sources
DS5319 Figure 2, RM0008 Chapter 7
Register focus
CR / CFGR / AHBENR / APB2ENR / APB1ENR
Address note: the real STM32F103 RCC register block starts at 0x40021000. Official registers used here include RCC_APB2ENR = 0x40021018 and RCC_APB1ENR = 0x4002101C. The trainer's C pointer RCC is a compact MMIO view at 0x1800 with only APB2ENR and APB1ENR fields. The numeric register defines still preserve the official STM32-style addresses for Register View and read_reg / write_reg.

Contents

Front matter: Document scope.

  1. RCC overview
  2. Clock tree overview
  3. Derived clocks and important exceptions
  4. RCC register map
  5. Clock control register (RCC_CR)
  6. Clock configuration register (RCC_CFGR)
  7. AHB/APB enable registers
  8. Programming sequences
  9. Student register guide and code examples

Document scope

This chapter follows the official STM32F103 document split: the datasheet provides the big clock-tree view, while RM0008 explains the control registers, prescalers, and peripheral enable sequence. Trainer-executable examples are kept separate in Chapter 9.

1 RCC overview

On STM32F103, RCC performs three jobs. First, it decides which oscillator or PLL output becomes SYSCLK. Second, it divides that system clock into the AHB and APB bus clocks. Third, it enables or disables the bus clock that reaches each peripheral register block.

2 Clock tree overview

Reconstructed STM32F103 RCC clock tree slice

Figure 1. Reconstructed STM32F103 RCC clock-tree slice

Source reconstruction: STM32F103 datasheet (DS5319 Rev 20, Figure 2. Clock tree) and RM0008 Rev 21, Figure 8. Clock tree

The official documents place clock distribution before register details. That order matters because RCC_CR and RCC_CFGR only make sense after the reader can see where SYSCLK, HCLK, PCLK1, PCLK2, and ADCCLK come from.

2.1 Register callouts in Figure 1

Callout Clock-tree position Register What the student should connect it to
1 SW, AHB, APB1, APB2, and ADC prescaler path RCC_CFGR Clock-source selection and divider fields. The trainer provides these base settings for the current lab.
2 PCLK2 peripheral-enable path RCC_APB2ENR Open APB2 register blocks. IOPAEN enables GPIOA for PA2/PA3/PA4, and IOPBEN enables GPIOB for PB0/PB1.
3 PCLK1 peripheral-enable path RCC_APB1ENR Open APB1 register blocks such as TIM2. In the current trainer, this is the timer-side clock gate for the PWM route.

PA2, PA3, and PA4 belong to GPIOA; PB0 and PB1 belong to GPIOB. Both GPIO port clocks are opened from RCC_APB2ENR on the PCLK2 side, not from PCLK1. PCLK1 is the APB1 side used here for TIM2.

3 Derived clocks and important exceptions

Clock Generated from Main consumers Important limit or rule
SYSCLK HSI, HSE, or PLLCLK Core clock root Selected through RCC_CFGR.SW
HCLK SYSCLK through HPRE Core, memory, DMA, AHB bus Maximum 72 MHz
PCLK1 HCLK through PPRE1 APB1 peripherals such as TIM2, USART2, I2C Maximum 36 MHz
PCLK2 HCLK through PPRE2 APB2 peripherals such as GPIO, ADC1, USART1, SPI1, TIM1 Maximum 72 MHz
ADCCLK PCLK2 through ADCPRE ADC interface clock PCLK2 divided by 2, 4, 6, or 8
TIMxCLK Derived from APB domain clock TIM1, TIM2, TIM3, TIM4 and similar timers APB prescaler = 1 then x1, otherwise x2
Timer clock doubling rule: if the APB prescaler is 1, the timer clock equals PCLK. If the APB prescaler is not 1, the timer clock automatically becomes 2 x PCLK. Example: SYSCLK = 72 MHz, PPRE1 = /2, so PCLK1 = 36 MHz but TIM2 clock = 72 MHz.
72 MHz bring-up also depends on Flash wait states. RM0008 describes FLASH_ACR.LATENCY as 0 wait state for up to 24 MHz, 1 wait state for up to 48 MHz, and 2 wait states for up to 72 MHz.

4 RCC register map

Offset Register Purpose Trainer status
0x00 RCC_CR Clock source enable and ready flags Reference-only in current trainer
0x04 RCC_CFGR SYSCLK switch, PLL source, PLL multiplier, AHB/APB prescalers, ADC prescaler Reference-only in current trainer
0x14 RCC_AHBENR AHB peripheral clock enable register Reference-only in current trainer
0x18 RCC_APB2ENR APB2 peripheral clock enable register Exposed in trainer header and runtime
0x1C RCC_APB1ENR APB1 peripheral clock enable register Exposed in trainer header and runtime

Official base address: RCC = 0x40021000. Trainer pointer base: RCC = 0x1800. The trainer pointer is intentionally compact; do not infer official RCC_CR or RCC_CFGR pointer layout from it.

Reconstructed AHB APB2 APB1 enable register bit map

Figure 2. Representative RCC enable-register split across AHB, APB2, and APB1

Source reconstruction: RM0008 Rev 21, Sections 7.3.6 through 7.3.8. Trainer-highlighted bits show the currently exposed subset.

5 Clock control register (RCC_CR)

Address offset: 0x00
Reset value: 0x0000 XX83

Bit Name Meaning Clock-control role
0 HSION Internal 8 MHz RC enable Turns on the reset-default clock source
1 HSIRDY Internal 8 MHz RC ready flag Wait until the internal oscillator is stable
16 HSEON External high-speed clock enable Starts crystal mode or bypass mode
17 HSERDY External high-speed clock ready flag Wait for stable external clock before switching
18 HSEBYP External clock bypass Use only when feeding an already-generated external clock into OSC_IN
24 PLLON PLL enable Enable PLL only after the multiplier and source are configured
25 PLLRDY PLL lock flag Wait here before selecting PLL as SYSCLK

RCC_CR is the "turn it on and wait until ready" register. Each oscillator or PLL enable bit has a matching ready status bit, so software can confirm that the source is stable before routing it into SYSCLK.

6 Clock configuration register (RCC_CFGR)

Address offset: 0x04
Reset value: 0x00000000

Field Meaning Clock path role
SW System clock switch Selects which source becomes SYSCLK
SWS System clock switch status Confirms which source is actually driving SYSCLK
HPRE AHB prescaler Divides SYSCLK to produce HCLK
PPRE1 APB1 prescaler Must keep APB1 at or below 36 MHz
PPRE2 APB2 prescaler Divides HCLK to produce PCLK2
ADCPRE ADC prescaler Selects PCLK2 / 2, /4, /6, or /8
PLLSRC PLL input source Chooses HSI/2 or HSE
PLLXTPRE HSE divider before PLL Optionally divides HSE by 2 before the PLL stage
PLLMUL PLL multiplication factor Must be programmed while PLL is disabled and must not generate more than 72 MHz

RCC_CFGR is the "which clock do I select and how do I divide it" register. The official RM0008 wording makes a clean distinction: RCC_CR enables sources, while RCC_CFGR routes and scales them.

6.1 Clock-tree bit and field summary

Register bit or field Clock-tree position Effect on clock path
RCC_CR.HSIONHSI 8 MHz oscillator blockEnables the internal 8 MHz oscillator.
RCC_CR.HSIRDYHSI ready stateReports that the internal oscillator is stable.
RCC_CR.HSEONHSE oscillator blockEnables the external crystal or bypass-clock source.
RCC_CR.HSERDYHSE ready stateReports that the external high-speed clock is stable.
RCC_CR.PLLONPLL blockEnables the PLL multiplication path.
RCC_CR.PLLRDYPLL ready stateReports that the PLL is locked.
RCC_CFGR.SWSYSCLK selection muxSelects HSI, HSE, or PLL as the requested SYSCLK source.
RCC_CFGR.SWSSYSCLK status pathReports which source is actually driving SYSCLK.
RCC_CFGR.HPRESYSCLK -> HCLK dividerDivides SYSCLK to produce the AHB clock, HCLK.
RCC_CFGR.PPRE1HCLK -> PCLK1 dividerDivides HCLK to produce the APB1 clock, PCLK1.
RCC_CFGR.PPRE2HCLK -> PCLK2 dividerDivides HCLK to produce the APB2 clock, PCLK2.
RCC_CFGR.ADCPREPCLK2 -> ADCCLK dividerDerives the ADC conversion clock from PCLK2.
RCC_APB2ENR.IOPAENPCLK2 -> GPIOA gateSupplies the bus clock to the GPIOA register block.
RCC_APB2ENR.ADC1ENPCLK2 -> ADC1 interface gateSupplies the bus clock to the ADC1 register interface.
RCC_APB1ENR.TIM2ENPCLK1 -> TIM2 gateSupplies the bus clock to the TIM2 register and timer block.

7 AHB/APB enable registers

7.1 AHB peripheral clock enable register (RCC_AHBENR)

Bit Name Domain example
0DMA1ENDMA1 clock enable
1DMA2ENDMA2 clock enable
2SRAMENSRAM interface clock enable
4FLITFENFlash interface clock enable

7.2 Enable-register domain split

  • RCC_AHBENR controls AHB-side interfaces such as DMA, SRAM, and Flash interface clocks.
  • RCC_APB2ENR controls high-speed peripheral register blocks such as AFIO, GPIO ports, ADC1, and USART1.
  • RCC_APB1ENR controls lower-speed peripheral register blocks such as TIM2.

7.3 APB2 peripheral clock enable register (RCC_APB2ENR)

Address offset: 0x18
Reset value: 0x00000000

Name Bit Mask Write example Unlocks
AFIOEN00x00000001RCC->APB2ENR |= (1u << 0);Alternate-function routing helpers
IOPAEN20x00000004RCC->APB2ENR |= (1u << 2);GPIOA register block
IOPBEN30x00000008RCC->APB2ENR |= (1u << 3);GPIOB register block
ADC1EN90x00000200RCC->APB2ENR |= (1u << 9);ADC1 register block
Enabled bits Register value Use case
AFIOEN | IOPAEN0x00000005AFIO + GPIOA
AFIOEN | IOPAEN | IOPBEN0x0000000DAFIO + GPIOA + GPIOB
AFIOEN | IOPAEN | ADC1EN0x00000205AFIO + GPIOA + ADC1
AFIOEN | IOPAEN | IOPBEN | ADC1EN0x0000020DAFIO + GPIOA + GPIOB + ADC1

Example whole-register write: RCC->APB2ENR = 0x0000020D

Bit Name Description
0AFIOEN0x00000001; enables alternate-function routing helpers used with EXTI and timer/GPIO interaction
2IOPAEN0x00000004; opens the GPIOA register path
3IOPBEN0x00000008; opens the GPIOB register path
9ADC1EN0x00000200; opens the ADC1 register path, while conversion clock still depends on RCC_CFGR.ADCPRE

7.4 APB1 peripheral clock enable register (RCC_APB1ENR)

Address offset: 0x1C
Reset value: 0x00000000

Name Bit Mask Write example Unlocks
TIM2EN00x00000001RCC->APB1ENR |= (1u << 0);TIM2 register block
TIM3EN10x00000002RCC->APB1ENR |= (1u << 1);TIM3 register block
USART2EN170x00020000RCC->APB1ENR |= (1u << 17);USART2 register block
I2C1EN210x00200000RCC->APB1ENR |= (1u << 21);I2C1 register block
Enabled bits Register value Use case
TIM2EN0x00000001Enable TIM2 only
TIM2EN | TIM3EN0x00000003Enable TIM2 and TIM3

Example whole-register write: RCC->APB1ENR = 0x00000001

Bit Name Description
0TIM2EN0x00000001; opens the TIM2 register path used by the trainer PWM route
1TIM3EN0x00000002; opens the TIM3 register path
17USART2EN0x00020000; opens the USART2 register path
21I2C1EN0x00200000; opens the I2C1 register path

8 Programming sequences

Official STM32F103 clock-source switching uses RCC_CR, RCC_CFGR, and FLASH_ACR. The current trainer code path keeps execution narrower and uses the APB enable registers directly.

9 Student register guide and code examples

Student-facing register distinction
This final section separates the current trainer code path from the full STM32F103 register path. The main chapter above remains the RCC reference section; this section is the student-oriented bridge into runnable examples.

9.1 Which RCC registers the student should look at

Register Current trainer status Register role Where it appears in the figures
RCC_CR Full STM32F103 example Enables HSI, HSE, and PLL sources and reports their matching ready status bits. Figure 1 source blocks: HSI / HSE / PLL
RCC_CFGR Full STM32F103 example Defines the clock source selection, status, prescalers, PLL source, and PLL multiplication factor. Figure 1 SW mux and AHB/APB/ADC Prescaler path
RCC_AHBENR Reference table in this chapter Enables AHB-side interfaces such as DMA, SRAM, and the Flash interface. Figure 1 HCLK to AHB domain path
RCC_APB2ENR Used directly in current trainer examples Enables APB2 peripheral register blocks such as AFIO, GPIOA, GPIOB, ADC1, and USART1. Figure 1 PCLK2 peripheral-enable path
RCC_APB1ENR Used directly in current trainer examples Enables APB1 peripheral register blocks such as TIM2. Figure 1 PCLK1 peripheral-enable path
FLASH_ACR Full STM32F103 example Sets Flash wait states before raising SYSCLK. Preparation step before the 72 MHz clock-tree example

9.2 Current trainer route and enable examples

Peripheral / route Required RCC enable Then configure Related chapter
GPIOA output or input GPIOA sits on APB2, so enable RCC->APB2ENR.IOPAEN. Program GPIOA_CRL / GPIOA_CRH, then use IDR, ODR, BSRR, or BRR. GPIOA chapter
ADC1 reading on PA1 / CURRENT_SENSE GPIOA and ADC1 both sit on APB2, so enable IOPAEN and ADC1EN. Official STM32 flow also derives ADCCLK from PCLK2 through RCC_CFGR.ADCPRE. Place PA1 in analog mode, then configure ADC channel selection, sample time, and conversion start logic. ADC1 chapter
TIM2 PWM output on the trainer route TIM2 sits on APB1, so enable RCC->APB1ENR.TIM2EN. The routed pad still needs its GPIO port clock. Configure the GPIO pin for alternate-function output and then program timer output enable and duty registers. TIM2 + GPIOA chapters
EXTI6-related routing for PA6 / HALL_IN AFIO and the GPIO port depend on APB2 clock enables. Configure the pad mode and then program the interrupt registers. EXTI and GPIOA chapters

9.3 Current trainer code example

/* Current trainer example: enable only the APB gates that the lab needs */
RCC->APB2ENR |= (1u << 0);   /* AFIOEN: PCLK2 alternate-function helper gate */
RCC->APB2ENR |= (1u << 2);   /* IOPAEN: PCLK2 -> GPIOA gate */
RCC->APB2ENR |= (1u << 3);   /* IOPBEN: PCLK2 -> GPIOB gate */
RCC->APB2ENR |= (1u << 9);   /* ADC1EN: PCLK2 -> ADC1 interface gate */
RCC->APB1ENR |= (1u << 0);   /* TIM2EN: PCLK1 -> TIM2 gate */

This is the compact RCC code path students use most often in the current trainer. It enables the APB2 and APB1 peripheral register blocks needed by the visible GPIO, ADC, EXTI helper, and TIM2 routes.

9.4 Full STM32F103 example when every register is available

/* Full-register STM32F103 example: HSE 8 MHz -> PLL x9 -> SYSCLK 72 MHz */
FLASH_ACR |= 0x2u;                  /* FLASH latency = 2 before 72 MHz */

RCC->CR |= (1u << 16);             /* HSEON: HSE source ON */
while ((RCC->CR & (1u << 17)) == 0u) { }   /* HSERDY: HSE stable */

{
    uint32_t cfgr = RCC->CFGR;
    cfgr &= ~((1u << 16) | (1u << 17) | (0xFu << 18) | (0xFu << 4) | (0x7u << 8) | (0x7u << 11) | (0x3u << 14));
    cfgr |=
        (1u << 16) |               /* PLLSRC = HSE: HSE -> PLL path */
        (0u << 17) |               /* PLLXTPRE = /1 */
        (7u << 18) |               /* PLLMUL = x9 */
        (0u << 4)  |               /* HPRE = /1 */
        (4u << 8)  |               /* PPRE1 = /2 */
        (0u << 11) |               /* PPRE2 = /1 */
        (2u << 14);                /* ADCPRE = /6 */
    RCC->CFGR = cfgr;
}

RCC->CR |= (1u << 24);             /* PLLON: PLL source ON */
while ((RCC->CR & (1u << 25)) == 0u) { }   /* PLLRDY: PLL stable */

RCC->CFGR = (RCC->CFGR & ~0x3u) | 0x2u;    /* SW = PLL */
while (((RCC->CFGR >> 2) & 0x3u) != 0x2u) { }   /* SWS = PLL */

This example shows the full-device clock-source path using RCC_CR, RCC_CFGR, and FLASH_ACR. Read it along the Figure 1 path: HSE -> PLLXTPRE -> PLL -> SW -> SYSCLK -> AHB/APB/ADC Prescaler. For the HSE 8 MHz -> PLL x9 -> 72 MHz route, PLLSRC = 1 selects HSE as the PLL input.

STM32F103 RCC reference chapter RCC-RM001 Rev 2.0