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 let sys_clock_source = parse_optional_param(rcc_params, "SYSCLKSource")?;
10 let pll_clock_source = parse_optional_param(rcc_params, "PLLSourceVirtual")?;
11 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 let rcc_params = config.get("RCC").unwrap();
46
47 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 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 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);