Merge pull request #30 from 9names/fix_xosc_warning

Remove unnecessary unsafe block + cargo fmt XOSC
This commit is contained in:
9names 2021-04-29 17:53:22 +10:00 committed by GitHub
commit 48dd8069b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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
}); });