diff options
| author | Badr Bouslikhin <[email protected]> | 2023-12-01 15:05:31 +0100 |
|---|---|---|
| committer | Badr Bouslikhin <[email protected]> | 2023-12-01 15:05:31 +0100 |
| commit | c97f65ac609221067f7af4deb69d5b7d66d57c7a (patch) | |
| tree | a7b4b7c21549aa14eaf33343f4f2a2220fc5049e | |
| parent | fe8c46bce329efe7921386dd46a493f607453bd8 (diff) | |
stm32/rcc: make h7 rm0399 power supply configurable
| -rw-r--r-- | embassy-stm32/src/rcc/h.rs | 148 |
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)] | ||
| 123 | pub 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)] | ||
| 166 | pub 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] |
| 122 | pub struct Config { | 173 | pub 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 | ||
| 149 | impl Default for Config { | 204 | impl 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 |
