-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
40a8637
commit 35d3a65
Showing
4 changed files
with
188 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//! Prelude | ||
|
||
pub use crate::pwr::PwrExt as _stm32h5xx_hal_pwr_PwrExt; | ||
|
||
pub use fugit::{ExtU32 as _, RateExtU32 as _}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
//! Power configuration | ||
//! | ||
//! This module configures the PWR unit to provide the core voltage `VCORE`. | ||
//! The processor supports multiple voltage scaling modes, from VOS3 (lowest | ||
//! performance, lowest power consumption) to VOS0 (highest performance, | ||
//! highest power consumption). | ||
//! | ||
//! After reset the system is in VOS3. This power configuration module allows | ||
//! modes VOS0 to VOS3 to be selected. | ||
//! | ||
//! ```rust | ||
//! let dp = pac::Peripherals::take().unwrap(); | ||
//! | ||
//! let pwr = dp.PWR.constrain(); | ||
//! let pwrcfg = pwr.vos3().freeze(); | ||
//! | ||
//! assert_eq!(pwrcfg.vos(), VoltageScale::Scale3); | ||
//! ``` | ||
//! | ||
//! If no mode is explicitly selected, it defaults to VOS0 after calling `freeze`. | ||
//! | ||
//! ```rust | ||
//! let dp = pac::Peripherals::take().unwrap(); | ||
//! | ||
//! let pwr = dp.PWR.constrain(); | ||
//! let pwrcfg = pwr.freeze(); | ||
//! | ||
//! assert_eq!(pwrcfg.vos(), VoltageScale::Scale0); | ||
//! ``` | ||
//! | ||
//! | ||
use crate::stm32::pwr::voscr::VOS; | ||
use crate::stm32::pwr::vossr::ACTVOSR; | ||
use crate::stm32::PWR; | ||
|
||
/// Extension trait that constrains the `PWR` peripheral | ||
pub trait PwrExt { | ||
fn constrain(self) -> Pwr; | ||
} | ||
|
||
impl PwrExt for PWR { | ||
fn constrain(self) -> Pwr { | ||
Pwr { | ||
rb: self, | ||
target_vos: VoltageScale::Scale0, | ||
} | ||
} | ||
} | ||
|
||
/// Constrained PWR peripheral | ||
/// | ||
/// Generated by calling `constrain` on the PAC's PWR peripheral. | ||
pub struct Pwr { | ||
pub(crate) rb: PWR, | ||
target_vos: VoltageScale, | ||
} | ||
|
||
/// Voltage Scale | ||
/// | ||
/// Represents the voltage range feeding the CPU core. The maximum core | ||
/// clock frequency depends on this value. | ||
#[derive(Copy, Clone, PartialEq, Eq)] | ||
pub enum VoltageScale { | ||
/// VOS 0 range VCORE 1.30V - 1.40V | ||
Scale0, | ||
/// VOS 1 range VCORE 1.15V - 1.26V | ||
Scale1, | ||
/// VOS 2 range VCORE 1.05V - 1.15V | ||
Scale2, | ||
/// VOS 3 range VCORE 0.95V - 1.05V | ||
Scale3, | ||
} | ||
|
||
impl From<VoltageScale> for VOS { | ||
fn from(value: VoltageScale) -> Self { | ||
match value { | ||
VoltageScale::Scale3 => VOS::Vos3, | ||
VoltageScale::Scale2 => VOS::Vos2, | ||
VoltageScale::Scale1 => VOS::Vos1, | ||
VoltageScale::Scale0 => VOS::Vos0, | ||
} | ||
} | ||
} | ||
|
||
impl From<ACTVOSR> for VoltageScale { | ||
fn from(value: ACTVOSR) -> Self { | ||
match value { | ||
ACTVOSR::Vos3 => VoltageScale::Scale3, | ||
ACTVOSR::Vos2 => VoltageScale::Scale2, | ||
ACTVOSR::Vos1 => VoltageScale::Scale1, | ||
ACTVOSR::Vos0 => VoltageScale::Scale0, | ||
} | ||
} | ||
} | ||
|
||
/// Power Configuration | ||
/// | ||
/// Generated when the PWR peripheral is frozen. | ||
/// longer be changed. | ||
pub struct PowerConfiguration { | ||
pub(crate) vos: VoltageScale, | ||
} | ||
|
||
impl PowerConfiguration { | ||
/// Gets the `VoltageScale` which was configured by `Pwr::freeze()`. | ||
pub fn vos(&self) -> VoltageScale { | ||
self.vos | ||
} | ||
} | ||
|
||
/// Internal power methods | ||
impl Pwr { | ||
/// Transition between voltage scaling levels | ||
fn voltage_scaling_transition(&self, new_scale: VoltageScale) { | ||
// ************************************ | ||
// Note: STM32H503 Errata 2.2.13 states that for Rev A, Z this transition should only | ||
// be executed from RAM. It's unclear if these silicon revisions saw wide release, so | ||
// this is left executed from flash. | ||
// ************************************ | ||
|
||
self.rb.voscr().write(|w| w.vos().variant(new_scale.into())); | ||
while self.rb.vossr().read().vosrdy().is_not_ready() {} | ||
} | ||
|
||
/// Returns a reference to the inner peripheral | ||
pub fn inner(&self) -> &PWR { | ||
&self.rb | ||
} | ||
|
||
/// Returns a mutable reference to the inner peripheral | ||
pub fn inner_mut(&mut self) -> &mut PWR { | ||
&mut self.rb | ||
} | ||
} | ||
|
||
/// Builder methods | ||
impl Pwr { | ||
/// Configure Voltage Scale 0. This is the default configuration | ||
#[must_use] | ||
pub fn vos0(mut self) -> Self { | ||
self.target_vos = VoltageScale::Scale0; | ||
self | ||
} | ||
/// Configure Voltage Scale 1 | ||
#[must_use] | ||
pub fn vos1(mut self) -> Self { | ||
self.target_vos = VoltageScale::Scale1; | ||
self | ||
} | ||
/// Configure Voltage Scale 2 | ||
#[must_use] | ||
pub fn vos2(mut self) -> Self { | ||
self.target_vos = VoltageScale::Scale2; | ||
self | ||
} | ||
/// Configure Voltage Scale 3 | ||
#[must_use] | ||
pub fn vos3(mut self) -> Self { | ||
self.target_vos = VoltageScale::Scale3; | ||
self | ||
} | ||
|
||
pub fn freeze(self) -> PowerConfiguration { | ||
// Validate the supply configuration. If you are stuck here, it is | ||
// because the voltages on your board do not match those specified | ||
// in the VOSCR.VOS By default after reset VOS = Scale 3, so check | ||
// that the voltage on the VCAP pins = 1.0V. | ||
while self.rb.vossr().read().actvosrdy().is_not_ready() {} | ||
|
||
let current_scale = | ||
VoltageScale::from(self.rb.vossr().read().actvos().variant()); | ||
|
||
let vos = self.target_vos; | ||
if current_scale != vos { | ||
self.voltage_scaling_transition(vos); | ||
} | ||
|
||
PowerConfiguration { vos } | ||
} | ||
} |