aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-02-02 20:48:39 +0000
committerGitHub <[email protected]>2024-02-02 20:48:39 +0000
commita099084bffe621f45fc798cec26164b96a8984aa (patch)
treebdfeee2d77079deeb7106446307bace85ec0cbf2
parent9e704e622abc348d63c061425c9699fbff9ca7d2 (diff)
parent92690d8590301360cca8889fe9d118eb3cc30202 (diff)
Merge pull request #2520 from Ecco/stm32wba-rcc-v3
Migrate STM32WBA to RCCv3
-rw-r--r--embassy-stm32/src/rcc/wba.rs193
1 files changed, 103 insertions, 90 deletions
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
index 1d04d480a..dfa236484 100644
--- a/embassy-stm32/src/rcc/wba.rs
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -1,5 +1,8 @@
1use stm32_metapac::rcc::vals::{Pllsrc, Sw}; 1pub use crate::pac::pwr::vals::Vos as VoltageScale;
2 2use crate::pac::rcc::regs::Cfgr1;
3pub use crate::pac::rcc::vals::{
4 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as ClockSrc,
5};
3use crate::pac::{FLASH, RCC}; 6use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 7use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 8use crate::time::Hertz;
@@ -9,82 +12,108 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
9// HSE speed 12// HSE speed
10pub const HSE_FREQ: Hertz = Hertz(32_000_000); 13pub const HSE_FREQ: Hertz = Hertz(32_000_000);
11 14
12pub use crate::pac::pwr::vals::Vos as VoltageScale; 15#[derive(Clone, Copy, Eq, PartialEq)]
13pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 16pub struct Hse {
14 17 pub prescaler: HsePrescaler,
15#[derive(Copy, Clone)]
16pub enum ClockSrc {
17 HSE,
18 HSI,
19}
20
21#[derive(Clone, Copy, Debug)]
22pub enum PllSource {
23 HSE,
24 HSI,
25}
26
27impl Into<Pllsrc> for PllSource {
28 fn into(self) -> Pllsrc {
29 match self {
30 PllSource::HSE => Pllsrc::HSE,
31 PllSource::HSI => Pllsrc::HSI,
32 }
33 }
34}
35
36impl Into<Sw> for ClockSrc {
37 fn into(self) -> Sw {
38 match self {
39 ClockSrc::HSE => Sw::HSE,
40 ClockSrc::HSI => Sw::HSI,
41 }
42 }
43} 18}
44 19
20/// Clocks configuration
45pub struct Config { 21pub struct Config {
22 // base clock sources
23 pub hsi: bool,
24 pub hse: Option<Hse>,
25
26 // sysclk, buses.
46 pub mux: ClockSrc, 27 pub mux: ClockSrc,
47 pub ahb_pre: AHBPrescaler, 28 pub ahb_pre: AHBPrescaler,
48 pub apb1_pre: APBPrescaler, 29 pub apb1_pre: APBPrescaler,
49 pub apb2_pre: APBPrescaler, 30 pub apb2_pre: APBPrescaler,
50 pub apb7_pre: APBPrescaler, 31 pub apb7_pre: APBPrescaler,
32
33 // low speed LSI/LSE/RTC
51 pub ls: super::LsConfig, 34 pub ls: super::LsConfig,
35
36 pub adc_clock_source: AdcClockSource,
37
38 pub voltage_scale: VoltageScale,
52} 39}
53 40
54impl Default for Config { 41impl Default for Config {
55 fn default() -> Self { 42 #[inline]
56 Self { 43 fn default() -> Config {
44 Config {
45 hse: None,
46 hsi: true,
57 mux: ClockSrc::HSI, 47 mux: ClockSrc::HSI,
58 ahb_pre: AHBPrescaler::DIV1, 48 ahb_pre: AHBPrescaler::DIV1,
59 apb1_pre: APBPrescaler::DIV1, 49 apb1_pre: APBPrescaler::DIV1,
60 apb2_pre: APBPrescaler::DIV1, 50 apb2_pre: APBPrescaler::DIV1,
61 apb7_pre: APBPrescaler::DIV1, 51 apb7_pre: APBPrescaler::DIV1,
62 ls: Default::default(), 52 ls: Default::default(),
53 adc_clock_source: AdcClockSource::HCLK1,
54 voltage_scale: VoltageScale::RANGE2,
63 } 55 }
64 } 56 }
65} 57}
66 58
59fn hsi_enable() {
60 RCC.cr().modify(|w| w.set_hsion(true));
61 while !RCC.cr().read().hsirdy() {}
62}
63
67pub(crate) unsafe fn init(config: Config) { 64pub(crate) unsafe fn init(config: Config) {
68 let sys_clk = match config.mux { 65 // Switch to HSI to prevent problems with PLL configuration.
69 ClockSrc::HSE => { 66 if !RCC.cr().read().hsion() {
70 RCC.cr().write(|w| w.set_hseon(true)); 67 hsi_enable()
71 while !RCC.cr().read().hserdy() {} 68 }
69 if RCC.cfgr1().read().sws() != ClockSrc::HSI {
70 // Set HSI as a clock source, reset prescalers.
71 RCC.cfgr1().write_value(Cfgr1::default());
72 // Wait for clock switch status bits to change.
73 while RCC.cfgr1().read().sws() != ClockSrc::HSI {}
74 }
72 75
73 HSE_FREQ 76 // Set voltage scale
74 } 77 crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale));
75 ClockSrc::HSI => { 78 while !crate::pac::PWR.vosr().read().vosrdy() {}
76 RCC.cr().write(|w| w.set_hsion(true));
77 while !RCC.cr().read().hsirdy() {}
78 79
79 HSI_FREQ 80 let rtc = config.ls.init();
80 } 81
82 let hsi = config.hsi.then(|| {
83 hsi_enable();
84
85 HSI_FREQ
86 });
87
88 let hse = config.hse.map(|hse| {
89 RCC.cr().write(|w| {
90 w.set_hseon(true);
91 w.set_hsepre(hse.prescaler);
92 });
93 while !RCC.cr().read().hserdy() {}
94
95 HSE_FREQ
96 });
97
98 let sys_clk = match config.mux {
99 ClockSrc::HSE => hse.unwrap(),
100 ClockSrc::HSI => hsi.unwrap(),
101 ClockSrc::_RESERVED_1 => unreachable!(),
102 ClockSrc::PLL1_R => todo!(),
81 }; 103 };
82 104
83 // TODO make configurable 105 assert!(sys_clk.0 <= 100_000_000);
84 let power_vos = VoltageScale::RANGE1; 106
107 let hclk1 = sys_clk / config.ahb_pre;
108 let hclk2 = hclk1;
109 let hclk4 = hclk1;
110 // TODO: hclk5
111 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
112 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
113 let (pclk7, _) = super::util::calc_pclk(hclk1, config.apb7_pre);
85 114
86 // states and programming delay 115 // Set flash wait states
87 let wait_states = match power_vos { 116 let flash_latency = match config.voltage_scale {
88 VoltageScale::RANGE1 => match sys_clk.0 { 117 VoltageScale::RANGE1 => match sys_clk.0 {
89 ..=32_000_000 => 0, 118 ..=32_000_000 => 0,
90 ..=64_000_000 => 1, 119 ..=64_000_000 => 1,
@@ -99,13 +128,24 @@ pub(crate) unsafe fn init(config: Config) {
99 }, 128 },
100 }; 129 };
101 130
102 FLASH.acr().modify(|w| { 131 FLASH.acr().modify(|w| w.set_latency(flash_latency));
103 w.set_latency(wait_states); 132 while FLASH.acr().read().latency() != flash_latency {}
104 }); 133
134 // Set sram wait states
135 let _sram_latency = match config.voltage_scale {
136 VoltageScale::RANGE1 => 0,
137 VoltageScale::RANGE2 => match sys_clk.0 {
138 ..=12_000_000 => 0,
139 ..=16_000_000 => 1,
140 _ => 2,
141 },
142 };
143 // TODO: Set the SRAM wait states
105 144
106 RCC.cfgr1().modify(|w| { 145 RCC.cfgr1().modify(|w| {
107 w.set_sw(config.mux.into()); 146 w.set_sw(config.mux);
108 }); 147 });
148 while RCC.cfgr1().read().sws() != config.mux {}
109 149
110 RCC.cfgr2().modify(|w| { 150 RCC.cfgr2().modify(|w| {
111 w.set_hpre(config.ahb_pre); 151 w.set_hpre(config.ahb_pre);
@@ -113,45 +153,18 @@ pub(crate) unsafe fn init(config: Config) {
113 w.set_ppre2(config.apb2_pre); 153 w.set_ppre2(config.apb2_pre);
114 }); 154 });
115 155
116 RCC.cfgr3().modify(|w| { 156 RCC.ccipr3().modify(|w| w.set_adcsel(config.adc_clock_source));
117 w.set_ppre7(config.apb7_pre);
118 });
119
120 let ahb_freq = sys_clk / config.ahb_pre;
121 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
122 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
123 pre => {
124 let freq = ahb_freq / pre;
125 (freq, freq * 2u32)
126 }
127 };
128 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
129 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
130 pre => {
131 let freq = ahb_freq / pre;
132 (freq, freq * 2u32)
133 }
134 };
135 let (apb7_freq, _apb7_tim_freq) = match config.apb7_pre {
136 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
137 pre => {
138 let freq = ahb_freq / pre;
139 (freq, freq * 2u32)
140 }
141 };
142
143 let rtc = config.ls.init();
144 157
145 set_freqs(Clocks { 158 set_freqs(Clocks {
146 sys: sys_clk, 159 sys: sys_clk,
147 hclk1: ahb_freq, 160 hclk1,
148 hclk2: ahb_freq, 161 hclk2,
149 hclk4: ahb_freq, 162 hclk4,
150 pclk1: apb1_freq, 163 pclk1,
151 pclk2: apb2_freq, 164 pclk2,
152 pclk7: apb7_freq, 165 pclk7,
153 pclk1_tim: apb1_tim_freq, 166 pclk1_tim,
154 pclk2_tim: apb2_tim_freq, 167 pclk2_tim,
155 rtc, 168 rtc,
156 }); 169 });
157} 170}