Merge pull request #4187 from 1-rafael-1/rp235x-overclocking
RP235x overclocking
This commit is contained in:
commit
5a19b64fec
@ -38,7 +38,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//! ### Standard 125MHz configuration
|
//! ### Standard 125MHz (rp2040) or 150Mhz (rp235x) configuration
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
//! let config = ClockConfig::crystal(12_000_000);
|
//! let config = ClockConfig::crystal(12_000_000);
|
||||||
//! ```
|
//! ```
|
||||||
@ -82,6 +82,18 @@ use crate::{pac, reset, Peri};
|
|||||||
// be very useful until we have runtime clock reconfiguration. once this
|
// be very useful until we have runtime clock reconfiguration. once this
|
||||||
// happens we can resurrect the commented-out gpin bits.
|
// happens we can resurrect the commented-out gpin bits.
|
||||||
|
|
||||||
|
/// Clock error types.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum ClockError {
|
||||||
|
/// PLL failed to lock within the timeout period.
|
||||||
|
PllLockTimedOut,
|
||||||
|
/// Could not find valid PLL parameters for system clock.
|
||||||
|
InvalidPllParameters,
|
||||||
|
/// Reading the core voltage failed due to an unexpected value in the register.
|
||||||
|
UnexpectedCoreVoltageRead,
|
||||||
|
}
|
||||||
|
|
||||||
struct Clocks {
|
struct Clocks {
|
||||||
xosc: AtomicU32,
|
xosc: AtomicU32,
|
||||||
sys: AtomicU32,
|
sys: AtomicU32,
|
||||||
@ -136,15 +148,16 @@ pub enum PeriClkSrc {
|
|||||||
// Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
// Gpin1 = ClkPeriCtrlAuxsrc::CLKSRC_GPIN1 as _ ,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Core voltage regulator settings for RP2040.
|
/// Core voltage regulator settings.
|
||||||
///
|
///
|
||||||
/// The RP2040 voltage regulator can be configured for different output voltages.
|
/// The voltage regulator can be configured for different output voltages.
|
||||||
/// Higher voltages allow for higher clock frequencies but increase power consumption and heat.
|
/// Higher voltages allow for higher clock frequencies but increase power consumption and heat.
|
||||||
#[cfg(feature = "rp2040")]
|
#[cfg(feature = "rp2040")]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum CoreVoltage {
|
pub enum CoreVoltage {
|
||||||
/// 0.80V - Suitable for lower frequencies
|
/// 0.80V
|
||||||
V0_80 = 0b0000,
|
V0_80 = 0b0000,
|
||||||
/// 0.85V
|
/// 0.85V
|
||||||
V0_85 = 0b0110,
|
V0_85 = 0b0110,
|
||||||
@ -168,11 +181,58 @@ pub enum CoreVoltage {
|
|||||||
V1_30 = 0b1111,
|
V1_30 = 0b1111,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rp2040")]
|
/// Core voltage regulator settings.
|
||||||
|
///
|
||||||
|
/// The voltage regulator can be configured for different output voltages.
|
||||||
|
/// Higher voltages allow for higher clock frequencies but increase power consumption and heat.
|
||||||
|
///
|
||||||
|
/// **Note**: The maximum voltage is 1.30V, unless unlocked by setting unless the voltage limit
|
||||||
|
/// is disabled using the disable_voltage_limit field in the vreg_ctrl register. For lack of practical use at this
|
||||||
|
/// point in time, this is not implemented here. So the maximum voltage in this enum is 1.30V for now.
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum CoreVoltage {
|
||||||
|
/// 0.55V
|
||||||
|
V0_55 = 0b00000,
|
||||||
|
/// 0.60V
|
||||||
|
V0_60 = 0b00001,
|
||||||
|
/// 0.65V
|
||||||
|
V0_65 = 0b00010,
|
||||||
|
/// 0.70V
|
||||||
|
V0_70 = 0b00011,
|
||||||
|
/// 0.75V
|
||||||
|
V0_75 = 0b00100,
|
||||||
|
/// 0.80V
|
||||||
|
V0_80 = 0b00101,
|
||||||
|
/// 0.85V
|
||||||
|
V0_85 = 0b00110,
|
||||||
|
/// 0.90V
|
||||||
|
V0_90 = 0b00111,
|
||||||
|
/// 0.95V
|
||||||
|
V0_95 = 0b01000,
|
||||||
|
/// 1.00V
|
||||||
|
V1_00 = 0b01001,
|
||||||
|
/// 1.05V
|
||||||
|
V1_05 = 0b01010,
|
||||||
|
/// 1.10V - Default voltage level
|
||||||
|
V1_10 = 0b01011,
|
||||||
|
/// 1.15V
|
||||||
|
V1_15 = 0b01100,
|
||||||
|
/// 1.20V
|
||||||
|
V1_20 = 0b01101,
|
||||||
|
/// 1.25V
|
||||||
|
V1_25 = 0b01110,
|
||||||
|
/// 1.30V
|
||||||
|
V1_30 = 0b01111,
|
||||||
|
}
|
||||||
|
|
||||||
impl CoreVoltage {
|
impl CoreVoltage {
|
||||||
/// Get the recommended Brown-Out Detection (BOD) setting for this voltage.
|
/// Get the recommended Brown-Out Detection (BOD) setting for this voltage.
|
||||||
/// Sets the BOD threshold to approximately 80% of the core voltage.
|
/// Sets the BOD threshold to approximately 80% of the core voltage.
|
||||||
fn recommended_bod(self) -> u8 {
|
fn recommended_bod(self) -> u8 {
|
||||||
|
#[cfg(feature = "rp2040")]
|
||||||
match self {
|
match self {
|
||||||
CoreVoltage::V0_80 => 0b0100, // 0.645V (~81% of 0.80V)
|
CoreVoltage::V0_80 => 0b0100, // 0.645V (~81% of 0.80V)
|
||||||
CoreVoltage::V0_85 => 0b0101, // 0.688V (~81% of 0.85V)
|
CoreVoltage::V0_85 => 0b0101, // 0.688V (~81% of 0.85V)
|
||||||
@ -180,12 +240,32 @@ impl CoreVoltage {
|
|||||||
CoreVoltage::V0_95 => 0b0111, // 0.774V (~81% of 0.95V)
|
CoreVoltage::V0_95 => 0b0111, // 0.774V (~81% of 0.95V)
|
||||||
CoreVoltage::V1_00 => 0b1000, // 0.817V (~82% of 1.00V)
|
CoreVoltage::V1_00 => 0b1000, // 0.817V (~82% of 1.00V)
|
||||||
CoreVoltage::V1_05 => 0b1000, // 0.817V (~78% of 1.05V)
|
CoreVoltage::V1_05 => 0b1000, // 0.817V (~78% of 1.05V)
|
||||||
CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V)
|
CoreVoltage::V1_10 => 0b1001, // 0.860V (~78% of 1.10V), the default
|
||||||
CoreVoltage::V1_15 => 0b1010, // 0.903V (~79% of 1.15V)
|
CoreVoltage::V1_15 => 0b1010, // 0.903V (~79% of 1.15V)
|
||||||
CoreVoltage::V1_20 => 0b1011, // 0.946V (~79% of 1.20V)
|
CoreVoltage::V1_20 => 0b1011, // 0.946V (~79% of 1.20V)
|
||||||
CoreVoltage::V1_25 => 0b1100, // 0.989V (~79% of 1.25V)
|
CoreVoltage::V1_25 => 0b1100, // 0.989V (~79% of 1.25V)
|
||||||
CoreVoltage::V1_30 => 0b1101, // 1.032V (~79% of 1.30V)
|
CoreVoltage::V1_30 => 0b1101, // 1.032V (~79% of 1.30V)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
match self {
|
||||||
|
CoreVoltage::V0_55 => 0b00001, // 0.516V (~94% of 0.55V)
|
||||||
|
CoreVoltage::V0_60 => 0b00010, // 0.559V (~93% of 0.60V)
|
||||||
|
CoreVoltage::V0_65 => 0b00011, // 0.602V (~93% of 0.65V)
|
||||||
|
CoreVoltage::V0_70 => 0b00011, // 0.602V (~86% of 0.70V)
|
||||||
|
CoreVoltage::V0_75 => 0b00100, // 0.645V (~86% of 0.75V)
|
||||||
|
CoreVoltage::V0_80 => 0b00101, // 0.688V (~86% of 0.80V)
|
||||||
|
CoreVoltage::V0_85 => 0b00110, // 0.731V (~86% of 0.85V)
|
||||||
|
CoreVoltage::V0_90 => 0b00110, // 0.731V (~81% of 0.90V)
|
||||||
|
CoreVoltage::V0_95 => 0b00111, // 0.774V (~81% of 0.95V)
|
||||||
|
CoreVoltage::V1_00 => 0b01000, // 0.817V (~82% of 1.00V)
|
||||||
|
CoreVoltage::V1_05 => 0b01000, // 0.817V (~78% of 1.05V)
|
||||||
|
CoreVoltage::V1_10 => 0b01001, // 0.860V (~78% of 1.10V), the default
|
||||||
|
CoreVoltage::V1_15 => 0b01001, // 0.860V (~75% of 1.15V)
|
||||||
|
CoreVoltage::V1_20 => 0b01010, // 0.903V (~75% of 1.20V)
|
||||||
|
CoreVoltage::V1_25 => 0b01010, // 0.903V (~72% of 1.25V)
|
||||||
|
CoreVoltage::V1_30 => 0b01011, // 0.946V (~73% of 1.30V)
|
||||||
|
// all others: 0.946V (see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,12 +289,10 @@ pub struct ClockConfig {
|
|||||||
/// RTC clock configuration.
|
/// RTC clock configuration.
|
||||||
#[cfg(feature = "rp2040")]
|
#[cfg(feature = "rp2040")]
|
||||||
pub rtc_clk: Option<RtcClkConfig>,
|
pub rtc_clk: Option<RtcClkConfig>,
|
||||||
/// Core voltage scaling (RP2040 only). Defaults to 1.10V.
|
/// Core voltage scaling. Defaults to 1.10V.
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
pub core_voltage: CoreVoltage,
|
pub core_voltage: CoreVoltage,
|
||||||
/// Voltage stabilization delay in microseconds.
|
/// Voltage stabilization delay in microseconds.
|
||||||
/// If not set, defaults will be used based on voltage level.
|
/// If not set, defaults will be used based on voltage level.
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
pub voltage_stabilization_delay_us: Option<u32>,
|
pub voltage_stabilization_delay_us: Option<u32>,
|
||||||
// See above re gpin handling being commented out
|
// See above re gpin handling being commented out
|
||||||
// gpin0: Option<(u32, Gpin<'static, AnyPin>)>,
|
// gpin0: Option<(u32, Gpin<'static, AnyPin>)>,
|
||||||
@ -250,9 +328,7 @@ impl Default for ClockConfig {
|
|||||||
adc_clk: None,
|
adc_clk: None,
|
||||||
#[cfg(feature = "rp2040")]
|
#[cfg(feature = "rp2040")]
|
||||||
rtc_clk: None,
|
rtc_clk: None,
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
core_voltage: CoreVoltage::V1_10,
|
core_voltage: CoreVoltage::V1_10,
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
voltage_stabilization_delay_us: None,
|
voltage_stabilization_delay_us: None,
|
||||||
// See above re gpin handling being commented out
|
// See above re gpin handling being commented out
|
||||||
// gpin0: None,
|
// gpin0: None,
|
||||||
@ -323,9 +399,7 @@ impl ClockConfig {
|
|||||||
div_frac: 0,
|
div_frac: 0,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
}),
|
}),
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V)
|
core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V)
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
voltage_stabilization_delay_us: None,
|
voltage_stabilization_delay_us: None,
|
||||||
// See above re gpin handling being commented out
|
// See above re gpin handling being commented out
|
||||||
// gpin0: None,
|
// gpin0: None,
|
||||||
@ -368,9 +442,7 @@ impl ClockConfig {
|
|||||||
div_frac: 171,
|
div_frac: 171,
|
||||||
phase: 0,
|
phase: 0,
|
||||||
}),
|
}),
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V)
|
core_voltage: CoreVoltage::V1_10, // Use hardware default (1.10V)
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
voltage_stabilization_delay_us: None,
|
voltage_stabilization_delay_us: None,
|
||||||
// See above re gpin handling being commented out
|
// See above re gpin handling being commented out
|
||||||
// gpin0: None,
|
// gpin0: None,
|
||||||
@ -391,29 +463,42 @@ impl ClockConfig {
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// A ClockConfig configured to achieve the requested system frequency using the
|
/// A ClockConfig configured to achieve the requested system frequency using the
|
||||||
/// the usual 12Mhz crystal, or panic if no valid parameters can be found.
|
/// the usual 12Mhz crystal, or an error if no valid parameters can be found.
|
||||||
///
|
///
|
||||||
/// # Note on core voltage:
|
/// # Note on core voltage:
|
||||||
|
///
|
||||||
|
/// **For RP2040**:
|
||||||
/// To date the only officially documented core voltages (see Datasheet section 2.15.3.1. Instances) are:
|
/// To date the only officially documented core voltages (see Datasheet section 2.15.3.1. Instances) are:
|
||||||
/// - Up to 133MHz: V1_10 (default)
|
/// - Up to 133MHz: V1_10 (default)
|
||||||
/// - Above 133MHz: V1_15, but in the context of the datasheet covering reaching up to 200Mhz
|
/// - Above 133MHz: V1_15, but in the context of the datasheet covering reaching up to 200Mhz
|
||||||
/// That way all other frequencies below 133MHz or above 200MHz are not explicitly documented and not covered here.
|
/// That way all other frequencies below 133MHz or above 200MHz are not explicitly documented and not covered here.
|
||||||
/// In case You want to go below 133MHz or above 200MHz and want a different voltage, You will have to set that manually and with caution.
|
/// In case You want to go below 133MHz or above 200MHz and want a different voltage, You will have to set that manually and with caution.
|
||||||
#[cfg(feature = "rp2040")]
|
///
|
||||||
pub fn system_freq(hz: u32) -> Self {
|
/// **For RP235x**:
|
||||||
|
/// At this point in time there is no official manufacturer endorsement for running the chip on other core voltages and/or other clock speeds than the defaults.
|
||||||
|
/// Using this function is experimental and may not work as expected or even damage the chip.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// A Result containing either the configured ClockConfig or a ClockError.
|
||||||
|
pub fn system_freq(hz: u32) -> Result<Self, ClockError> {
|
||||||
// Start with the standard configuration from crystal()
|
// Start with the standard configuration from crystal()
|
||||||
const DEFAULT_CRYSTAL_HZ: u32 = 12_000_000;
|
const DEFAULT_CRYSTAL_HZ: u32 = 12_000_000;
|
||||||
let mut config = Self::crystal(DEFAULT_CRYSTAL_HZ);
|
let mut config = Self::crystal(DEFAULT_CRYSTAL_HZ);
|
||||||
|
|
||||||
// No need to modify anything if target frequency is already 125MHz
|
// No need to modify anything if target frequency is already 125MHz
|
||||||
// (which is what crystal() configures by default)
|
// (which is what crystal() configures by default)
|
||||||
|
#[cfg(feature = "rp2040")]
|
||||||
if hz == 125_000_000 {
|
if hz == 125_000_000 {
|
||||||
return config;
|
return Ok(config);
|
||||||
|
}
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
if hz == 150_000_000 {
|
||||||
|
return Ok(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find optimal PLL parameters for the requested frequency
|
// Find optimal PLL parameters for the requested frequency
|
||||||
let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz)
|
let sys_pll_params = find_pll_params(DEFAULT_CRYSTAL_HZ, hz).ok_or(ClockError::InvalidPllParameters)?;
|
||||||
.unwrap_or_else(|| panic!("Could not find valid PLL parameters for system clock"));
|
|
||||||
|
|
||||||
// Replace the sys_pll configuration with our custom parameters
|
// Replace the sys_pll configuration with our custom parameters
|
||||||
if let Some(xosc) = &mut config.xosc {
|
if let Some(xosc) = &mut config.xosc {
|
||||||
@ -429,8 +514,16 @@ impl ClockConfig {
|
|||||||
_ => CoreVoltage::V1_10, // Use default voltage (V1_10)
|
_ => CoreVoltage::V1_10, // Use default voltage (V1_10)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
{
|
||||||
|
config.core_voltage = match hz {
|
||||||
|
// There is no official support for running the chip on other core voltages and/or other clock speeds than the defaults.
|
||||||
|
// So for now we have not way of knowing what the voltage should be. Change this if the manufacturer provides more information.
|
||||||
|
_ => CoreVoltage::V1_10, // Use default voltage (V1_10)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
config
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure with manual PLL settings for full control over system clock
|
/// Configure with manual PLL settings for full control over system clock
|
||||||
@ -525,6 +618,7 @@ impl ClockConfig {
|
|||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum RoscRange {
|
pub enum RoscRange {
|
||||||
/// Low range.
|
/// Low range.
|
||||||
Low = pac::rosc::vals::FreqRange::LOW.0,
|
Low = pac::rosc::vals::FreqRange::LOW.0,
|
||||||
@ -631,6 +725,7 @@ pub struct RefClkConfig {
|
|||||||
/// Reference clock source.
|
/// Reference clock source.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum RefClkSrc {
|
pub enum RefClkSrc {
|
||||||
/// XOSC.
|
/// XOSC.
|
||||||
Xosc,
|
Xosc,
|
||||||
@ -646,6 +741,7 @@ pub enum RefClkSrc {
|
|||||||
/// SYS clock source.
|
/// SYS clock source.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum SysClkSrc {
|
pub enum SysClkSrc {
|
||||||
/// REF.
|
/// REF.
|
||||||
Ref,
|
Ref,
|
||||||
@ -684,6 +780,7 @@ pub struct SysClkConfig {
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum UsbClkSrc {
|
pub enum UsbClkSrc {
|
||||||
/// PLL USB.
|
/// PLL USB.
|
||||||
PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkUsbCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
@ -712,6 +809,7 @@ pub struct UsbClkConfig {
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum AdcClkSrc {
|
pub enum AdcClkSrc {
|
||||||
/// PLL USB.
|
/// PLL USB.
|
||||||
PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
PllUsb = ClkAdcCtrlAuxsrc::CLKSRC_PLL_USB as _,
|
||||||
@ -740,6 +838,7 @@ pub struct AdcClkConfig {
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[cfg(feature = "rp2040")]
|
#[cfg(feature = "rp2040")]
|
||||||
pub enum RtcClkSrc {
|
pub enum RtcClkSrc {
|
||||||
/// PLL USB.
|
/// PLL USB.
|
||||||
@ -791,7 +890,6 @@ pub struct RtcClkConfig {
|
|||||||
/// // Find parameters for 133MHz system clock from 12MHz crystal
|
/// // Find parameters for 133MHz system clock from 12MHz crystal
|
||||||
/// let pll_params = find_pll_params(12_000_000, 133_000_000).unwrap();
|
/// let pll_params = find_pll_params(12_000_000, 133_000_000).unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
fn find_pll_params(input_hz: u32, target_hz: u32) -> Option<PllConfig> {
|
fn find_pll_params(input_hz: u32, target_hz: u32) -> Option<PllConfig> {
|
||||||
// Fixed reference divider for system PLL
|
// Fixed reference divider for system PLL
|
||||||
const PLL_SYS_REFDIV: u8 = 1;
|
const PLL_SYS_REFDIV: u8 = 1;
|
||||||
@ -925,18 +1023,31 @@ pub(crate) unsafe fn init(config: ClockConfig) {
|
|||||||
};
|
};
|
||||||
CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed);
|
CLOCKS.rosc.store(rosc_freq, Ordering::Relaxed);
|
||||||
|
|
||||||
// Set Core Voltage (RP2040 only), if we have config for it and we're not using the default
|
// Set Core Voltage, if we have config for it and we're not using the default
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
{
|
{
|
||||||
let voltage = config.core_voltage;
|
let voltage = config.core_voltage;
|
||||||
|
|
||||||
|
#[cfg(feature = "rp2040")]
|
||||||
let vreg = pac::VREG_AND_CHIP_RESET;
|
let vreg = pac::VREG_AND_CHIP_RESET;
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
let vreg = pac::POWMAN;
|
||||||
|
|
||||||
let current_vsel = vreg.vreg().read().vsel();
|
let current_vsel = vreg.vreg().read().vsel();
|
||||||
let target_vsel = voltage as u8;
|
let target_vsel = voltage as u8;
|
||||||
|
|
||||||
// If the target voltage is different from the current one, we need to change it
|
// If the target voltage is different from the current one, we need to change it
|
||||||
if target_vsel != current_vsel {
|
if target_vsel != current_vsel {
|
||||||
// Use modify() to preserve the HIZ and EN bits - otherwise we will disable the regulator when changing voltage
|
// Set the voltage regulator to the target voltage
|
||||||
|
#[cfg(feature = "rp2040")]
|
||||||
vreg.vreg().modify(|w| w.set_vsel(target_vsel));
|
vreg.vreg().modify(|w| w.set_vsel(target_vsel));
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
// For rp235x changes to the voltage regulator are protected by a password, see datasheet section 6.4 Power Management (POWMAN) Registers
|
||||||
|
// The password is "5AFE" (0x5AFE), it must be set in the top 16 bits of the register
|
||||||
|
vreg.vreg().modify(|w| {
|
||||||
|
w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password
|
||||||
|
w.set_vsel(target_vsel);
|
||||||
|
*w
|
||||||
|
});
|
||||||
|
|
||||||
// Wait for the voltage to stabilize. Use the provided delay or default based on voltage
|
// Wait for the voltage to stabilize. Use the provided delay or default based on voltage
|
||||||
let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| {
|
let settling_time_us = config.voltage_stabilization_delay_us.unwrap_or_else(|| {
|
||||||
@ -955,10 +1066,17 @@ pub(crate) unsafe fn init(config: ClockConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only now set the BOD level. At this point the voltage is considered stable.
|
// Only now set the BOD level. At this point the voltage is considered stable.
|
||||||
|
#[cfg(feature = "rp2040")]
|
||||||
vreg.bod().write(|w| {
|
vreg.bod().write(|w| {
|
||||||
w.set_vsel(voltage.recommended_bod());
|
w.set_vsel(voltage.recommended_bod());
|
||||||
w.set_en(true); // Enable brownout detection
|
w.set_en(true); // Enable brownout detection
|
||||||
});
|
});
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
vreg.bod().write(|w| {
|
||||||
|
w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password
|
||||||
|
w.set_vsel(voltage.recommended_bod());
|
||||||
|
w.set_en(true); // Enable brownout detection
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,14 +1088,14 @@ pub(crate) unsafe fn init(config: ClockConfig) {
|
|||||||
let pll_sys_freq = match config.sys_pll {
|
let pll_sys_freq = match config.sys_pll {
|
||||||
Some(sys_pll_config) => match configure_pll(pac::PLL_SYS, config.hz, sys_pll_config) {
|
Some(sys_pll_config) => match configure_pll(pac::PLL_SYS, config.hz, sys_pll_config) {
|
||||||
Ok(freq) => freq,
|
Ok(freq) => freq,
|
||||||
Err(e) => panic!("Failed to configure PLL_SYS: {}", e),
|
Err(e) => panic!("Failed to configure PLL_SYS: {:?}", e),
|
||||||
},
|
},
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
let pll_usb_freq = match config.usb_pll {
|
let pll_usb_freq = match config.usb_pll {
|
||||||
Some(usb_pll_config) => match configure_pll(pac::PLL_USB, config.hz, usb_pll_config) {
|
Some(usb_pll_config) => match configure_pll(pac::PLL_USB, config.hz, usb_pll_config) {
|
||||||
Ok(freq) => freq,
|
Ok(freq) => freq,
|
||||||
Err(e) => panic!("Failed to configure PLL_USB: {}", e),
|
Err(e) => panic!("Failed to configure PLL_USB: {:?}", e),
|
||||||
},
|
},
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
@ -1283,6 +1401,58 @@ pub fn clk_rtc_freq() -> u16 {
|
|||||||
CLOCKS.rtc.load(Ordering::Relaxed)
|
CLOCKS.rtc.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The core voltage of the chip.
|
||||||
|
///
|
||||||
|
/// Returns the current core voltage or an error if the voltage register
|
||||||
|
/// contains an unknown value.
|
||||||
|
pub fn core_voltage() -> Result<CoreVoltage, ClockError> {
|
||||||
|
#[cfg(feature = "rp2040")]
|
||||||
|
{
|
||||||
|
let vreg = pac::VREG_AND_CHIP_RESET;
|
||||||
|
let vsel = vreg.vreg().read().vsel();
|
||||||
|
match vsel {
|
||||||
|
0b0000 => Ok(CoreVoltage::V0_80),
|
||||||
|
0b0110 => Ok(CoreVoltage::V0_85),
|
||||||
|
0b0111 => Ok(CoreVoltage::V0_90),
|
||||||
|
0b1000 => Ok(CoreVoltage::V0_95),
|
||||||
|
0b1001 => Ok(CoreVoltage::V1_00),
|
||||||
|
0b1010 => Ok(CoreVoltage::V1_05),
|
||||||
|
0b1011 => Ok(CoreVoltage::V1_10),
|
||||||
|
0b1100 => Ok(CoreVoltage::V1_15),
|
||||||
|
0b1101 => Ok(CoreVoltage::V1_20),
|
||||||
|
0b1110 => Ok(CoreVoltage::V1_25),
|
||||||
|
0b1111 => Ok(CoreVoltage::V1_30),
|
||||||
|
_ => Err(ClockError::UnexpectedCoreVoltageRead),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "_rp235x")]
|
||||||
|
{
|
||||||
|
let vreg = pac::POWMAN;
|
||||||
|
let vsel = vreg.vreg().read().vsel();
|
||||||
|
match vsel {
|
||||||
|
0b00000 => Ok(CoreVoltage::V0_55),
|
||||||
|
0b00001 => Ok(CoreVoltage::V0_60),
|
||||||
|
0b00010 => Ok(CoreVoltage::V0_65),
|
||||||
|
0b00011 => Ok(CoreVoltage::V0_70),
|
||||||
|
0b00100 => Ok(CoreVoltage::V0_75),
|
||||||
|
0b00101 => Ok(CoreVoltage::V0_80),
|
||||||
|
0b00110 => Ok(CoreVoltage::V0_85),
|
||||||
|
0b00111 => Ok(CoreVoltage::V0_90),
|
||||||
|
0b01000 => Ok(CoreVoltage::V0_95),
|
||||||
|
0b01001 => Ok(CoreVoltage::V1_00),
|
||||||
|
0b01010 => Ok(CoreVoltage::V1_05),
|
||||||
|
0b01011 => Ok(CoreVoltage::V1_10),
|
||||||
|
0b01100 => Ok(CoreVoltage::V1_15),
|
||||||
|
0b01101 => Ok(CoreVoltage::V1_20),
|
||||||
|
0b01110 => Ok(CoreVoltage::V1_25),
|
||||||
|
0b01111 => Ok(CoreVoltage::V1_30),
|
||||||
|
_ => Err(ClockError::UnexpectedCoreVoltageRead),
|
||||||
|
// see CoreVoltage: we do not support setting Voltages higher than 1.30V at this point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn start_xosc(crystal_hz: u32, delay_multiplier: u32) {
|
fn start_xosc(crystal_hz: u32, delay_multiplier: u32) {
|
||||||
let startup_delay = (((crystal_hz / 1000) * delay_multiplier) + 128) / 256;
|
let startup_delay = (((crystal_hz / 1000) * delay_multiplier) + 128) / 256;
|
||||||
pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16));
|
pac::XOSC.startup().write(|w| w.set_delay(startup_delay as u16));
|
||||||
@ -1295,7 +1465,7 @@ fn start_xosc(crystal_hz: u32, delay_multiplier: u32) {
|
|||||||
|
|
||||||
/// PLL (Phase-Locked Loop) configuration
|
/// PLL (Phase-Locked Loop) configuration
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result<u32, &'static str> {
|
fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result<u32, ClockError> {
|
||||||
// Calculate reference frequency
|
// Calculate reference frequency
|
||||||
let ref_freq = input_freq / config.refdiv as u32;
|
let ref_freq = input_freq / config.refdiv as u32;
|
||||||
|
|
||||||
@ -1366,7 +1536,7 @@ fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> Result
|
|||||||
timeout -= 1;
|
timeout -= 1;
|
||||||
if timeout == 0 {
|
if timeout == 0 {
|
||||||
// PLL failed to lock, return 0 to indicate failure
|
// PLL failed to lock, return 0 to indicate failure
|
||||||
return Err("PLL failed to lock");
|
return Err(ClockError::PllLockTimedOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1937,21 +2107,21 @@ mod tests {
|
|||||||
{
|
{
|
||||||
// Test automatic voltage scaling based on frequency
|
// Test automatic voltage scaling based on frequency
|
||||||
// Under 133 MHz should use default voltage (V1_10)
|
// Under 133 MHz should use default voltage (V1_10)
|
||||||
let config = ClockConfig::system_freq(125_000_000);
|
let config = ClockConfig::system_freq(125_000_000).unwrap();
|
||||||
assert_eq!(config.core_voltage, CoreVoltage::V1_10);
|
assert_eq!(config.core_voltage, CoreVoltage::V1_10);
|
||||||
|
|
||||||
// 133-200 MHz should use V1_15
|
// 133-200 MHz should use V1_15
|
||||||
let config = ClockConfig::system_freq(150_000_000);
|
let config = ClockConfig::system_freq(150_000_000).unwrap();
|
||||||
assert_eq!(config.core_voltage, CoreVoltage::V1_15);
|
assert_eq!(config.core_voltage, CoreVoltage::V1_15);
|
||||||
let config = ClockConfig::system_freq(200_000_000);
|
let config = ClockConfig::system_freq(200_000_000).unwrap();
|
||||||
assert_eq!(config.core_voltage, CoreVoltage::V1_15);
|
assert_eq!(config.core_voltage, CoreVoltage::V1_15);
|
||||||
|
|
||||||
// Above 200 MHz should use V1_25
|
// Above 200 MHz should use V1_15
|
||||||
let config = ClockConfig::system_freq(250_000_000);
|
let config = ClockConfig::system_freq(250_000_000).unwrap();
|
||||||
assert_eq!(config.core_voltage, CoreVoltage::V1_15);
|
assert_eq!(config.core_voltage, CoreVoltage::V1_15);
|
||||||
|
|
||||||
// Below 125 MHz should use V1_10
|
// Below 125 MHz should use V1_10
|
||||||
let config = ClockConfig::system_freq(100_000_000);
|
let config = ClockConfig::system_freq(100_000_000).unwrap();
|
||||||
assert_eq!(config.core_voltage, CoreVoltage::V1_10);
|
assert_eq!(config.core_voltage, CoreVoltage::V1_10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_rp::clocks::{clk_sys_freq, ClockConfig};
|
use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig};
|
||||||
use embassy_rp::config::Config;
|
use embassy_rp::config::Config;
|
||||||
use embassy_rp::gpio::{Level, Output};
|
use embassy_rp::gpio::{Level, Output};
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
@ -18,10 +18,7 @@ const COUNT_TO: i64 = 10_000_000;
|
|||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
// Set up for clock frequency of 200 MHz, setting all necessary defaults.
|
// Set up for clock frequency of 200 MHz, setting all necessary defaults.
|
||||||
let config = Config::new(ClockConfig::system_freq(200_000_000));
|
let config = Config::new(ClockConfig::system_freq(200_000_000).unwrap());
|
||||||
|
|
||||||
// Show the voltage scale for verification
|
|
||||||
info!("System core voltage: {}", Debug2Format(&config.clocks.core_voltage));
|
|
||||||
|
|
||||||
// Initialize the peripherals
|
// Initialize the peripherals
|
||||||
let p = embassy_rp::init(config);
|
let p = embassy_rp::init(config);
|
||||||
@ -29,6 +26,9 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
// Show CPU frequency for verification
|
// Show CPU frequency for verification
|
||||||
let sys_freq = clk_sys_freq();
|
let sys_freq = clk_sys_freq();
|
||||||
info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
|
info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
|
||||||
|
// Show core voltage for verification
|
||||||
|
let core_voltage = core_voltage().unwrap();
|
||||||
|
info!("Core voltage: {}", core_voltage);
|
||||||
|
|
||||||
// LED to indicate the system is running
|
// LED to indicate the system is running
|
||||||
let mut led = Output::new(p.PIN_25, Level::Low);
|
let mut led = Output::new(p.PIN_25, Level::Low);
|
||||||
|
|||||||
@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_rp::clocks;
|
use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage, PllConfig};
|
||||||
use embassy_rp::clocks::{ClockConfig, CoreVoltage, PllConfig};
|
|
||||||
use embassy_rp::config::Config;
|
use embassy_rp::config::Config;
|
||||||
use embassy_rp::gpio::{Level, Output};
|
use embassy_rp::gpio::{Level, Output};
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
@ -41,9 +40,12 @@ async fn main(_spawner: Spawner) -> ! {
|
|||||||
// Initialize with our manual overclock configuration
|
// Initialize with our manual overclock configuration
|
||||||
let p = embassy_rp::init(configure_manual_overclock());
|
let p = embassy_rp::init(configure_manual_overclock());
|
||||||
|
|
||||||
// Verify the actual system clock frequency
|
// Show CPU frequency for verification
|
||||||
let sys_freq = clocks::clk_sys_freq();
|
let sys_freq = clk_sys_freq();
|
||||||
info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
|
info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
|
||||||
|
// Show core voltage for verification
|
||||||
|
let core_voltage = core_voltage().unwrap();
|
||||||
|
info!("Core voltage: {}", core_voltage);
|
||||||
|
|
||||||
// LED to indicate the system is running
|
// LED to indicate the system is running
|
||||||
let mut led = Output::new(p.PIN_25, Level::Low);
|
let mut led = Output::new(p.PIN_25, Level::Low);
|
||||||
|
|||||||
74
examples/rp235x/src/bin/overclock.rs
Normal file
74
examples/rp235x/src/bin/overclock.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//! # Overclocking the RP2350 to 200 MHz
|
||||||
|
//!
|
||||||
|
//! This example demonstrates how to configure the RP2350 to run at 200 MHz instead of the default 150 MHz.
|
||||||
|
//!
|
||||||
|
//! ## Note
|
||||||
|
//!
|
||||||
|
//! As of yet there is no official support for running the RP235x at higher clock frequencies and/or other core voltages than the default.
|
||||||
|
//! Doing so may cause unexpected behavior and/or damage the chip.
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage};
|
||||||
|
use embassy_rp::config::Config;
|
||||||
|
use embassy_rp::gpio::{Level, Output};
|
||||||
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
const COUNT_TO: i64 = 10_000_000;
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
|
// Set up for clock frequency of 200 MHz, setting all necessary defaults.
|
||||||
|
let mut config = Config::new(ClockConfig::system_freq(200_000_000).unwrap());
|
||||||
|
|
||||||
|
// since for the rp235x there is no official support for higher clock frequencies, `system_freq()` will not set a voltage for us.
|
||||||
|
// We need to guess the core voltage, that is needed for the higher clock frequency. Going with a small increase from the default 1.1V here, based on
|
||||||
|
// what we know about the RP2040. This is not guaranteed to be correct.
|
||||||
|
config.clocks.core_voltage = CoreVoltage::V1_15;
|
||||||
|
|
||||||
|
// Initialize the peripherals
|
||||||
|
let p = embassy_rp::init(config);
|
||||||
|
|
||||||
|
// Show CPU frequency for verification
|
||||||
|
let sys_freq = clk_sys_freq();
|
||||||
|
info!("System clock frequency: {} MHz", sys_freq / 1_000_000);
|
||||||
|
// Show core voltage for verification
|
||||||
|
let core_voltage = core_voltage().unwrap();
|
||||||
|
info!("Core voltage: {}", core_voltage);
|
||||||
|
|
||||||
|
// LED to indicate the system is running
|
||||||
|
let mut led = Output::new(p.PIN_25, Level::Low);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// Reset the counter at the start of measurement period
|
||||||
|
let mut counter = 0;
|
||||||
|
|
||||||
|
// Turn LED on while counting
|
||||||
|
led.set_high();
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
|
||||||
|
// This is a busy loop that will take some time to complete
|
||||||
|
while counter < COUNT_TO {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let elapsed = Instant::now() - start;
|
||||||
|
|
||||||
|
// Report the elapsed time
|
||||||
|
led.set_low();
|
||||||
|
info!(
|
||||||
|
"At {}Mhz: Elapsed time to count to {}: {}ms",
|
||||||
|
sys_freq / 1_000_000,
|
||||||
|
counter,
|
||||||
|
elapsed.as_millis()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wait 2 seconds before starting the next measurement
|
||||||
|
Timer::after(Duration::from_secs(2)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,14 +7,8 @@ teleprobe_meta::target!(b"rpi-pico");
|
|||||||
teleprobe_meta::target!(b"pimoroni-pico-plus-2");
|
teleprobe_meta::target!(b"pimoroni-pico-plus-2");
|
||||||
|
|
||||||
use defmt::info;
|
use defmt::info;
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
use defmt::{assert, assert_eq};
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_rp::clocks;
|
use embassy_rp::clocks::{clk_sys_freq, core_voltage, ClockConfig, CoreVoltage};
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
use embassy_rp::clocks::ClockConfig;
|
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
use embassy_rp::clocks::CoreVoltage;
|
|
||||||
use embassy_rp::config::Config;
|
use embassy_rp::config::Config;
|
||||||
use embassy_time::Instant;
|
use embassy_time::Instant;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -23,23 +17,26 @@ const COUNT_TO: i64 = 10_000_000;
|
|||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
#[cfg(feature = "rp2040")]
|
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
#[cfg(not(feature = "rp2040"))]
|
|
||||||
let config = Config::default();
|
|
||||||
|
|
||||||
// Initialize with 200MHz clock configuration for RP2040, other chips will use default clock
|
// Initialize with 200MHz clock configuration
|
||||||
#[cfg(feature = "rp2040")]
|
config.clocks = ClockConfig::system_freq(200_000_000).unwrap();
|
||||||
|
|
||||||
|
// if we are rp235x, we need to manually set the core voltage. rp2040 should do this automatically
|
||||||
|
#[cfg(feature = "rp235xb")]
|
||||||
{
|
{
|
||||||
config.clocks = ClockConfig::system_freq(200_000_000);
|
config.clocks.core_voltage = CoreVoltage::V1_15;
|
||||||
let voltage = config.clocks.core_voltage;
|
|
||||||
assert!(matches!(voltage, CoreVoltage::V1_15), "Expected voltage scale V1_15");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _p = embassy_rp::init(config);
|
let _p = embassy_rp::init(config);
|
||||||
|
|
||||||
|
// We should be at core voltage of 1.15V
|
||||||
|
assert_eq!(core_voltage().unwrap(), CoreVoltage::V1_15, "Core voltage is not 1.15V");
|
||||||
|
// We should be at 200MHz
|
||||||
|
assert_eq!(clk_sys_freq(), 200_000_000, "System clock frequency is not 200MHz");
|
||||||
|
|
||||||
// Test the system speed
|
// Test the system speed
|
||||||
let (time_elapsed, clk_sys_freq) = {
|
let time_elapsed = {
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
while counter < COUNT_TO {
|
while counter < COUNT_TO {
|
||||||
@ -47,24 +44,26 @@ async fn main(_spawner: Spawner) {
|
|||||||
}
|
}
|
||||||
let elapsed = Instant::now() - start;
|
let elapsed = Instant::now() - start;
|
||||||
|
|
||||||
(elapsed.as_millis(), clocks::clk_sys_freq())
|
elapsed.as_millis()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Report the elapsed time, so that the compiler doesn't optimize it away for chips other than RP2040
|
// Tests will fail if unused variables are detected:
|
||||||
|
// Report the elapsed time, so that the compiler doesn't optimize it away for the chip not on test
|
||||||
info!(
|
info!(
|
||||||
"At {}Mhz: Elapsed time to count to {}: {}ms",
|
"At {}Mhz: Elapsed time to count to {}: {}ms",
|
||||||
clk_sys_freq / 1_000_000,
|
clk_sys_freq() / 1_000_000,
|
||||||
COUNT_TO,
|
COUNT_TO,
|
||||||
time_elapsed
|
time_elapsed
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Check if the elapsed time is within expected limits
|
||||||
|
// for rp2040 we expect about 600ms
|
||||||
#[cfg(feature = "rp2040")]
|
#[cfg(feature = "rp2040")]
|
||||||
{
|
// allow 1% error
|
||||||
// we should be at 200MHz
|
assert!(time_elapsed < 606, "Elapsed time is too long");
|
||||||
assert_eq!(clk_sys_freq, 200_000_000, "System clock frequency is not 200MHz");
|
// for rp235x we expect about 450ms
|
||||||
// At 200MHz, the time to count to 10_000_000 should be at 600ms, testing with 1% margin
|
#[cfg(feature = "rp235xb")]
|
||||||
assert!(time_elapsed <= 606, "Elapsed time is too long");
|
assert!(time_elapsed < 455, "Elapsed time is too long");
|
||||||
}
|
|
||||||
|
|
||||||
cortex_m::asm::bkpt();
|
cortex_m::asm::bkpt();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user