cube2rust/
rcc.rs

1use crate::*;
2
3pub fn get_rcc(config: &ConfigParams<'_>) -> anyhow::Result<RCC> {
4    let rcc_params = config
5        .get("RCC")
6        .ok_or_else(|| anyhow!("No RCC configuration found"))?;
7
8    // SYSCLK Config
9    let sys_clock_source = parse_optional_param(rcc_params, "SYSCLKSource")?;
10    let pll_clock_source = parse_optional_param(rcc_params, "PLLSourceVirtual")?;
11    // ioc file does not set SYSCLKFreq_VALUE if it's HSI 8Mhz
12    let sysclk_freq = parse_optional_u32(rcc_params, "SYSCLKFreq_VALUE")?;
13    let hclk_freq = parse_optional_u32(rcc_params, "HCLKFreq_Value")?;
14    let apb1_freq = parse_optional_u32(rcc_params, "APB1Freq_Value")?;
15
16    let clock_source = get_clock_source(&sys_clock_source, &pll_clock_source, config)?;
17
18    Ok(RCC {
19        clock_source,
20        sysclk_freq,
21        hclk_freq,
22        apb1_freq,
23    })
24}
25
26fn get_clock_source(
27    sys_clock_source: &Option<SYSCLKSourceType>,
28    pll_clock_source: &Option<PLLSourceType>,
29    config: &ConfigParams<'_>,
30) -> anyhow::Result<ClockSource> {
31    match sys_clock_source {
32        None | Some(SYSCLKSourceType::RCC_SYSCLKSOURCE_HSI) => Ok(ClockSource::HSI),
33        Some(SYSCLKSourceType::RCC_SYSCLKSOURCE_HSI48) => Ok(ClockSource::HSI48),
34        Some(SYSCLKSourceType::RCC_SYSCLKSOURCE_HSE) => Ok(ClockSource::HSE(get_hse_mode(config)?)),
35        Some(SYSCLKSourceType::RCC_SYSCLKSOURCE_PLLCLK) => match pll_clock_source {
36            None | Some(PLLSourceType::RCC_PLLSOURCE_HSI) => Ok(ClockSource::HSI),
37            Some(PLLSourceType::RCC_PLLSOURCE_HSI48) => Ok(ClockSource::HSI48),
38            Some(PLLSourceType::RCC_PLLSOURCE_HSE) => Ok(ClockSource::HSE(get_hse_mode(config)?)),
39        },
40    }
41}
42
43fn get_hse_mode(config: &ConfigParams<'_>) -> anyhow::Result<HSEMode> {
44    // RCC existance was checked already
45    let rcc_params = config.get("RCC").unwrap();
46
47    // get mode from pin configuration
48    let &mode = config
49        .get("PF0-OSC_IN")
50        .map(|pfo| pfo.get("Mode"))
51        .ok_or_else(|| anyhow!("PF0-OSC_IN required"))?
52        .ok_or_else(|| anyhow!("PF0-OSC_IN.Mode required"))?;
53    // get freq
54    let freq = parse_mandatory_u32(rcc_params, "VCOOutput2Freq_Value")?;
55
56    let mode: anyhow::Result<HSEMode> = match mode {
57        "HSE-External-Oscillator" => Ok(HSEMode::NotBypassed(freq)),
58        "HSE-External-Clock-Source" => Ok(HSEMode::Bypassed(freq)),
59        _ => bail!("Unknown clock source"),
60    };
61    mode.context("Parsing of external clock source")
62}
63
64#[derive(Debug)]
65pub struct RCC {
66    // TODO USBClockSource
67    // TODO CRS
68    pub clock_source: ClockSource,
69    pub sysclk_freq: Option<u32>,
70    pub hclk_freq: Option<u32>,
71    pub apb1_freq: Option<u32>,
72}
73
74#[derive(Debug, PartialEq)]
75pub enum ClockSource {
76    HSI,
77    HSI48,
78    HSE(HSEMode),
79}
80
81#[derive(Debug, PartialEq)]
82pub enum HSEMode {
83    NotBypassed(u32),
84    Bypassed(u32),
85}
86
87parameter!(
88    SYSCLKSourceType,
89    [
90        RCC_SYSCLKSOURCE_HSI,
91        RCC_SYSCLKSOURCE_HSI48,
92        RCC_SYSCLKSOURCE_PLLCLK,
93        RCC_SYSCLKSOURCE_HSE
94    ],
95    default = RCC_SYSCLKSOURCE_HSI
96);
97
98parameter!(
99    PLLSourceType,
100    [RCC_PLLSOURCE_HSI, RCC_PLLSOURCE_HSI48, RCC_PLLSOURCE_HSE]
101);