The "Holy Bible" for embedded engineers
System Clock Configuration, PLL Setup, and Frequency Management
Learn to configure system clocks, PLLs, and manage frequencies for optimal performance
Clock management is fundamental to embedded system design, affecting performance, power consumption, and system reliability. Proper clock configuration ensures optimal operation and efficient resource utilization.
Clocks determine peripheral timing, serial baud, PWM resolution, and power. Choose sources (HSI, HSE, PLLs) that meet jitter/stability requirements and document the tree.
// Configure PLL for target SYSCLK; validate multiples for peripherals
void clocks_init(void){ /* enable HSE, configure PLLM/N/P/Q; switch SYSCLK */ }
System Clock Tree
┌─────────────────────────────────────────────────────────────┐
│ Primary Clock Sources │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ HSE │ │ HSI │ │ MSI │ │
│ │ (External │ │ (Internal │ │ (Multi- │ │
│ │ Crystal) │ │ RC Osc) │ │ Speed RC) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ PLL Configuration │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ PLL M │ │ PLL N │ │ PLL P │ │ │
│ │ │ (Divider) │ │(Multiplier) │ │ (Divider) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ System Clock (SYSCLK) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Peripheral Clock Distribution │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ AHB Bus │ │ APB1 Bus │ │ APB2 Bus │ │ │
│ │ │ (High Speed)│ │ (Low Speed) │ │(High Speed) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
└─────────────────────────────────────────────────────────────┘
PLL Frequency Generation
Input Frequency (f_in)
^
│ ┌─────────────────┐
│ │ │
│ │ │
│ │ │
+──────────────────────────-> Time
PLL Output (f_out = f_in × N/M)
^
│ ┌─────────────────┐
│ │ │
│ │ │
│ │ │
+──────────────────────────-> Time
│<->│ Higher Frequency
Phase Relationship
^
│ ┌─────────────────┐
│ │ │
│ │ │
│ │ │
+──────────────────────────-> Time
│<->│ Phase Locked
Clock Gating for Power Optimization
┌─────────────────────────────────────────────────────────────┐
│ Clock Gating Control │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Module 1 │ │ Module 2 │ │ Module 3 │ │
│ │ Clock Gate │ │ Clock Gate │ │ Clock Gate │ │
│ │ [ON] │ │ [OFF] │ │ [ON] │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Active │ │ Inactive │ │ Active │ │
│ │ (Consuming │ │ (No Power │ │ (Consuming │ │
│ │ Power) │ │ Draw) │ │ Power) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Clocks serve as the heartbeat of embedded systems, synchronizing all operations and determining system performance. Understanding clock management is essential for designing reliable, efficient, and high-performance systems.
Key Characteristics:
Proper clock management is critical for system success:
Clock system design involves balancing multiple competing requirements:
1) Clock tree documentation
2) Jitter measurement
Hardware_Fundamentals/Power_Management.md
for clock gatingEmbedded_C/Type_Qualifiers.md
for volatile access// Internal clock sources
typedef enum {
CLOCK_SOURCE_HSI, // High-speed internal oscillator
CLOCK_SOURCE_MSI, // Multi-speed internal oscillator
CLOCK_SOURCE_LSI, // Low-speed internal oscillator
CLOCK_SOURCE_LSE // Low-speed external oscillator
} clock_source_t;
// Clock source configuration
typedef struct {
clock_source_t source;
uint32_t frequency;
bool enabled;
bool stable;
} clock_source_config_t;
// Internal clock configuration
void configure_internal_clocks(void) {
// Enable HSI (High-Speed Internal)
RCC->CR |= RCC_CR_HSION;
// Wait for HSI to be ready
while (!(RCC->CR & RCC_CR_HSIRDY));
// Configure HSI frequency (typically 16MHz)
RCC->CR &= ~RCC_CR_HSITRIM;
RCC->CR |= (16 << RCC_CR_HSITRIM_Pos);
// Enable LSI (Low-Speed Internal) for watchdog
RCC->CSR |= RCC_CSR_LSION;
// Wait for LSI to be ready
while (!(RCC->CSR & RCC_CSR_LSIRDY));
}
// External clock configuration
typedef struct {
uint32_t frequency;
bool enabled;
bool bypass_mode;
} external_clock_config_t;
// Configure external clock
void configure_external_clock(external_clock_config_t *config) {
// Enable HSE (High-Speed External)
RCC->CR |= RCC_CR_HSEON;
// Wait for HSE to be ready
while (!(RCC->CR & RCC_CR_HSERDY));
// Configure bypass mode if needed
if (config->bypass_mode) {
RCC->CR |= RCC_CR_HSEBYP;
}
// Set frequency
config->frequency = get_external_clock_frequency();
}
// Clock source selection
typedef enum {
SYSCLK_SOURCE_HSI,
SYSCLK_SOURCE_HSE,
SYSCLK_SOURCE_PLL
} sysclk_source_t;
// Select system clock source
void select_system_clock_source(sysclk_source_t source) {
// Clear current source
RCC->CFGR &= ~RCC_CFGR_SW;
// Set new source
switch (source) {
case SYSCLK_SOURCE_HSI:
RCC->CFGR |= RCC_CFGR_SW_HSI;
break;
case SYSCLK_SOURCE_HSE:
RCC->CFGR |= RCC_CFGR_SW_HSE;
break;
case SYSCLK_SOURCE_PLL:
RCC->CFGR |= RCC_CFGR_SW_PLL;
break;
}
// Wait for clock source to be ready
while ((RCC->CFGR & RCC_CFGR_SWS) != (source << RCC_CFGR_SWS_Pos));
}
// PLL configuration
typedef struct {
uint32_t input_frequency;
uint32_t output_frequency;
uint8_t m_factor; // PLLM
uint16_t n_factor; // PLLN
uint8_t p_factor; // PLLP
uint8_t q_factor; // PLLQ
bool enabled;
} pll_config_t;
// PLL configuration for STM32F4
typedef struct {
uint8_t pllm; // PLLM (2-63)
uint16_t plln; // PLLN (192-432)
uint8_t pllp; // PLLP (2, 4, 6, 8)
uint8_t pllq; // PLLQ (2-15)
} stm32f4_pll_config_t;
// Calculate PLL factors
void calculate_pll_factors(uint32_t input_freq, uint32_t output_freq, pll_config_t *config) {
// Calculate N factor
config->n_factor = (output_freq * 2) / input_freq;
// Ensure N is within valid range
if (config->n_factor < 192) config->n_factor = 192;
if (config->n_factor > 432) config->n_factor = 432;
// Calculate P factor for system clock
config->p_factor = 2; // Default to 2
// Calculate Q factor for USB clock
config->q_factor = 7; // Default to 7 for 48MHz USB
}
// Configure PLL
void configure_pll(pll_config_t *config) {
// Disable PLL
RCC->CR &= ~RCC_CR_PLLON;
// Wait for PLL to be disabled
while (RCC->CR & RCC_CR_PLLRDY);
// Configure PLL factors
RCC->PLLCFGR = 0;
RCC->PLLCFGR |= (config->m_factor << RCC_PLLCFGR_PLLM_Pos);
RCC->PLLCFGR |= (config->n_factor << RCC_PLLCFGR_PLLN_Pos);
RCC->PLLCFGR |= (((config->p_factor / 2) - 1) << RCC_PLLCFGR_PLLP_Pos);
RCC->PLLCFGR |= (config->q_factor << RCC_PLLCFGR_PLLQ_Pos);
// Select PLL source
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
// Enable PLL
RCC->CR |= RCC_CR_PLLON;
// Wait for PLL to be ready
while (!(RCC->CR & RCC_CR_PLLRDY));
}
// PLL configuration example for 168MHz system clock
void configure_pll_168mhz(void) {
pll_config_t pll_config;
// Input: 8MHz HSE, Output: 168MHz
pll_config.input_frequency = 8000000;
pll_config.output_frequency = 168000000;
pll_config.m_factor = 8; // 8MHz / 8 = 1MHz
pll_config.n_factor = 336; // 1MHz * 336 = 336MHz
pll_config.p_factor = 2; // 336MHz / 2 = 168MHz
pll_config.q_factor = 7; // 336MHz / 7 = 48MHz
configure_pll(&pll_config);
}
// PLL status monitoring
typedef struct {
bool pll_locked;
uint32_t actual_frequency;
uint32_t target_frequency;
bool frequency_stable;
} pll_status_t;
// Monitor PLL status
void monitor_pll_status(pll_status_t *status) {
// Check if PLL is locked
status->pll_locked = (RCC->CR & RCC_CR_PLLRDY) ? true : false;
// Calculate actual frequency
status->actual_frequency = calculate_actual_frequency();
// Check if frequency is stable
status->frequency_stable = (status->actual_frequency == status->target_frequency);
// Log PLL status
if (!status->pll_locked) {
log_pll_error("PLL not locked");
}
}
// System clock distribution
typedef struct {
uint32_t system_clock;
uint32_t ahb_clock;
uint32_t apb1_clock;
uint32_t apb2_clock;
} clock_distribution_t;
// Configure clock distribution
void configure_clock_distribution(clock_distribution_t *clocks) {
// Configure AHB prescaler
RCC->CFGR &= ~RCC_CFGR_HPRE;
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; // No prescaling
// Configure APB1 prescaler (max 42MHz)
RCC->CFGR &= ~RCC_CFGR_PPRE1;
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; // Divide by 4
// Configure APB2 prescaler
RCC->CFGR &= ~RCC_CFGR_PPRE2;
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; // Divide by 2
// Update clock frequencies
clocks->system_clock = get_system_clock_frequency();
clocks->ahb_clock = clocks->system_clock;
clocks->apb1_clock = clocks->system_clock / 4;
clocks->apb2_clock = clocks->system_clock / 2;
}
// Peripheral clock configuration
typedef struct {
peripheral_type_t peripheral;
uint32_t frequency;
bool enabled;
} peripheral_clock_config_t;
// Enable peripheral clock
void enable_peripheral_clock(peripheral_type_t peripheral) {
switch (peripheral) {
case PERIPHERAL_GPIOA:
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
break;
case PERIPHERAL_GPIOB:
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
break;
case PERIPHERAL_UART1:
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
break;
case PERIPHERAL_TIM1:
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
break;
case PERIPHERAL_ADC1:
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
break;
}
}
// Disable peripheral clock
void disable_peripheral_clock(peripheral_type_t peripheral) {
switch (peripheral) {
case PERIPHERAL_GPIOA:
RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOAEN;
break;
case PERIPHERAL_GPIOB:
RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOBEN;
break;
case PERIPHERAL_UART1:
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN;
break;
case PERIPHERAL_TIM1:
RCC->APB2ENR &= ~RCC_APB2ENR_TIM1EN;
break;
case PERIPHERAL_ADC1:
RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN;
break;
}
}
// Clock tree structure
typedef struct {
clock_source_t source;
uint32_t source_frequency;
uint32_t pll_frequency;
uint32_t system_frequency;
uint32_t peripheral_frequencies[MAX_PERIPHERALS];
} clock_tree_t;
// Initialize clock tree
void initialize_clock_tree(clock_tree_t *tree) {
// Configure clock sources
configure_internal_clocks();
configure_external_clocks();
// Configure PLL
configure_pll_168mhz();
// Configure clock distribution
configure_clock_distribution();
// Update clock tree
tree->source = CLOCK_SOURCE_HSE;
tree->source_frequency = 8000000; // 8MHz
tree->pll_frequency = 168000000; // 168MHz
tree->system_frequency = 168000000; // 168MHz
// Configure peripheral frequencies
for (int i = 0; i < MAX_PERIPHERALS; i++) {
tree->peripheral_frequencies[i] = get_peripheral_frequency(i);
}
}
// Dynamic frequency scaling
typedef struct {
uint32_t current_frequency;
uint32_t target_frequency;
bool scaling_enabled;
} frequency_scaling_t;
// Dynamic frequency scaling
void dynamic_frequency_scaling(void) {
uint32_t cpu_load = get_cpu_load();
uint32_t target_frequency;
if (cpu_load < 30) {
// Low load - reduce frequency
target_frequency = 84000000; // 84MHz
} else if (cpu_load > 80) {
// High load - increase frequency
target_frequency = 168000000; // 168MHz
} else {
// Medium load - maintain current frequency
target_frequency = get_current_frequency();
}
// Scale frequency if needed
if (target_frequency != get_current_frequency()) {
scale_frequency(target_frequency);
}
}
// Scale frequency
void scale_frequency(uint32_t target_frequency) {
// Save current state
save_clock_state();
// Configure PLL for new frequency
configure_pll_for_frequency(target_frequency);
// Switch to new frequency
switch_system_clock(target_frequency);
// Restore state
restore_clock_state();
}
// Frequency monitoring
typedef struct {
uint32_t measured_frequency;
uint32_t expected_frequency;
uint32_t tolerance;
bool frequency_ok;
} frequency_monitor_t;
// Monitor frequency
void monitor_frequency(frequency_monitor_t *monitor) {
// Measure actual frequency
monitor->measured_frequency = measure_system_frequency();
// Check if frequency is within tolerance
uint32_t difference = abs(monitor->measured_frequency - monitor->expected_frequency);
monitor->frequency_ok = (difference <= monitor->tolerance);
// Log frequency status
if (!monitor->frequency_ok) {
log_frequency_error(monitor->measured_frequency, monitor->expected_frequency);
}
}
// Clock gating for power saving
void enable_clock_gating(void) {
// Gate unused peripheral clocks
RCC->AHB1ENR &= ~(RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN);
RCC->APB1ENR &= ~(RCC_APB1ENR_USART2EN | RCC_APB1ENR_TIM3EN);
RCC->APB2ENR &= ~(RCC_APB2ENR_USART1EN | RCC_APB2ENR_TIM1EN);
}
// Enable clock only when needed
void enable_clock_on_demand(peripheral_type_t peripheral) {
// Enable clock
enable_peripheral_clock(peripheral);
// Use peripheral
use_peripheral(peripheral);
// Disable clock after use
disable_peripheral_clock(peripheral);
}
// Clock gating management
typedef struct {
bool gpio_clocks_gated;
bool uart_clocks_gated;
bool timer_clocks_gated;
bool adc_clocks_gated;
} clock_gating_status_t;
// Manage clock gating
void manage_clock_gating(clock_gating_status_t *status) {
// Gate unused GPIO clocks
if (!gpio_used) {
gate_gpio_clocks();
status->gpio_clocks_gated = true;
}
// Gate unused UART clocks
if (!uart_used) {
gate_uart_clocks();
status->uart_clocks_gated = true;
}
// Gate unused timer clocks
if (!timer_used) {
gate_timer_clocks();
status->timer_clocks_gated = true;
}
}
// Clock status monitoring
typedef struct {
bool system_clock_stable;
bool pll_locked;
uint32_t system_frequency;
uint32_t peripheral_frequencies[MAX_PERIPHERALS];
bool all_clocks_ok;
} clock_status_t;
// Monitor clock status
void monitor_clock_status(clock_status_t *status) {
// Check system clock stability
status->system_clock_stable = check_system_clock_stability();
// Check PLL lock status
status->pll_locked = (RCC->CR & RCC_CR_PLLRDY) ? true : false;
// Measure system frequency
status->system_frequency = measure_system_frequency();
// Check peripheral frequencies
for (int i = 0; i < MAX_PERIPHERALS; i++) {
status->peripheral_frequencies[i] = measure_peripheral_frequency(i);
}
// Overall status
status->all_clocks_ok = status->system_clock_stable && status->pll_locked;
// Log status
if (!status->all_clocks_ok) {
log_clock_status_error(status);
}
}
// Clock error detection
typedef enum {
CLOCK_ERROR_NONE,
CLOCK_ERROR_PLL_UNLOCKED,
CLOCK_ERROR_FREQUENCY_DEVIATION,
CLOCK_ERROR_SOURCE_FAILURE
} clock_error_t;
// Detect clock errors
clock_error_t detect_clock_errors(void) {
// Check PLL lock
if (!(RCC->CR & RCC_CR_PLLRDY)) {
return CLOCK_ERROR_PLL_UNLOCKED;
}
// Check frequency deviation
uint32_t measured_freq = measure_system_frequency();
uint32_t expected_freq = get_expected_frequency();
uint32_t tolerance = expected_freq * 0.01; // 1% tolerance
if (abs(measured_freq - expected_freq) > tolerance) {
return CLOCK_ERROR_FREQUENCY_DEVIATION;
}
// Check clock source
if (!(RCC->CR & RCC_CR_HSERDY)) {
return CLOCK_ERROR_SOURCE_FAILURE;
}
return CLOCK_ERROR_NONE;
}
// Clock management checklist
/*
□ Configure clock sources properly
□ Set up PLL with correct factors
□ Configure clock distribution
□ Enable only needed peripheral clocks
□ Monitor clock stability
□ Implement frequency scaling
□ Use clock gating for power saving
□ Test clock configurations
□ Document clock setup
□ Handle clock errors
*/
// Good clock management example
void good_clock_management(void) {
// Initialize clock system
initialize_clock_system();
// Configure PLL
configure_pll_168mhz();
// Configure clock distribution
configure_clock_distribution();
// Enable only needed peripherals
enable_needed_peripheral_clocks();
// Monitor clock status
monitor_clock_status();
}
// PLL configuration checklist
/*
□ Calculate PLL factors correctly
□ Ensure factors are within valid ranges
□ Configure PLL source properly
□ Wait for PLL to lock
□ Monitor PLL status
□ Handle PLL errors
□ Test PLL configuration
□ Document PLL setup
□ Consider power consumption
□ Validate frequency output
*/
// Good PLL configuration
void good_pll_configuration(void) {
// Calculate PLL factors
pll_config_t pll_config;
calculate_pll_factors(8000000, 168000000, &pll_config);
// Validate factors
if (!validate_pll_factors(&pll_config)) {
// Use default configuration
use_default_pll_config();
}
// Configure PLL
configure_pll(&pll_config);
// Wait for PLL to lock
while (!(RCC->CR & RCC_CR_PLLRDY));
// Verify frequency
verify_pll_frequency();
}
// WRONG: Incorrect PLL factors
void bad_pll_configuration(void) {
// Incorrect factors - may cause instability
RCC->PLLCFGR = 0;
RCC->PLLCFGR |= (1 << RCC_PLLCFGR_PLLM_Pos); // Too low
RCC->PLLCFGR |= (500 << RCC_PLLCFGR_PLLN_Pos); // Too high
RCC->PLLCFGR |= (1 << RCC_PLLCFGR_PLLP_Pos); // Invalid
}
// CORRECT: Proper PLL configuration
void good_pll_configuration(void) {
// Calculate correct factors
pll_config_t config;
calculate_pll_factors(8000000, 168000000, &config);
// Validate factors
if (validate_pll_factors(&config)) {
configure_pll(&config);
}
}
// WRONG: No clock configuration
void bad_no_clock_config(void) {
// Use default clocks without configuration
// May result in incorrect frequencies
}
// CORRECT: Proper clock configuration
void good_clock_config(void) {
// Configure all clock sources
configure_internal_clocks();
configure_external_clocks();
// Configure PLL
configure_pll_168mhz();
// Configure clock distribution
configure_clock_distribution();
}
// WRONG: Always enable all clocks
void bad_clock_gating(void) {
// Enable all peripheral clocks
RCC->AHB1ENR = 0xFFFFFFFF;
RCC->APB1ENR = 0xFFFFFFFF;
RCC->APB2ENR = 0xFFFFFFFF;
}
// CORRECT: Enable only needed clocks
void good_clock_gating(void) {
// Enable only needed peripheral clocks
enable_peripheral_clock(PERIPHERAL_GPIOA);
enable_peripheral_clock(PERIPHERAL_UART1);
enable_peripheral_clock(PERIPHERAL_TIM1);
}
// Basic clock configuration
void basic_clock_configuration(void) {
// Enable HSE
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY));
// Configure PLL for 168MHz
RCC->PLLCFGR = 0;
RCC->PLLCFGR |= (8 << RCC_PLLCFGR_PLLM_Pos); // 8MHz / 8 = 1MHz
RCC->PLLCFGR |= (336 << RCC_PLLCFGR_PLLN_Pos); // 1MHz * 336 = 336MHz
RCC->PLLCFGR |= (0 << RCC_PLLCFGR_PLLP_Pos); // 336MHz / 2 = 168MHz
RCC->PLLCFGR |= (7 << RCC_PLLCFGR_PLLQ_Pos); // 336MHz / 7 = 48MHz
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
// Enable PLL
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
// Switch to PLL
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}
// Advanced clock management
typedef struct {
uint32_t system_frequency;
uint32_t peripheral_frequencies[MAX_PERIPHERALS];
bool dynamic_scaling_enabled;
bool power_optimization_enabled;
} advanced_clock_config_t;
void advanced_clock_management(void) {
advanced_clock_config_t config;
// Initialize clock system
initialize_clock_system();
// Configure for high performance
config.system_frequency = 168000000;
config.dynamic_scaling_enabled = true;
config.power_optimization_enabled = true;
// Apply configuration
apply_clock_configuration(&config);
// Start monitoring
start_clock_monitoring();
// Main loop with dynamic scaling
while (1) {
// Dynamic frequency scaling
if (config.dynamic_scaling_enabled) {
dynamic_frequency_scaling();
}
// Power optimization
if (config.power_optimization_enabled) {
optimize_clock_power();
}
// Monitor clock status
monitor_clock_status();
// Process tasks
process_tasks();
}
}
// Power-optimized clock configuration
void power_optimized_clock_config(void) {
// Configure for low power
configure_low_power_clocks();
// Enable clock gating
enable_clock_gating();
// Configure dynamic frequency scaling
configure_dynamic_frequency_scaling();
// Main loop with power optimization
while (1) {
// Check system load
uint32_t load = get_system_load();
if (load < 20) {
// Low load - reduce frequency
set_system_frequency(84000000); // 84MHz
} else if (load > 80) {
// High load - increase frequency
set_system_frequency(168000000); // 168MHz
}
// Process tasks
process_tasks();
// Sleep if idle
if (is_system_idle()) {
enter_sleep_mode();
}
}
}
void battery_optimized_clock_system(void) {
// Configure for battery operation
configure_battery_optimized_clocks();
while (1) {
// Monitor battery level
uint32_t battery_level = get_battery_level();
// Scale frequency based on battery
if (battery_level < 30) {
set_system_frequency(84000000); // Low frequency
} else {
set_system_frequency(168000000); // High frequency
}
// Process tasks
process_tasks();
}
}
void clock_monitoring_system(void) {
// Initialize monitoring
initialize_clock_monitoring();
while (1) {
// Monitor clock status
clock_status_t status;
monitor_clock_status(&status);
// Handle errors
if (!status.all_clocks_ok) {
handle_clock_error(&status);
}
// Log status
log_clock_status(&status);
// Wait for next check
delay_ms(CLOCK_MONITOR_INTERVAL);
}
}
Next Topic: Reset Management → Hardware Abstraction Layer