Skip to content

RFC: Automatic clock configuration #48

@mgottschlag

Description

@mgottschlag

The HAL currently expects the user to manually select a suitable clock configuration. Usually, this is done using, for example, STM32CubeMX.

I would argue that this is not what most users want - they do not want to download a comparably large additional software package and click through its interface whenever their clock requirements change. I would argue that it should be possible to specify the required frequencies somewhere in the project and have some tool automatically generate the required clock configuration.

Other HALs (stm32f4xx-hal, for example) implement a more comfortable interface which calculates the PLL configurations at runtime. This approach is suboptimal as it increases code size and startup time - clock configuration calculation should ideally be done at compile time.

I just hacked a library together (mgottschlag/stm32g4xx-clkcfg) together which basically performs an exhaustive search over all possible clock configurations, selecting the best according to the requirements specified by the user. The library then generates a code fragment that can be included via include!().

What do you think of this approach? Should something like that be integrated into the HAL or at least referenced by the README?

Currently, the library has its own copy of stm32g4xx-hals config structs and will therefore break whenever those are changed, so some refactoring is necessary to make the approach more robust.

Usage Example

use std::io::stdout;

use embedded_time::rate::*;
use stm32g4xx_clkcfg::{ClockRequirements, Frequencies};

fn main() {
    println!("Configuration for the highest possible sysclk with a 48MHz USB clock from a 24 MHz crystal:");
    let req = ClockRequirements::new()
        .hse(24_000_000.Hz())
        .sysclk(170_000_000.Hz())
        .usb_rng_clk(true);
    match req.resolve(false) {
        Ok((cfg, freqs)) => {
            cfg.write_code(&mut stdout()).unwrap();
	    // _freqs holds the frequencies generated by the configuration.
        }
        Err(e) => {
            println!("Error: {:?}", e);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions