aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBadr Bouslikhin <[email protected]>2023-12-01 15:05:31 +0100
committerBadr Bouslikhin <[email protected]>2023-12-01 15:05:31 +0100
commitc97f65ac609221067f7af4deb69d5b7d66d57c7a (patch)
treea7b4b7c21549aa14eaf33343f4f2a2220fc5049e
parentfe8c46bce329efe7921386dd46a493f607453bd8 (diff)
stm32/rcc: make h7 rm0399 power supply configurable
-rw-r--r--embassy-stm32/src/rcc/h.rs148
1 files changed, 147 insertions, 1 deletions
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 1a9603d02..2d3550da6 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -117,6 +117,57 @@ impl From<TimerPrescaler> for Timpre {
117 } 117 }
118} 118}
119 119
120/// Power supply configuration
121/// See RM0433 Rev 4 7.4
122#[cfg(pwr_h7rm0399)]
123pub enum SupplyConfig {
124 /// Default power supply configuration.
125 /// V CORE Power Domains are supplied from the LDO according to VOS.
126 /// SMPS step-down converter enabled at 1.2V, may be used to supply the LDO.
127 Default,
128
129 /// Power supply configuration using the LDO.
130 /// V CORE Power Domains are supplied from the LDO according to VOS.
131 /// LDO power mode (Main, LP, Off) will follow system low-power modes.
132 /// SMPS step-down converter disabled.
133 LDO,
134
135 /// Power supply configuration directly from the SMPS step-down converter.
136 /// V CORE Power Domains are supplied from SMPS step-down converter according to VOS.
137 /// LDO bypassed.
138 /// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
139 DirectSMPS,
140
141 /// Power supply configuration from the SMPS step-down converter, that supplies the LDO.
142 /// V CORE Power Domains are supplied from the LDO according to VOS
143 /// LDO power mode (Main, LP, Off) will follow system low-power modes.
144 /// SMPS step-down converter enabled according to SDLEVEL, and supplies the LDO.
145 /// SMPS step-down converter power mode (MR, LP, Off) will follow system low-power modes.
146 SMPSLDO,
147
148 /// Power supply configuration from SMPS supplying external circuits and potentially the LDO.
149 /// V CORE Power Domains are supplied from voltage regulator according to VOS
150 /// LDO power mode (Main, LP, Off) will follow system low-power modes.
151 /// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the LDO.
152 /// SMPS step-down converter forced ON in MR mode.
153 SMPSExternalLDO,
154
155 /// Power supply configuration from SMPS supplying external circuits and bypassing the LDO.
156 /// V CORE supplied from external source
157 /// SMPS step-down converter enabled according to SDLEVEL used to supply external circuits and may supply the external source for V CORE .
158 /// SMPS step-down converter forced ON in MR mode.
159 SMPSExternalLDOBypass,
160}
161
162/// SMPS step-down converter voltage output level.
163/// This is only used in certain power supply configurations:
164/// SMPSLDO, SMPSExternalLDO, SMPSExternalLDOBypass.
165#[cfg(pwr_h7rm0399)]
166pub enum SMPSSupplyVoltage {
167 V1_8,
168 V2_5,
169}
170
120/// Configuration of the core clocks 171/// Configuration of the core clocks
121#[non_exhaustive] 172#[non_exhaustive]
122pub struct Config { 173pub struct Config {
@@ -144,6 +195,10 @@ pub struct Config {
144 pub timer_prescaler: TimerPrescaler, 195 pub timer_prescaler: TimerPrescaler,
145 pub voltage_scale: VoltageScale, 196 pub voltage_scale: VoltageScale,
146 pub ls: super::LsConfig, 197 pub ls: super::LsConfig,
198
199 #[cfg(pwr_h7rm0399)]
200 pub supply_config: SupplyConfig,
201 pub smps_supply_voltage: Option<SMPSSupplyVoltage>,
147} 202}
148 203
149impl Default for Config { 204impl Default for Config {
@@ -177,6 +232,10 @@ impl Default for Config {
177 timer_prescaler: TimerPrescaler::DefaultX2, 232 timer_prescaler: TimerPrescaler::DefaultX2,
178 voltage_scale: VoltageScale::Scale0, 233 voltage_scale: VoltageScale::Scale0,
179 ls: Default::default(), 234 ls: Default::default(),
235
236 #[cfg(pwr_h7rm0399)]
237 supply_config: SupplyConfig::Default,
238 smps_supply_voltage: None,
180 } 239 }
181 } 240 }
182} 241}
@@ -194,7 +253,7 @@ pub(crate) unsafe fn init(config: Config) {
194 w.set_bypass(false); 253 w.set_bypass(false);
195 }); 254 });
196 255
197 #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))] 256 #[cfg(any(pwr_h7rm0455, pwr_h7rm0468))]
198 PWR.cr3().modify(|w| { 257 PWR.cr3().modify(|w| {
199 // hardcode "Direct SPMS" for now, this is what works on nucleos with the 258 // hardcode "Direct SPMS" for now, this is what works on nucleos with the
200 // default solderbridge configuration. 259 // default solderbridge configuration.
@@ -202,6 +261,93 @@ pub(crate) unsafe fn init(config: Config) {
202 w.set_ldoen(false); 261 w.set_ldoen(false);
203 }); 262 });
204 263
264 #[cfg(pwr_h7rm0399)]
265 {
266 match config.supply_config {
267 SupplyConfig::Default => {
268 PWR.cr3().modify(|w| {
269 w.set_sdlevel(0b00);
270 w.set_sdexthp(false);
271 w.set_sden(true);
272 w.set_ldoen(true);
273 w.set_bypass(false);
274 });
275 }
276 SupplyConfig::LDO => {
277 PWR.cr3().modify(|w| {
278 w.set_sden(false);
279 w.set_ldoen(true);
280 w.set_bypass(false);
281 });
282 }
283 SupplyConfig::DirectSMPS => {
284 PWR.cr3().modify(|w| {
285 w.set_sdexthp(false);
286 w.set_sden(true);
287 w.set_ldoen(false);
288 w.set_bypass(false);
289 });
290 }
291 SupplyConfig::SMPSLDO => {
292 PWR.cr3().modify(|w| {
293 match config.smps_supply_voltage {
294 Some(SMPSSupplyVoltage::V1_8) => {
295 PWR.cr3().modify(|w| w.set_sdlevel(0b01));
296 }
297 Some(SMPSSupplyVoltage::V2_5) => {
298 PWR.cr3().modify(|w| w.set_sdlevel(0b10));
299 }
300 None => {
301 panic!("Supply configuration SMPSLDO requires a supply voltage to be set.");
302 }
303 }
304 w.set_sdexthp(false);
305 w.set_sden(true);
306 w.set_ldoen(true);
307 w.set_bypass(false);
308 });
309 }
310 SupplyConfig::SMPSExternalLDO => {
311 PWR.cr3().modify(|w| {
312 match config.smps_supply_voltage {
313 Some(SMPSSupplyVoltage::V1_8) => {
314 PWR.cr3().modify(|w| w.set_sdlevel(0b01));
315 }
316 Some(SMPSSupplyVoltage::V2_5) => {
317 PWR.cr3().modify(|w| w.set_sdlevel(0b10));
318 }
319 None => {
320 panic!("Supply configuration SMPSExternalLDO requires a supply voltage to be set.");
321 }
322 }
323 w.set_sdexthp(true);
324 w.set_sden(true);
325 w.set_ldoen(true);
326 w.set_bypass(false);
327 });
328 }
329 SupplyConfig::SMPSExternalLDOBypass => {
330 PWR.cr3().modify(|w| {
331 match config.smps_supply_voltage {
332 Some(SMPSSupplyVoltage::V1_8) => {
333 PWR.cr3().modify(|w| w.set_sdlevel(0b01));
334 }
335 Some(SMPSSupplyVoltage::V2_5) => {
336 PWR.cr3().modify(|w| w.set_sdlevel(0b10));
337 }
338 None => {
339 panic!("Supply configuration SMPSExternalLDOBypass requires a supply voltage to be set.");
340 }
341 }
342 w.set_sdexthp(true);
343 w.set_sden(true);
344 w.set_ldoen(false);
345 w.set_bypass(true);
346 });
347 }
348 }
349 }
350
205 // Validate the supply configuration. If you are stuck here, it is 351 // Validate the supply configuration. If you are stuck here, it is
206 // because the voltages on your board do not match those specified 352 // because the voltages on your board do not match those specified
207 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset 353 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset