Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

RFC: Automatic clock configuration #48

Open
mgottschlag opened this issue Feb 20, 2022 · 2 comments
Open

RFC: Automatic clock configuration #48

mgottschlag opened this issue Feb 20, 2022 · 2 comments

Comments

@mgottschlag
Copy link
Contributor

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);
        }
    }
}
@David-OConnor
Copy link

David-OConnor commented Mar 26, 2022

You could provide one or more sensible defaults, for users who don't want to look up the clock tree to get started. (Although looking up the clock tree will always happen for non-trivial projects, and Cube's interactive tool is nicer than looking in the RM)

I think the API described above will lead to the user to enter invalid configs with no feedback until later. (compile time? run time?) There are too many DOF in clock trees for this approach to make sense.

@agalakhov
Copy link

Looks good, but this could be implemented as a procedural macro to be called directly from the user's code without intermediate file generation.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants