Skip to content

Commit 404a69f

Browse files
authored
Merge pull request embassy-rs#6310 from usbalbin/c5-rcc
C5 - Work on RCC config
2 parents 9e31679 + bb92bdd commit 404a69f

3 files changed

Lines changed: 190 additions & 3 deletions

File tree

embassy-stm32/src/rcc/c5.rs

Lines changed: 140 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,145 @@
1+
use stm32_metapac::FLASH;
2+
3+
use crate::pac::RCC;
14
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler, Sw as Sysclk};
5+
use crate::time::Hertz;
6+
7+
/// HSI speed
8+
pub const HSI_FREQ: Hertz = Hertz(144_000_000);
29

310
/// Configuration of the core clocks
411
#[non_exhaustive]
5-
#[derive(Clone, Copy, Default)]
6-
pub struct Config {}
12+
#[derive(Clone, Copy)]
13+
pub struct Config {
14+
/// Enable HSI full speed tap (144MHz)
15+
pub hsi: bool,
16+
17+
/// Enable HSI Div 3 tap (48MHz)
18+
pub hsi_div3: bool,
19+
20+
/// System Clock Configuration
21+
pub sys: Sysclk,
22+
23+
pub ahb_pre: AHBPrescaler,
24+
pub apb1_pre: APBPrescaler,
25+
pub apb2_pre: APBPrescaler,
26+
pub apb3_pre: APBPrescaler,
27+
}
28+
29+
impl Config {
30+
pub const fn new() -> Self {
31+
Self {
32+
hsi: false,
33+
hsi_div3: true,
34+
sys: Sysclk::Hsidiv3,
35+
ahb_pre: AHBPrescaler::Div1,
36+
apb1_pre: APBPrescaler::Div1,
37+
apb2_pre: APBPrescaler::Div1,
38+
apb3_pre: APBPrescaler::Div1,
39+
}
40+
}
41+
}
42+
43+
impl Default for Config {
44+
fn default() -> Self {
45+
Self::new()
46+
}
47+
}
48+
49+
pub(crate) unsafe fn init(config: Config) {
50+
// Turn on clock sources. Keep hsidiv3(the default)
51+
// on for now since that will be used during init
52+
RCC.cr().modify(|w| {
53+
w.set_hsion(config.hsi);
54+
w.set_hsidiv3on(true);
55+
});
56+
57+
if config.hsi {
58+
while !RCC.cr().read().hsirdy() {}
59+
}
60+
if config.hsi_div3 {
61+
while !RCC.cr().read().hsidiv3rdy() {}
62+
}
63+
64+
// Configure HSI
65+
let hsi = config.hsi.then_some(HSI_FREQ);
66+
let hsi_div3 = config.hsi_div3.then_some(Hertz(HSI_FREQ.0 / 3));
67+
68+
RCC.cfgr().modify(|w| w.set_sw(config.sys));
69+
while RCC.cfgr().read().sws() != config.sys {}
70+
71+
// Turn off unused clock sources
72+
RCC.cr().modify(|w| {
73+
w.set_hsion(config.hsi);
74+
w.set_hsidiv3on(config.hsi_div3);
75+
});
76+
77+
// TODO: Configure HSE
78+
79+
// Configure sysclk
80+
let sys = match config.sys {
81+
Sysclk::Hsidiv3 => unwrap!(hsi_div3),
82+
Sysclk::Hsi => unwrap!(hsi),
83+
Sysclk::Hse => unimplemented!(),
84+
Sysclk::Psi => unimplemented!(),
85+
};
86+
assert!(max::SYSCLK.contains(&sys));
87+
88+
let hclk = sys / config.ahb_pre;
89+
assert!(max::HCLK.contains(&hclk));
90+
91+
let apb1 = hclk / config.apb1_pre;
92+
assert!(max::PCLK.contains(&apb1));
93+
94+
let apb2 = hclk / config.apb2_pre;
95+
assert!(max::PCLK.contains(&apb2));
96+
97+
let apb3 = hclk / config.apb3_pre;
98+
assert!(max::PCLK.contains(&apb3));
99+
100+
flash_setup(hclk);
101+
102+
//let rtc = config.ls.init();
103+
104+
RCC.cfgr2().modify(|w| w.set_hpre(config.ahb_pre));
105+
while RCC.cfgr2().read().hpre() != config.ahb_pre {}
106+
107+
RCC.cfgr2().modify(|w| {
108+
w.set_ppre1(config.apb1_pre);
109+
w.set_ppre2(config.apb2_pre);
110+
w.set_ppre3(config.apb3_pre);
111+
});
112+
}
113+
114+
fn flash_setup(hclk: Hertz) {
115+
let (latency, wrhighfreq) = match hclk.0 {
116+
..=34_000_000 => (0, 0b00),
117+
..=68_000_000 => (1, 0b00),
118+
..=102_000_000 => (2, 0b01),
119+
..=136_000_000 => (3, 0b01),
120+
..=144_000_000 => (4, 0b10),
121+
_ => unreachable!(),
122+
};
123+
let latency = latency.into();
124+
125+
debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq);
126+
127+
FLASH.acr().write(|w| {
128+
w.set_wrhighfreq(wrhighfreq);
129+
w.set_latency(latency);
130+
});
131+
while FLASH.acr().read().latency() != latency {}
132+
}
133+
134+
mod max {
135+
use core::ops::RangeInclusive;
136+
137+
use crate::time::Hertz;
7138

8-
pub(crate) unsafe fn init(_config: Config) {}
139+
// pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(50_000_000);
140+
// pub(crate) const HSE_BYP_ANALOG: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(50_000_000);
141+
// pub(crate) const HSE_BYP_DIGITAL: RangeInclusive<Hertz> = Hertz(0)..=Hertz(50_000_000);
142+
pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(144_000_000);
143+
pub(crate) const PCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(144_000_000);
144+
pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(144_000_000);
145+
}

examples/stm32c5/src/bin/hsi.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use defmt::*;
5+
use embassy_executor::Spawner;
6+
use embassy_stm32::{Config, rcc};
7+
use {defmt_rtt as _, panic_probe as _};
8+
9+
#[embassy_executor::main]
10+
async fn main(_spawner: Spawner) {
11+
let config = {
12+
let mut config = Config::default();
13+
config.rcc.hsi = true;
14+
config.rcc.hsi_div3 = false;
15+
config.rcc.sys = rcc::Sysclk::Hsi;
16+
17+
config
18+
};
19+
20+
let _p = embassy_stm32::init(config);
21+
22+
info!("Sys clocked by HSI running at 144MHz!");
23+
24+
loop {}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use defmt::*;
5+
use embassy_executor::Spawner;
6+
use embassy_stm32::{Config, rcc};
7+
use {defmt_rtt as _, panic_probe as _};
8+
9+
#[embassy_executor::main]
10+
async fn main(_spawner: Spawner) {
11+
let config = {
12+
let mut config = Config::default();
13+
config.rcc.hsi = false;
14+
config.rcc.hsi_div3 = true;
15+
config.rcc.sys = rcc::Sysclk::Hsidiv3;
16+
17+
config
18+
};
19+
20+
let _p = embassy_stm32::init(config);
21+
22+
info!("Sys clocked by HSI/3 running at 48MHz!");
23+
24+
loop {}
25+
}

0 commit comments

Comments
 (0)