STM Week 2: Clock & Power Management

STM

Adapted from 1

Concepts

1. Clock Sources

a. HSI (High-Speed Internal Oscillator)

  • 16 MHz RC oscillator. Low accuracy (±1%) but requires no external components
  • Used as a fallback if HSE fails

b. HSE (High-Speed External Oscillator)

  • External crystal (4–26 MHz). High accuracy (±0.1%)
  • Required for achieving maximum clock speeds (e.g., 168 MHz)

c. PLL (Phase-Locked Loop)

  • Multiplies HSE/HSI frequency. Example: HSE (8 MHz) → PLL (×21) → 168 MHz
  • Divided into PLLM (input divider), PLLN (multiplier), and PLLP (output divider)

2. Power Modes

  1. Run Mode: Full power (CPU, peripherals active)
  2. Sleep Mode: CPU halted, peripherals active. Wake via interrupts
  3. Stop Mode: Core voltage domain powered off. Wake via external interrupts or RTC

3. Clock Tree Analysis

  • SYSCLK: System clock (max 168 MHz). Sources: HSI, HSE, PLL
  • AHB Prescaler: Divides SYSCLK for AHB bus (e.g., 168 MHz → 168 MHz)
  • APB1/APB2 Prescalers: Divides AHB for peripherals (APB1 max 42 MHz, APB2 max 84 MHz)

Example Code

// system_stm32f4xx.c (auto-generated by STM32CubeMX)
void SystemClock_Config(void) {
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  // Configure HSE (8 MHz) → PLL → 168 MHz
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;     // HSE (8 MHz) / 8 = 1 MHz
  RCC_OscInitStruct.PLL.PLLN = 336;   // 1 MHz × 336 = 336 MHz
  RCC_OscInitStruct.PLL.PLLP = 2;      // 336 MHz / 2 = 168 MHz (SYSCLK)
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  // Configure clock dividers
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
                                RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;     // 168 MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;      // 42 MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;      // 84 MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

Questions

  1. What happens if APB1’s clock exceeds 42 MHz?
  2. How does Stop mode differ from Sleep mode?
  3. If HSE fails, which clock source does the STM32 use?

Project: Setting STM Clock Speed

Configure the STM32 to run at 168 MHz using STM32CubeMX. Validate timing accuracy using bsp_delay.c and an oscilloscope.

Steps

  1. Clock Configuration:
    • Set HSE as the clock source
    • Configure PLL to generate 168 MHz
    • Adjust AHB/APB prescalers for safe peripheral operation
  2. Delay Module: Use bsp_delay.c to create a 1 Hz signal (500 ms high, 500 ms low) on a GPIO pin
  3. Measure the GPIO pin’s frequency with an oscilloscope (expected: 1 Hz ±1%)

Walkthrough

Step 1: Configure Clock in STM32CubeMX

  1. Open STM32CubeMX → New Project > Select your STM32F4 MCU
  2. Clock Configuration Tab:
    • Set HSE to “Crystal/Ceramic Resonator” (assumes 8 MHz external crystal)
    • Set PLL Source Mux to HSE
    • Configure PLLM = 8, PLLN = 336, PLLP = 2 → SYSCLK = 168 MHz
    • Set AHB Prescaler = 1 (168 MHz), APB1 = 4 (42 MHz), APB2 = 2 (84 MHz)
  3. Generate code with “Project → Generate Code”

Step 2: Implement Delay Module

// bsp_delay.c  
#include "stm32f4xx_hal.h"  

void delay_ms(uint32_t ms) {  
  uint32_t start = HAL_GetTick();  
  while (HAL_GetTick() - start < ms);  
}  

// main.c  
int main(void) {  
  HAL_Init();  
  SystemClock_Config();  
  __HAL_RCC_GPIOA_CLK_ENABLE();  
  GPIO_InitTypeDef GPIO_InitStruct = {0};  
  GPIO_InitStruct.Pin = GPIO_PIN_5;  
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  

  while (1) {  
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);  
    delay_ms(500);  
  }  
}  

Step 3: Oscilloscope Verification

  • Connect the oscilloscope probe to GPIO Pin PA5
  • Measure period: Should be 1 sec (500 ms high + 500 ms low)
  • If timing is incorrect, check PLL settings and HAL_RCC_ClockConfig() in system_stm32f4xx.c

Debugging

GPIO toggle is too slow

  • Verify SystemCoreClock in system_stm32f4xx.c is 168000000

Code crashes after clock configuration

  • Ensure Flash Latency is set to 5 wait states (required for 168 MHz)

No signal on oscilloscope

  • Confirm GPIO pin is configured as output and oscilloscope ground is connected.

Dictionary

  • HSI/HSE: Internal/external clock sources
  • PLL: Clock multiplier for higher frequencies
  • SYSCLK: Primary system clock
  • AHB/APB: Buses for peripherals and memory
  • Prescaler: Divides clock frequency

Resources

  1. STM32 Clock Configuration Guide
  2. STM32 Clock System Introduction
  3. Oscilloscope Basics Tutorial
  4. Everything about Oscilloscopes Playlist

Answers to Questions

  1. Peripheral registers may corrupt, leading to undefined behavior
  2. Stop mode turns off the core voltage domain, reducing power further but requiring longer wake-up time
  3. HSI (16 MHz)

Credits

  1. Deepseek.