Module clocks

Source
Expand description

STM32F4xx clock driver

This crate provides drivers for various clocks: HSI, PLL, system, AHB, APB1 and APB2. This documentation applies to the system clock, AHB, APB1 and APB2. For in-detail documentation for HSI and PLL, check their documentation.

§Features

  • Dynamic system source
  • Hardware limits verification for AHB, APB1 and APB2.
  • Prescaler configuration for AHB, APB1 and APB2.
  • Support for MCO1

§Limitations

  • Precision of 1MHz
  • No support for MCO2

§Usage 1

First, import the following enums:

// Assuming a STM32F429 chip. Change this to correspond to the chip model.
use stm32f429zi::rcc::APBPrescaler;
use stm32f429zi::rcc::AHBPrescaler;
use stm32f429zi::rcc::SysClockSource;

A reference to the crate::clocks::Clocks is needed:

// Add this in board main.rs
let clocks = &peripherals.stm32f4.clocks;

§Retrieve the AHB frequency:

let ahb_frequency = clocks.get_ahb_frequency_mhz();
debug!("Current AHB frequency is {}MHz", ahb_frequency);

§Retrieve the AHB prescaler:

let ahb_prescaler = clocks.get_ahb_prescaler();
debug!("Current AHB prescaler is {:?}", ahb_prescaler);

NOTE: If one wishes to get the usize equivalent value of crate::clocks::Clocks::get_ahb_prescaler, to use in computations for example, they must use crate::rcc::AHBPrescaler.into() method:

let ahb_prescaler_usize: usize = clocks.get_ahb_prescaler().into();
if ahb_prescaler_usize > 8 {
    /* Do something */
}

§Set the AHB prescaler

clocks.set_ahb_prescaler(AHBPrescaler::DivideBy4);

§APB1 and APB2 prescalers

APB1 and APB2 prescalers are configured in a similar way as AHB prescaler, except that the corresponding enum is APBPrescaler.

§Retrieve the system clock frequency:

let sys_frequency = clocks.get_sys_clock_frequency_mhz();
debug!("Current system clock frequency is {}MHz", sys_frequency);

§Retrieve the system clock source:

let sys_source = clocks.get_sys_clock_source();
debug!("Current system clock source is {:?}", sys_source);

§Change the system clock source to PLL:

Changing the system clock source is a fastidious task because of AHB, APB1 and APB2 limits, which are chip-dependent. This example assumes a STM32F429 chip.

First, get a reference to the PLL

let pll = &peripherals.stm32f4.clocks.pll;

Then, configure its frequency and enable it

pll.set_frequency_mhz(50);
pll.enable();

STM32F429 maximum APB1 frequency is 45MHz, which is computed as following: freq_APB1 = freq_sys / AHB_prescaler / APB1_prescaler Default prescaler values are 1, which gives an frequency of 50MHz without modifying the APB1 prescaler. As such, the APB1 prescaler must be changed.

clocks.set_apb1_prescaler(APBPrescaler::DivideBy2);

Since the APB1 frequency limit is satisfied now, the system clock source can be safely changed.

clocks.set_sys_clock_source(SysClockSource::PLL);

§Another example of changing the system clock to PLL for STM32F429:

As before, Pll clock is configured and enabled.

pll.set_frequency_mhz(100);
pll.enable();

Because of the high frequency of the PLL clock, both APB1 and APB2 prescalers must be configured.

clocks.set_apb1_prescaler(APBPrescaler::DivideBy4);
clocks.set_apb2_prescaler(APBPrescaler::DivideBy2);

As an alternative, the AHB prescaler could be configured to change both APB1 and APB2 frequencies.

// Changing it to 2 wouldn't work, because it would give a frequency of 50MHz for the APB1.
clocks.set_ahb_prescaler(APBPrescaler::DivideBy4);

Now, it’s safe to change the system clock source:

clocks.set_sys_clock_source(SysClockSource::PLL);

  1. For the purpose of brevity, any error checking has been removed. 

Modules§

tests
Tests for clocks functionalities

Structs§

Clocks
Main struct for configuring on-board clocks.

Traits§

Stm32f4Clocks
Stm32f4Clocks trait