mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-24 05:01:31 +11:00
Merge pull request #30 from 9names/fix_xosc_warning
Remove unnecessary unsafe block + cargo fmt XOSC
This commit is contained in:
commit
48dd8069b8
|
@ -2,23 +2,13 @@
|
||||||
// See [Chapter 2 Section 16](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details
|
// See [Chapter 2 Section 16](https://datasheets.raspberrypi.org/rp2040/rp2040_datasheet.pdf) for more details
|
||||||
|
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::{
|
use core::{convert::Infallible, ops::RangeInclusive};
|
||||||
convert::Infallible,
|
|
||||||
ops::RangeInclusive
|
|
||||||
};
|
|
||||||
|
|
||||||
use embedded_time::{
|
use embedded_time::{
|
||||||
fraction::Fraction,
|
duration::{Duration, Milliseconds},
|
||||||
fixed_point::FixedPoint,
|
fixed_point::FixedPoint,
|
||||||
rate::{
|
fraction::Fraction,
|
||||||
Hertz,
|
rate::{Hertz, Megahertz, Rate},
|
||||||
Megahertz,
|
|
||||||
Rate
|
|
||||||
},
|
|
||||||
duration::{
|
|
||||||
Milliseconds,
|
|
||||||
Duration
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use nb::Error::WouldBlock;
|
use nb::Error::WouldBlock;
|
||||||
|
@ -31,12 +21,12 @@ pub struct Disabled;
|
||||||
|
|
||||||
/// XOSC is initialized, ie we've given parameters (typestate)
|
/// XOSC is initialized, ie we've given parameters (typestate)
|
||||||
pub struct Initialized {
|
pub struct Initialized {
|
||||||
freq_hz: Hertz
|
freq_hz: Hertz,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stable state (typestate)
|
/// Stable state (typestate)
|
||||||
pub struct Stable{
|
pub struct Stable {
|
||||||
freq_hz: Hertz
|
freq_hz: Hertz,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// XOSC is in dormant mode (see Chapter 2, Section 16, §5)
|
/// XOSC is in dormant mode (see Chapter 2, Section 16, §5)
|
||||||
|
@ -53,13 +43,14 @@ pub enum Error {
|
||||||
FrequencyOutOfRange,
|
FrequencyOutOfRange,
|
||||||
|
|
||||||
/// Argument is bad : overflows, ...
|
/// Argument is bad : overflows, ...
|
||||||
BadArgument
|
BadArgument,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Blocking helper method to setup the XOSC without going through all the steps.
|
/// Blocking helper method to setup the XOSC without going through all the steps.
|
||||||
pub fn setup_xosc_blocking(xosc_dev: rp2040_pac::XOSC, frequency: Hertz) -> Result<CrystalOscillator<Stable>, Error> {
|
pub fn setup_xosc_blocking(
|
||||||
|
xosc_dev: rp2040_pac::XOSC,
|
||||||
|
frequency: Hertz,
|
||||||
|
) -> Result<CrystalOscillator<Stable>, Error> {
|
||||||
let initialized_xosc = CrystalOscillator::new(xosc_dev).initialize(frequency)?;
|
let initialized_xosc = CrystalOscillator::new(xosc_dev).initialize(frequency)?;
|
||||||
|
|
||||||
let stable_xosc_token = nb::block!(initialized_xosc.await_stabilization()).unwrap();
|
let stable_xosc_token = nb::block!(initialized_xosc.await_stabilization()).unwrap();
|
||||||
|
@ -67,11 +58,10 @@ pub fn setup_xosc_blocking(xosc_dev: rp2040_pac::XOSC, frequency: Hertz) -> Resu
|
||||||
Ok(initialized_xosc.get_stable(stable_xosc_token))
|
Ok(initialized_xosc.get_stable(stable_xosc_token))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A Crystal Oscillator.
|
/// A Crystal Oscillator.
|
||||||
pub struct CrystalOscillator<S: State> {
|
pub struct CrystalOscillator<S: State> {
|
||||||
device: rp2040_pac::XOSC,
|
device: rp2040_pac::XOSC,
|
||||||
state: S
|
state: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: State> CrystalOscillator<S> {
|
impl<S: State> CrystalOscillator<S> {
|
||||||
|
@ -79,7 +69,7 @@ impl<S: State> CrystalOscillator<S> {
|
||||||
fn transition<To: State>(self, state: To) -> CrystalOscillator<To> {
|
fn transition<To: State>(self, state: To) -> CrystalOscillator<To> {
|
||||||
CrystalOscillator {
|
CrystalOscillator {
|
||||||
device: self.device,
|
device: self.device,
|
||||||
state: state
|
state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,26 +80,25 @@ impl<S: State> CrystalOscillator<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrystalOscillator<Disabled> {
|
impl CrystalOscillator<Disabled> {
|
||||||
|
|
||||||
/// Creates a new CrystalOscillator from the underlying device.
|
/// Creates a new CrystalOscillator from the underlying device.
|
||||||
pub fn new(dev: rp2040_pac::XOSC) -> Self {
|
pub fn new(dev: rp2040_pac::XOSC) -> Self {
|
||||||
CrystalOscillator {
|
CrystalOscillator {
|
||||||
device: dev,
|
device: dev,
|
||||||
state: Disabled
|
state: Disabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the XOSC : frequency range is set, startup delay is calculated and set.
|
/// Initializes the XOSC : frequency range is set, startup delay is calculated and set.
|
||||||
pub fn initialize(self, frequency: Hertz) -> Result<CrystalOscillator<Initialized>, Error> {
|
pub fn initialize(self, frequency: Hertz) -> Result<CrystalOscillator<Initialized>, Error> {
|
||||||
|
const ALLOWED_FREQUENCY_RANGE: RangeInclusive<Megahertz<u32>> =
|
||||||
const ALLOWED_FREQUENCY_RANGE: RangeInclusive<Megahertz<u32>> = Megahertz(1)..=Megahertz(15);
|
Megahertz(1)..=Megahertz(15);
|
||||||
const STABLE_DELAY: Milliseconds = Milliseconds(1_u32);
|
const STABLE_DELAY: Milliseconds = Milliseconds(1_u32);
|
||||||
const DIVIDER: Fraction = Fraction::new(256, 1);
|
const DIVIDER: Fraction = Fraction::new(256, 1);
|
||||||
|
|
||||||
let freq_mhz: Megahertz = frequency.into();
|
let freq_mhz: Megahertz = frequency.into();
|
||||||
|
|
||||||
if !ALLOWED_FREQUENCY_RANGE.contains(&freq_mhz) {
|
if !ALLOWED_FREQUENCY_RANGE.contains(&freq_mhz) {
|
||||||
return Err(Error::FrequencyOutOfRange)
|
return Err(Error::FrequencyOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.device.ctrl.write(|w| {
|
self.device.ctrl.write(|w| {
|
||||||
|
@ -118,20 +107,20 @@ impl CrystalOscillator<Disabled> {
|
||||||
});
|
});
|
||||||
|
|
||||||
//1 ms = 10e-3 sec and Freq = 1/T where T is in seconds so 1ms converts to 1000Hz
|
//1 ms = 10e-3 sec and Freq = 1/T where T is in seconds so 1ms converts to 1000Hz
|
||||||
let delay_to_hz: Hertz = STABLE_DELAY.to_rate().map_err(|_|Error::BadArgument)?;
|
let delay_to_hz: Hertz = STABLE_DELAY.to_rate().map_err(|_| Error::BadArgument)?;
|
||||||
|
|
||||||
//startup_delay = ((freq_hz * 10e-3) / 256) = ((freq_hz / 1000) / 256)
|
//startup_delay = ((freq_hz * 10e-3) / 256) = ((freq_hz / 1000) / 256)
|
||||||
//See Chapter 2, Section 16, §3)
|
//See Chapter 2, Section 16, §3)
|
||||||
//We do the calculation first.
|
//We do the calculation first.
|
||||||
let startup_delay = frequency.
|
let startup_delay = frequency
|
||||||
checked_div(delay_to_hz.integer()).and_then(|r|
|
.checked_div(delay_to_hz.integer())
|
||||||
r.to_generic::<u32>(DIVIDER).ok()
|
.and_then(|r| r.to_generic::<u32>(DIVIDER).ok())
|
||||||
).
|
.ok_or(Error::BadArgument)?;
|
||||||
ok_or(Error::BadArgument)?;
|
|
||||||
|
|
||||||
//Then we check if it fits into an u16.
|
//Then we check if it fits into an u16.
|
||||||
let startup_delay: u16 = (*startup_delay.integer()).try_into().
|
let startup_delay: u16 = (*startup_delay.integer())
|
||||||
map_err(|_|Error::BadArgument)?;
|
.try_into()
|
||||||
|
.map_err(|_| Error::BadArgument)?;
|
||||||
|
|
||||||
self.device.startup.write(|w| unsafe {
|
self.device.startup.write(|w| unsafe {
|
||||||
w.delay().bits(startup_delay);
|
w.delay().bits(startup_delay);
|
||||||
|
@ -143,42 +132,33 @@ impl CrystalOscillator<Disabled> {
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(self.transition(Initialized {
|
Ok(self.transition(Initialized { freq_hz: frequency }))
|
||||||
freq_hz: frequency
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A token that's given when the oscillator is stablilzed, and can be exchanged to proceed to the next stage.
|
/// A token that's given when the oscillator is stablilzed, and can be exchanged to proceed to the next stage.
|
||||||
pub struct StableOscillatorToken {
|
pub struct StableOscillatorToken {
|
||||||
_private : ()
|
_private: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrystalOscillator<Initialized> {
|
impl CrystalOscillator<Initialized> {
|
||||||
|
|
||||||
/// One has to wait for the startup delay before using the oscillator, ie awaiting stablilzation of the XOSC
|
/// One has to wait for the startup delay before using the oscillator, ie awaiting stablilzation of the XOSC
|
||||||
pub fn await_stabilization(&self) -> nb::Result<StableOscillatorToken, Infallible> {
|
pub fn await_stabilization(&self) -> nb::Result<StableOscillatorToken, Infallible> {
|
||||||
|
|
||||||
if self.device.status.read().stable().bit_is_clear() {
|
if self.device.status.read().stable().bit_is_clear() {
|
||||||
return Err(WouldBlock)
|
return Err(WouldBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(StableOscillatorToken {
|
Ok(StableOscillatorToken { _private: () })
|
||||||
_private: ()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the stablilzed oscillator
|
/// Returns the stablilzed oscillator
|
||||||
pub fn get_stable(self, _token: StableOscillatorToken) -> CrystalOscillator<Stable> {
|
pub fn get_stable(self, _token: StableOscillatorToken) -> CrystalOscillator<Stable> {
|
||||||
let freq_hz = self.state.freq_hz;
|
let freq_hz = self.state.freq_hz;
|
||||||
self.transition(Stable {
|
self.transition(Stable { freq_hz })
|
||||||
freq_hz
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrystalOscillator<Stable> {
|
impl CrystalOscillator<Stable> {
|
||||||
|
|
||||||
/// Operating frequency of the XOSC in hertz
|
/// Operating frequency of the XOSC in hertz
|
||||||
pub fn operating_frequency(&self) -> Hertz {
|
pub fn operating_frequency(&self) -> Hertz {
|
||||||
self.state.freq_hz
|
self.state.freq_hz
|
||||||
|
@ -186,7 +166,7 @@ impl CrystalOscillator<Stable> {
|
||||||
|
|
||||||
/// Disables the XOSC
|
/// Disables the XOSC
|
||||||
pub fn disable(self) -> CrystalOscillator<Disabled> {
|
pub fn disable(self) -> CrystalOscillator<Disabled> {
|
||||||
self.device.ctrl.modify(|_r,w| {
|
self.device.ctrl.modify(|_r, w| {
|
||||||
w.enable().disable();
|
w.enable().disable();
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
|
@ -203,7 +183,7 @@ impl CrystalOscillator<Stable> {
|
||||||
//taken from the C SDK
|
//taken from the C SDK
|
||||||
const XOSC_DORMANT_VALUE: u32 = 0x636f6d61;
|
const XOSC_DORMANT_VALUE: u32 = 0x636f6d61;
|
||||||
|
|
||||||
self.device.dormant.write(|w| unsafe {
|
self.device.dormant.write(|w| {
|
||||||
w.bits(XOSC_DORMANT_VALUE);
|
w.bits(XOSC_DORMANT_VALUE);
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue