hal::clock
Clock Configuration - PLL & System Clock Setup
~410 satır
~22 function
STM32/GD32
Overview
Clock modülü, mikrodenetleyicinin kalp atışıdır. HSI/HSE/PLL kaynaklarını structlandırır, sistem clockunu ayarlar ve peripheral clocklarını dağıtır. Doğru clock structlandırması sistemin performansını, güç tüketimini ve timing accuracy'sini truedan etkiler.
Key Features
- Clock Kaynakları: HSI (16 MHz internal), HSE (4-25 MHz external), LSI (32 kHz), LSE (32.768 kHz)
- PLL (Phase-Locked Loop): 8 MHz HSE -> 168 MHz system clock
- Clock Tree: SYSCLK -> AHB (CPU/DMA/Memory) -> APB1 (low speed) -> APB2 (high speed)
- Prescalers: AHB divider (1,2,4,...,512), APB1 divider (1,2,4,8,16), APB2 divider
- CSS (Clock Security System): HSE failure detection, automatic switch to HSI
- MCO (Master Clock Output): Clock signal output to GPIO pin
- RTC Clock: LSE/LSI for Real-Time Clock
- USB Clock: 48 MHz requirement for USB peripheral
Quick Start
import hal::clock
// HSE + PLL -> 72 MHz (STM32F1)
clock.init(do
source: clock.SOURCE_PLL,
hse_freq: 8_000_000, // 8 MHz crystal
pll_mul: 9, // 8 * 9 = 72 MHz
ahb_div: 1, // HCLK = 72 MHz
apb1_div: 2, // PCLK1 = 36 MHz (max 36 MHz)
apb2_div: 1 // PCLK2 = 72 MHz
end)
// Verify clock
let sysclk = clock.get_sysclk_freq()
io.yazdir_satır("SYSCLK: " + sysclk.metne() + " Hz")
Types and Enums'lar
// Clock Sources
enum ClockSource {
HSI, // High-Speed Internal (16 MHz)
HSE, // High-Speed External (4-25 MHz crystal)
PLL, // Phase-Locked Loop (multiplied clock)
LSI, // Low-Speed Internal (32 kHz, RTC)
LSE // Low-Speed External (32.768 kHz, RTC)
}
// PLL Source
enum PLLSource {
PLL_HSI, // HSI as PLL input
PLL_HSE // HSE as PLL input
}
// AHB Prescaler
enum AHBPrescaler {
DIV_1, DIV_2, DIV_4, DIV_8, DIV_16,
DIV_64, DIV_128, DIV_256, DIV_512
}
// APB Prescaler
enum APBPrescaler {
DIV_1, DIV_2, DIV_4, DIV_8, DIV_16
}
struct ClockConfig do
source: ClockSource,
hse_freq: int = 8_000_000,
pll_source: PLLSource = PLL_HSE,
pll_mul: int = 9, // STM32F1: 2-16
pll_m: int = 8, // STM32F4: input divider
pll_n: int = 336, // STM32F4: multiplier
pll_p: int = 2, // STM32F4: system clock divider
pll_q: int = 7, // STM32F4: USB/SDIO divider
ahb_prescaler: AHBPrescaler = DIV_1,
apb1_prescaler: APBPrescaler = DIV_2,
apb2_prescaler: APBPrescaler = DIV_1,
css_enable: bool = true, // Clock Security System
flash_latency: int = 2 // Wait states
end
Example 1: STM32F1 - 72 MHz Maximum Speed
Problem: STM32F103 for maksimum performans (72 MHz)
import hal::clock, hal::flash
function clock_72mhz_init() do
// Enable HSE (8 MHz external crystal)
clock.hse_enable()
// Wait for HSE ready
if değil clock.hse_wait_ready(1000) do
io.yazdir_satır("HSE failed to start!")
return
end
// Configure Flash latency (2 wait states for 72 MHz)
flash.set_latency(flash.LATENCY_2)
// Configure PLL: HSE * 9 = 8 MHz * 9 = 72 MHz
clock.pll_config(do
source: clock.PLL_HSE,
mul: 9
end)
// Enable PLL
clock.pll_enable()
clock.pll_wait_ready(1000)
// Configure bus prescalers
clock.set_ahb_prescaler(clock.AHB_DIV_1) // 72 MHz
clock.set_apb1_prescaler(clock.APB_DIV_2) // 36 MHz (max!)
clock.set_apb2_prescaler(clock.APB_DIV_1) // 72 MHz
// Switch to PLL as system clock
clock.set_sysclk_source(clock.SOURCE_PLL)
// Wait for switch
loop do
if clock.get_sysclk_source() == clock.SOURCE_PLL do
break
end
end
// Update SystemCoreClock variable
clock.system_core_clock_update()
io.yazdir_satır("Clock configured successfully!")
io.yazdir_satır("SYSCLK: " + clock.get_sysclk_freq().metne() + " Hz")
io.yazdir_satır("HCLK: " + clock.get_hclk_freq().metne() + " Hz")
io.yazdir_satır("PCLK1: " + clock.get_pclk1_freq().metne() + " Hz")
io.yazdir_satır("PCLK2: " + clock.get_pclk2_freq().metne() + " Hz")
end
Çıktı: SYSCLK: 72000000 Hz, HCLK: 72000000 Hz, PCLK1: 36000000 Hz, PCLK2: 72000000 Hz
Example 2: STM32F4 - 168 MHz with USB Support
Problem: STM32F407 for 168 MHz + 48 MHz USB clock
import hal::clock, hal::flash, hal::power
function clock_168mhz_usb_init() do
// Enable power interface clock
clock.periph_clock_enable(clock.PERIPH_PWR)
// Voltage scaling for max frequency
power.set_voltage_scaling(power.SCALE_1)
// Enable HSE (8 MHz)
clock.hse_enable()
clock.hse_wait_ready(1000)
// Flash latency (5 wait states for 168 MHz @ 3.3V)
flash.set_latency(flash.LATENCY_5)
flash.prefetch_enable()
flash.instruction_cache_enable()
flash.data_cache_enable()
// PLL configuration:
// VCO_IN = HSE / PLLM = 8 MHz / 8 = 1 MHz
// VCO_OUT = VCO_IN * PLLN = 1 MHz * 336 = 336 MHz
// SYSCLK = VCO_OUT / PLLP = 336 MHz / 2 = 168 MHz
// USB_CLK = VCO_OUT / PLLQ = 336 MHz / 7 = 48 MHz
clock.pll_config(do
source: clock.PLL_HSE,
pllm: 8, // Input divider
plln: 336, // Multiplier
pllp: 2, // System clock divider
pllq: 7 // USB clock divider
end)
clock.pll_enable()
clock.pll_wait_ready(1000)
// Bus prescalers
clock.set_ahb_prescaler(clock.AHB_DIV_1) // 168 MHz
clock.set_apb1_prescaler(clock.APB_DIV_4) // 42 MHz (max 42 MHz!)
clock.set_apb2_prescaler(clock.APB_DIV_2) // 84 MHz (max 84 MHz!)
// Switch to PLL
clock.set_sysclk_source(clock.SOURCE_PLL)
loop do
if clock.get_sysclk_source() == clock.SOURCE_PLL do
break
end
end
clock.system_core_clock_update()
// Verify USB clock
let usb_clk = clock.get_usb_freq()
io.yazdir_satır("USB Clock: " + usb_clk.metne() + " Hz")
if usb_clk != 48_000_000 do
io.yazdir_satır("WARNING: USB clock is not 48 MHz!")
end
end
Result: 168 MHz sistem clocku + 48 MHz USB clock. Maksimum performans.
Example 3: Clock Security System (CSS)
Problem: HSE crystal failure durumunda otomatik HSI'ye geçiş
import hal::clock, hal::nvic
let hse_failed: bool = false
function clock_css_init() do
// Normal clock setup with HSE
clock.hse_enable()
clock.hse_wait_ready(1000)
clock.pll_config(do
source: clock.PLL_HSE,
mul: 9
end)
clock.pll_enable()
clock.pll_wait_ready(1000)
// Enable Clock Security System
clock.css_enable()
// Enable NMI interrupt for CSS
nvic.enable_irq(nvic.RCC_IRQn, do priority: 0 end)
clock.set_sysclk_source(clock.SOURCE_PLL)
io.yazdir_satır("CSS enabled, monitoring HSE...")
end
// CSS failure interrupt handler
function RCC_IRQHandler() do
if clock.get_flag(clock.FLAG_CSS) do
io.yazdir_satır("CSS INTERRUPT: HSE FAILURE DETECTED!")
hse_failed = true
// System automatically switched to HSI
// Reconfigure PLL with HSI
clock.pll_disable()
clock.pll_config(do
source: clock.PLL_HSI,
mul: 16 // HSI/2 * 16 = 8 MHz * 8 = 64 MHz
end)
clock.pll_enable()
clock.pll_wait_ready(1000)
// Clear CSS flag
clock.clear_flag(clock.FLAG_CSS)
io.yazdir_satır("Switched to HSI-based PLL (64 MHz)")
end
end
function ana() do
clock_css_init()
loop do
if hse_failed do
io.yazdir_satır("Running on backup HSI clock")
// Reduce performance or enter safe mode
end
// Normal operation
delay_ms(1000)
end
end
Güvenlik: HSE arızasında sistem donmaz, otomatik HSI'ye geçer.
Example 4: MCO (Master Clock Output) for Debugging
Problem: Oscilloscope ile clock sinyalini gözlemlemek
import hal::clock, hal::gpio
function mco_debug_init() do
// MCO pin: PA8 (STM32F4)
gpio.pin_init(gpio.PORT_A, 8, do
mode: gpio.MODE_AF,
af: gpio.AF0_MCO,
speed: gpio.SPEED_VERY_HIGH
end)
// Output SYSCLK / 4 to MCO
// (168 MHz / 4 = 42 MHz on PA8)
clock.mco1_config(do
source: clock.MCO_SYSCLK,
prescaler: clock.MCO_DIV_4
end)
io.yazdir_satır("MCO output enabled on PA8")
io.yazdir_satır("Expected frequency: " +
(clock.get_sysclk_freq() / 4).metne() + " Hz")
end
// Alternative: Output PLL clock for verification
function mco_pll_check() do
gpio.pin_init(gpio.PORT_A, 8, do
mode: gpio.MODE_AF, af: gpio.AF0_MCO
end)
// Output PLL / 2
clock.mco1_config(do
source: clock.MCO_PLL,
prescaler: clock.MCO_DIV_2
end)
io.yazdir_satır("PLL clock on PA8 (use oscilloscope)")
end
Debug: Oscilloscope ile gerçek clock frekansını truelayın. PLL lock problemlerini tespit edin.
API Reference
Clock Source Control
// HSE control
function hse_enable()
function hse_disable()
function hse_wait_ready(timeout_ms: int) -> bool
// HSI control
function hsi_enable()
function hsi_disable()
function hsi_calibration_set(value: int)
// PLL control
function pll_config(config: PLLConfig)
function pll_enable()
function pll_disable()
function pll_wait_ready(timeout_ms: int) -> bool
// System clock
function set_sysclk_source(source: ClockSource)
function get_sysclk_source() -> ClockSource
function get_sysclk_freq() -> int
// Bus clocks
function set_ahb_prescaler(div: AHBPrescaler)
function set_apb1_prescaler(div: APBPrescaler)
function set_apb2_prescaler(div: APBPrescaler)
function get_hclk_freq() -> int
function get_pclk1_freq() -> int
function get_pclk2_freq() -> int
// Peripheral clocks
function periph_clock_enable(periph: Peripheral)
function periph_clock_disable(periph: Peripheral)
// CSS and MCO
function css_enable()
function css_disable()
function mco1_config(source: MCOSource, div: MCODiv)
// Utilities
function system_core_clock_update()
function get_flag(flag: ClockFlag) -> bool
function clear_flag(flag: ClockFlag)
Important Notes:
- Flash Latency: High frequency for wait state gerekli (168 MHz -> 5 WS)
- APB1 Max: STM32F1 36 MHz, F4 42 MHz, F7 54 MHz
- USB Clock: Tam 48 MHz olmalı (tolerance 0.25%)
- PLL Lock Time: ~200 μs, timeout kullanın
Platform Support
| Platform | Max SYSCLK | HSE Range | PLL Multiplier |
|---|---|---|---|
| STM32F1 | 72 MHz | 4-16 MHz | 2-16x |
| STM32F4 | 168 MHz | 4-26 MHz | PLLM/N/P/Q |
| STM32F7 | 216 MHz | 4-26 MHz | PLLM/N/P/Q |
| STM32H7 | 480 MHz | 4-48 MHz | PLLM/N/P/Q/R |
| GD32VF103 | 108 MHz | 4-25 MHz | 2-32x |
Best Practices
- HSE kullan: Accuracy for internal HSI yerine external crystal
- CSS enable: Production sistemlerde Clock Security System aktif
- Flash latency: Clock değiştirmeden önce flash wait state ayarla
- Timeout kullan: HSE/PLL ready beklerken timeout ekle
- Direct switch doma: HSE->PLL geçişinde önce PLL ready bekle
- APB limiti aşma: APB1 max frekansını kontrol et
Related Modules
- hal::flash - Flash latency configuration
- hal::power - Voltage scaling for high frequency
- hal::rtc - LSE/LSI clock for RTC
- hal::gpio - MCO pin configuration