The stm32 chip manual shows clearly that there are four clock sources:
1. HSI (Internal High-Speed clock 8 MHz) provides a clock source that supports BIT system clock
2. HSE (external high-speed clock) provides system clock and RTC clock source
3. LSE (low-speed external clock 32.768 kHz) can provide a clock source for rtc
4. LSI (low-speed internal clock) can provide the clock source for the independent watchdog
First, let's analyze the database function provided by ST: I use 3.5 of the database.
Let's see what is in systeminit.
Void systeminit (void)
{
RCC-> Cr | = (uint32_t) 0x00000001; // enable the HSI Internal High-Speed clock
# Ifndef stm32f10x_cl
RCC-> cfgr & = (uint32_t) 0xf8ff0000; // The 27-bit cfcg register is useless, so this macro is useless.
# Else // The two sides of the MCO are cleared, and the clock is not output out, 0-15 digits are cleared, Plck 2 is divided into ADC, and hclk is not divided into apb2.
RCC-> cfgr & = (uint32_t) 0xf0ff0000; // hclk is not divided into apb1, sysclk is not divided into AHB, and HSI is used as the system clock,
# Endif/* stm32f10x_cl */
/* Reset hseon, csson and pllon bits */
RCC-> Cr & = (uint32_t) 0xfef6ffff; // disable HSE
/* Reset hsebyp bit */
RCC-> Cr & = (uint32_t) 0 xfffbffff; // The External High-Speed clock is not bypassed.
/* Reset pllsrc, pllxtpre, pllmul and usbpre/otgfspre bits */
RCC-> cfgr & = (uint32_t) 0xff80ffff; // The PLL is divided into two groups: USB pre, pllmul * 2, and PLL input HSI/2.
# Ifdef stm32f10x_cl
/* Reset pll2on and pll3on bits */
RCC-> Cr & = (uint32_t) 0 xebffffff ;//
/* Disable all interrupts and clear pending bits */
RCC-> CIR = 0x00ff0000; // disable all interruptions and clear the interrupt flag.
/* Reset cfgr2 register */
RCC-> cfgr2 = 0x00000000;
# Elif defined (stm32f10x_ld_vl) | defined (stm32f10x_md_vl) | (defined stm32f10x_hd_vl)
/* Disable all interrupts and clear pending bits */
RCC-> CIR = 0x009f0000;
/* Reset cfgr2 register */
RCC-> cfgr2 = 0x00000000;
# Else
/* Disable all interrupts and clear pending bits */
RCC-> CIR = 0x009f0000;
# Endif/* stm32f10x_cl */
# If defined (stm32f10x_hd) | (defined stm32f10x_xl) | (defined stm32f10x_hd_vl)
# Ifdef data_in_extsram
Systeminit_extmemctl ();
# Endif/* data_in_extsram */
# Endif
/* Configure the system clock frequency, hclk, pclk2 and pclk1 prescalers */
/* Configure the flash latency cycles and enable prefetch buffer */
Setsysclock (); // finally call the clock setting function. The following analysis
# Ifdef vect_tab_sram
SCB-> vtor = sram_base | vect_tab_offset;/* the interrupt vector table is located at sram_base (0x20000000) + vect_tab_offset (0x0 */
# Else
SCB-> vtor = flash_base | vect_tab_offset;/* the interrupt vector table is located at flash_base (0x08000000) + vect_tab_offset (0x0 */
# Endif
}
Let's take a look at the setsysclock () function.
Static void setsysclock (void)
{
# Ifdef sysclk_freq_hse
Setsysclocktohse ();
# Elif defined sysclk_freq_24mhz
Setsysclockto24 ();
# Elif defined sysclk_freq_36mhz
Setsysclockto36 ();
# Elif defined sysclk_freq_48mhz
Setsysclockto48 ();
# Elif defined sysclk_freq_56mhz
Setsysclockto56 ();
# Elif defined sysclk_freq_72mhz
Setsysclockto72 ();
# Endif
/* If no macro is set above, HSI is used as the system clock source. Generally, setsysclockto72 () function is called */
}
Static void setsysclockto72 (void)
{
_ IO uint32_t startupcounter = 0, hsestatus = 0; // _ IO uint32_t stands for vu32
/* Sysclk, hclk, pclk2 and pclk1 configuration ---------------------------*/
/* Enable HSE */
RCC-> Cr | = (uint32_t) rcc_cr_hseon); // rcc_cr_hseon (uint32_t) 0x00010000) HSE enabling
/* Wait till HSE is ready and if time out is reached exit */
Do
{
Hsestatus = RCC-> Cr & rcc_cr_hserdy; // rcc_cr_hserdy (uint32_t) 0x00020000) test HSE status
Startupcounter ++; // count wait
} While (hsestatus = 0) & (startupcounter! = Hsestartup_timeout); // when counting> hsestartup_timeout (0x500) and HSE is available, it jumps out.
If (RCC-> Cr & rcc_cr_hserdy )! = Reset) // If HSE is available
{
Hsestatus = (uint32_t) 0x01; // set hsestatus to 1
}
Else
{
Hsestatus = (uint32_t) 0x00; // set hsestatus to 0
}
If (hsestatus = (uint32_t) 0x01) // when HSE is available
{
/* Enable prefetch buffer */
Flash-> ACR | = flash_acr_prftbe;
/* Flash 2 wait state */
Flash-> ACR & = (uint32_t) (uint32_t )~ Flash_acr_latency );
Flash-> ACR | = (uint32_t) flash_acr_latency_2;
/* Hclk = sysclk */
RCC-> cfgr | = (uint32_t) rcc_cfgr_hpre_div1; // hclk equals to the system clock
/* Pclk2 = hclk */
RCC-> cfgr | = (uint32_t) rcc_cfgr_ppre2_div1; // APB pre-division is hclk
/* Pclk1 = hclk */
RCC-> cfgr | = (uint32_t) rcc_cfgr_ppre1_div2; // The pre-division of APB high and low speed is hclk/2
# Ifdef stm32f10x_cl
/* Configure plls ------------------------------------------------------ * // No pll2
/* Pll2 configuration: pll2clk = (HSE/5) * 8 = 40 MHz */
/* Prediv1 configuration: prediv1clk = pll2/5 = 8 MHz */
RCC-> cfgr2 & = (uint32_t )~ (Rcc_cfgr2_prediv2 | rcc_cfgr2_pll2mul |
Rcc_cfgr2_prediv1 | rcc_cfgr2_prediv1src );
RCC-> cfgr2 | = (uint32_t) (rcc_cfgr2_prediv2_div5 | rcc_cfgr2_pll2mul8 |
Rcc_cfgr2_prediv1src_pll2 | rcc_cfgr2_prediv1_div3 );
/* Enable pll2 */
RCC-> Cr | = rcc_cr_pll2on;
/* Wait till pll2 is ready */
While (RCC-> Cr & rcc_cr_pll2rdy) = 0)
{
}
/* PLL configuration: pllclk = prediv1 * 9 = 72 MHz */
RCC-> cfgr & = (uint32_t )~ (Rcc_cfgr_pllxtpre | rcc_cfgr_pllsrc | rcc_cfgr_pllmull );
RCC-> cfgr | = (uint32_t) (rcc_cfgr_pllxtpre_prediv1 | rcc_cfgr_pllsrc_prediv1 |
Rcc_cfgr_pllmull9 );
# Else
/* PLL configuration: pllclk = HSE * 9 = 72 MHz * // pl9's multiplier = 72 MHz
RCC-> cfgr & = (uint32_t) (uint32_t )~ (Rcc_cfgr_pllsrc | rcc_cfgr_pllxtpre |
Rcc_cfgr_pllmull ));
RCC-> cfgr | = (uint32_t) (rcc_cfgr_pllsrc_hse | rcc_cfgr_pllmula9 );
# Endif/* stm32f10x_cl */
/* Enable PLL */
RCC-> Cr | = rcc_cr_pllon; // enable PLL
/* Wait till PLL is ready */
While (RCC-> Cr & rcc_cr_pllrdy) = 0) // wait for the PLL to be ready
{
}
/* Select PLL as system clock source * // set the system clock as the PLL clock source
RCC-> cfgr & = (uint32_t) (uint32_t )~ (Rcc_cfgr_sw ));
RCC-> cfgr | = (uint32_t) rcc_cfgr_sw_pll;
/* Wait till PLL is used as system clock source * // wait for the system clock to be ready
While (RCC-> cfgr & (uint32_t) rcc_cfgr_sws )! = (Uint32_t) 0x08)
{
}
}
Else
{/* If HSE fails to start-up, the application will have wrong clock
Configuration. User can add here some code to deal with this error */
/* Go to infinite loop */
While (1) // If HSE cannot be used, jump into the endless loop
{
}
}
}
Stm32 RCC clock Analysis