From 62e65e173cc7cc6909e29bd73ddef4915080de2d Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Sat, 28 Dec 2024 02:23:23 +0100 Subject: [PATCH] Use proto-hal for 'entitlement' instead of 'observation' --- Cargo.toml | 1 + examples/observe.rs | 6 +- src/adc.rs | 21 ++++-- src/comparator.rs | 17 +++-- src/dac.rs | 3 +- src/gpio.rs | 3 +- src/lib.rs | 1 - src/observable.rs | 161 -------------------------------------------- src/opamp.rs | 61 ++++++++--------- 9 files changed, 59 insertions(+), 215 deletions(-) delete mode 100644 src/observable.rs diff --git a/Cargo.toml b/Cargo.toml index 84d4bc39..66755750 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ version = "0.0.2" nb = "0.1.1" #stm32g4 = { git = "https://github.com/stm32-rs/stm32-rs-nightlies" } #"0.15.1" stm32g4 = { version = "0.19.0", package = "stm32g4-staging" } +proto-hal = { git = "https://github.com/AdinAck/proto-hal", rev = "9030895" } paste = "1.0" bitflags = "1.2" vcell = "0.1" diff --git a/examples/observe.rs b/examples/observe.rs index 4b184c6a..89ad505e 100644 --- a/examples/observe.rs +++ b/examples/observe.rs @@ -18,10 +18,10 @@ use hal::{ comparator::{ComparatorExt, ComparatorSplit, Config}, delay::SYSTDelayExt as _, gpio::GpioExt, - observable::Observable as _, rcc::RccExt, stm32, }; +use proto_hal::stasis::Freeze; use rt::entry; use stm32g4xx_hal::{self as hal, adc::config::SampleTime, delay::DelayExt as _}; @@ -38,7 +38,7 @@ fn main() -> ! { let (pa1, [pa1_token]) = gpioa // <- The pin to keep track of .pa1 .into_analog() - .observe(); + .freeze(); let pa0 = gpioa.pa0.into_analog(); // <- Reference voltage // Only pa1_token and pa0 consumed here @@ -57,7 +57,7 @@ fn main() -> ! { // Can not reconfigure pa1 here loop { // Can still use pa1 here - let sample = adc.convert(pa1.as_ref(), SampleTime::Cycles_640_5); + let sample = adc.convert(&pa1, SampleTime::Cycles_640_5); info!("Reading: {}", sample); delay.delay(1000.millis()); } diff --git a/src/adc.rs b/src/adc.rs index 600e8bcf..5e1ca88c 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -24,6 +24,7 @@ use embedded_hal::{ adc::{Channel, OneShot}, blocking::delay::DelayUs, }; +use proto_hal::stasis; use self::config::ExternalTrigger12; @@ -136,7 +137,9 @@ impl Temperature { macro_rules! adc_pins { ($($pin:ty => ($adc:ident, $chan:expr)),+ $(,)*) => { $( - impl Channel for $pin { + impl

Channel for P + where P: stasis::EntitlementLock + { type ID = u8; fn channel() -> u8 { $chan } } @@ -147,22 +150,30 @@ macro_rules! adc_pins { macro_rules! adc_opamp { ($($opamp:ty => ($adc:ident, $chan:expr)),+ $(,)*) => { $( - impl Channel for opamp::Follower<$opamp, A, InternalOutput> { + impl Channel for P + where P: stasis::EntitlementLock> + { type ID = u8; fn channel() -> u8 { $chan } } - impl Channel for opamp::OpenLoop<$opamp, A, B, InternalOutput> { + impl Channel for P + where P: stasis::EntitlementLock> + { type ID = u8; fn channel() -> u8 { $chan } } - impl Channel for opamp::Pga<$opamp, A, InternalOutput> { + impl Channel for P + where P: stasis::EntitlementLock> + { type ID = u8; fn channel() -> u8 { $chan } } - impl Channel for opamp::Locked<$opamp, InternalOutput> { + impl

Channel for P + where P: stasis::EntitlementLock> + { type ID = u8; fn channel() -> u8 { $chan } } diff --git a/src/comparator.rs b/src/comparator.rs index 5ebb880e..303e14f1 100644 --- a/src/comparator.rs +++ b/src/comparator.rs @@ -34,9 +34,9 @@ use crate::gpio::{ use crate::gpio::gpioc::{PC0, PC1}; use crate::gpio::gpioe::{PE7, PE8}; use crate::gpio::gpiof::PF1; -use crate::observable::ObservationLock; use crate::rcc::{Clocks, Rcc}; use crate::stm32::{COMP, EXTI}; +use proto_hal::stasis; /// Enabled Comparator (type state) pub struct Enabled; @@ -265,8 +265,7 @@ pub mod refint_input { const USE_RESISTOR_DIVIDER: bool = $use_r_div; } - impl crate::observable::Observable for $t {} - impl crate::Sealed for $t {} + impl proto_hal::stasis::Freeze for $t {} }; } @@ -398,8 +397,8 @@ pub trait ComparatorExt { where PP: PositiveInput, NP: NegativeInput, - P: ObservationLock, - N: ObservationLock; + P: stasis::EntitlementLock, + N: stasis::EntitlementLock; } macro_rules! impl_comparator { @@ -415,8 +414,8 @@ macro_rules! impl_comparator { where PP: PositiveInput<$COMP>, NP: NegativeInput<$COMP>, - P: ObservationLock, - N: ObservationLock, + P: stasis::EntitlementLock, + N: stasis::EntitlementLock, { PP::setup(&mut self); PP::setup(&mut self); @@ -453,8 +452,8 @@ macro_rules! impl_comparator { where PP: PositiveInput<$COMP>, NP: NegativeInput<$COMP>, - P: ObservationLock, - N: ObservationLock, + P: stasis::EntitlementLock, + N: stasis::EntitlementLock, { comp.comparator(positive_input, negative_input, config, clocks) } diff --git a/src/dac.rs b/src/dac.rs index 48c948c1..1af2aab4 100644 --- a/src/dac.rs +++ b/src/dac.rs @@ -218,8 +218,7 @@ macro_rules! dac_helper { } } - impl crate::Sealed for $CX { } - impl crate::observable::Observable for $CX { } + impl proto_hal::stasis::Freeze for $CX { } impl $CX { /// Calibrate the DAC output buffer by performing a "User diff --git a/src/gpio.rs b/src/gpio.rs index 00fdf28a..1f460fe6 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -1,7 +1,6 @@ //! General Purpose Input / Output use core::marker::PhantomData; -use crate::observable::Observable; use crate::rcc::Rcc; use crate::stm32::EXTI; use crate::syscfg::SysCfg; @@ -380,7 +379,7 @@ macro_rules! gpio { } } - impl Observable for $PXi { } + impl proto_hal::stasis::Freeze for $PXi { } impl $PXi { /// Configures the pin to operate as a floating input pin diff --git a/src/lib.rs b/src/lib.rs index 57d0fabd..93c12d07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,7 +84,6 @@ pub mod exti; pub mod flash; pub mod gpio; pub mod i2c; -pub mod observable; pub mod opamp; pub mod prelude; pub mod pwm; diff --git a/src/observable.rs b/src/observable.rs deleted file mode 100644 index 40067347..00000000 --- a/src/observable.rs +++ /dev/null @@ -1,161 +0,0 @@ -use crate::Sealed; -use core::{marker::PhantomData, ops}; - -pub trait ObservationLock: Sized + crate::Sealed { - type Peripheral: Observable; -} - -/// A struct to hold peripherals which are to be observed. -/// -/// This prevents the observed peripheral from being consumed. Thus -/// preventing things like a an observed gpio pin changing mode or an opamp from -/// being disabled. This makes sure the underlaying peripheral will not -/// change mode into something that is not compatible with what ever may be observing it. -pub struct Observed { - peripheral: P, -} - -impl Observed { - /// Release the observation of this peripheral - /// - /// This returns the underlaying perpheral type. Since it is no longer - /// observed, you are once again free to do what you want with it. - pub fn release(self, _data: [ObservationToken

; OBSERVER_COUNT]) -> P { - self.peripheral - } -} - -/// A struct to represent a registered observation of a peripheral of type `P` -/// -/// The existence of this type guarantees that the observed peripheral will not -/// change mode into something that is not compatibe with what ever is observing it -pub struct ObservationToken { - _p: PhantomData

, -} - -/// A trait providing an interface to make peripherals observed -/// -/// See [`Observable::observe`], [`Observed`] and [`ObservationToken`] -pub trait Observable: Sized { - /// Observe this peripheral to split it into a [`Observed`] and a set of [`ObservationToken`]'s - /// - /// This is useful when you need the same peripherals for multiple things at the same time. - /// - /// For example let's say you want to keep track of the voltage of a pin. You want to log it - /// every second but if it rises above a threshold then you need to react really fast. - /// - /// This can be solved by connecting the pin to a comparator that compares the pins - /// voltage to a reference. If the voltage rises above the reference then the comparator - /// will quickly detect this and an interrupt can be generated or similar (not shown here). - /// - /// ``` - /// let dp = stm32::Peripherals::take().unwrap(); - /// let mut rcc = dp.RCC.constrain(); - /// - /// let gpioa = dp.GPIOA.split(&mut rcc); - /// - /// let (comp1, comp2, ..) = dp.COMP.split(&mut rcc); - /// - /// let pa1 = gpioa.pa1.into_analog(); // <- The pin to keep track of - /// let pa0 = gpioa.pa0.into_analog(); // <- Reference voltage - /// - /// // Pins consumed here - /// let comp1 = comp1.comparator(pa1, pa0, Config::default(), &rcc.clocks); - /// let comp1 = comp1.enable(); - /// - /// // Can not use pa0 and pa1 for AD readings - /// ``` - /// - /// However we still want to perform AD readings every second. Since the pins are consumed - /// by the comparator this is impossible. - /// - /// It turns ut that to construct the comparator we do not actually need a pin. We - /// just need proof that there is a pin that is setup in the correct mode and which - /// will stay in that mode as long as the comparator lives. - /// - /// This is where [`Observable::observe`] comes in. It splits the peripheral, in this case - /// a pin, into an [`Observed`] and a set of [`ObservationToken`]'s. The `Observed` - /// type can be used just like the peripheral would normally be used. For our pin we can - /// use it to perform AD readings etc. There is however one vital difference, we can not - /// reconfigure the observed peripheral. The `ObservationToken`'s on the other hand - /// are tokens that proove that the peripheral will not be reconfigured. These can then - /// be used instead of the peripheral to pass as arguments to other peripherals. - /// - /// ``` - /// let cp = cortex_m::Peripherals::take().unwrap(); - /// let dp = stm32::Peripherals::take().unwrap(); - /// let mut rcc = dp.RCC.constrain(); - /// - /// let gpioa = dp.GPIOA.split(&mut rcc); - /// - /// let (comp1, ..) = dp.COMP.split(&mut rcc); - /// - /// let (pa1, [pa1_token]) = gpioa // <- The pin to keep track of - /// .pa1 - /// .into_analog() - /// .observe(); - /// let pa0 = gpioa.pa0.into_analog(); // <- Reference voltage - /// - /// // Only pa1_token and pa0 consumed here - /// let comp1 = comp1.comparator(pa1_token, pa0, Config::default(), &rcc.clocks); - /// let _comp1 = comp1.enable(); // <-- TODO: Do things with comparator - /// - /// let mut delay = cp.SYST.delay(&rcc.clocks); - /// let mut adc = dp.ADC1.claim_and_configure( - /// stm32g4xx_hal::adc::ClockSource::SystemClock, - /// &rcc, - /// stm32g4xx_hal::adc::config::AdcConfig::default(), - /// &mut delay, - /// false, - /// ); - /// - /// // Can not reconfigure pa1 here - /// loop { - /// // Can still use pa1 here - /// let sample = adc.convert(pa1.as_ref(), SampleTime::Cycles_640_5); - /// defmt::info!("Reading: {}", sample); - /// delay.delay(1000.millis()); - /// } - /// ``` - fn observe(self) -> (Observed, [ObservationToken; N]) { - ( - Observed { peripheral: self }, - core::array::from_fn(|_| ObservationToken { _p: PhantomData }), - ) - } -} - -impl ObservationLock for P { - type Peripheral = P; -} - -impl Sealed for ObservationToken

{} -impl ObservationLock for ObservationToken

{ - type Peripheral = P; -} - -impl AsRef

for Observed { - fn as_ref(&self) -> &P { - &self.peripheral - } -} - -impl AsMut

for Observed { - fn as_mut(&mut self) -> &mut P { - &mut self.peripheral - } -} - -impl ops::Deref for Observed { - type Target = P; - - fn deref(&self) -> &Self::Target { - &self.peripheral - } -} - -impl ops::DerefMut for Observed { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.peripheral - } -} diff --git a/src/opamp.rs b/src/opamp.rs index 63dea5bd..9ebb2a6e 100644 --- a/src/opamp.rs +++ b/src/opamp.rs @@ -59,8 +59,8 @@ // TODO: Add support for calibration -use crate::observable::{Observable, ObservationLock}; use core::marker::PhantomData; +use proto_hal::stasis; /// PGA Gain pub enum Gain { @@ -147,8 +147,8 @@ where gain: Gain, ) -> Pga where - F: ObservationLock, - Opamp::Vinm0: Observable; + F: stasis::EntitlementLock, + Opamp::Vinm0: stasis::Freeze; /// Configures the opamp for programmable gain operation, with /// external filtering. @@ -159,8 +159,8 @@ where gain: Gain, ) -> Pga where - N: ObservationLock, - Opamp::Vinm0: Observable; + N: stasis::EntitlementLock, + Opamp::Vinm0: stasis::Freeze; /// Configures the opamp for programmable gain operation, with /// external filtering. @@ -172,10 +172,10 @@ where gain: Gain, ) -> Pga where - N: ObservationLock, - F: ObservationLock, - Opamp::Vinm0: Observable, - Opamp::Vinm1: Observable; + N: stasis::EntitlementLock, + F: stasis::EntitlementLock, + Opamp::Vinm0: stasis::Freeze, + Opamp::Vinm1: stasis::Freeze; } /// Internal trait implementing the low level register write used to @@ -185,9 +185,9 @@ where Opamp: LookupPgaGain, { /// Type of the associated vinm0 input. - type Vinm0: Observable; + type Vinm0: stasis::Freeze; /// Type of the associated vinm1 input. - type Vinm1: Observable; + type Vinm1: stasis::Freeze; /// Write the opamp CSR register configuring the opamp PGA. /// @@ -377,8 +377,7 @@ macro_rules! opamps { } } - impl crate::Sealed for Follower<$opamp, Input, Output> { } - impl crate::observable::Observable for Follower<$opamp, Input, Output> { } + impl stasis::Freeze for Follower<$opamp, Input, Output> { } impl Follower<$opamp, Input, Output> { /// Set the lock bit in the registers. After the lock bit is @@ -419,7 +418,7 @@ macro_rules! opamps { /// Enables the external output pin. pub fn enable_output(self, output: O) -> Follower<$opamp, Input, O> - where O: ObservationLock + where O: stasis::EntitlementLock { unsafe { $opamp::_enable_output(); } @@ -431,8 +430,7 @@ macro_rules! opamps { } } - impl crate::Sealed for OpenLoop<$opamp, NonInverting, Inverting, Output> { } - impl crate::observable::Observable for OpenLoop<$opamp, NonInverting, Inverting, Output> { } + impl stasis::Freeze for OpenLoop<$opamp, NonInverting, Inverting, Output> { } impl OpenLoop<$opamp, NonInverting, Inverting, Output> { /// Set the lock bit in the registers. After the lock bit is @@ -474,7 +472,7 @@ macro_rules! opamps { /// Enables the external output pin. pub fn enable_output(self, output: O) -> OpenLoop<$opamp, NonInverting, Inverting, O> - where O: ObservationLock, + where O: stasis::EntitlementLock, { unsafe { $opamp::_enable_output(); } @@ -487,8 +485,7 @@ macro_rules! opamps { } } - impl crate::Sealed for Pga<$opamp, NonInverting, Output> { } - impl crate::observable::Observable for Pga<$opamp, NonInverting, Output> { } + impl stasis::Freeze for Pga<$opamp, NonInverting, Output> { } impl Pga<$opamp, NonInverting, Output> { /// Set the lock bit in the registers. After the lock bit is @@ -529,7 +526,7 @@ macro_rules! opamps { /// Enables the external output pin. pub fn enable_output(self, output: O) -> Pga<$opamp, NonInverting, O> where - O: ObservationLock, + O: stasis::EntitlementLock, { unsafe { $opamp::_enable_output(); } @@ -588,7 +585,7 @@ macro_rules! opamps { impl IntoFollower<$opamp, Input, InternalOutput> for Disabled<$opamp> where I: NonInverting<$opamp, VP_SEL=crate::stm32::opamp::[<$opampreg _csr>]::VP_SEL>, - Input: ObservationLock, + Input: stasis::EntitlementLock, { fn follower( self, @@ -627,8 +624,8 @@ macro_rules! opamps { where PP: NonInverting<$opamp, VP_SEL=crate::stm32::opamp::[<$opampreg _csr>]::VP_SEL>, NP: Inverting<$opamp, VM_SEL=crate::stm32::opamp::[<$opampreg _csr>]::VM_SEL>, - P: ObservationLock, - N: ObservationLock, + P: stasis::EntitlementLock, + N: stasis::EntitlementLock, { fn open_loop( self, @@ -669,7 +666,7 @@ macro_rules! opamps { impl ConfigurePgaReg<$opamp, P> for $opamp where PP: NonInverting<$opamp, VP_SEL=crate::stm32::opamp::[<$opampreg _csr>]::VP_SEL>, - P: ObservationLock, + P: stasis::EntitlementLock, { type Vinm0 = $vinm0; type Vinm1 = $vinm1; @@ -696,7 +693,7 @@ macro_rules! opamps { impl IntoPga<$opamp, P> for Disabled<$opamp> where PP: NonInverting<$opamp, VP_SEL=crate::stm32::opamp::[<$opampreg _csr>]::VP_SEL>, - P: ObservationLock, + P: stasis::EntitlementLock, { fn pga( self, @@ -705,7 +702,7 @@ macro_rules! opamps { ) -> Pga<$opamp, P, InternalOutput> where PP: NonInverting<$opamp, VP_SEL=crate::stm32::opamp::[<$opampreg _csr>]::VP_SEL>, - P: ObservationLock, + P: stasis::EntitlementLock, { $opamp::configure_pga(gain, PgaMode::Pga) } @@ -718,8 +715,8 @@ macro_rules! opamps { gain: Gain, ) -> Pga<$opamp, P, InternalOutput> where - F: ObservationLock>::Vinm0>, - F::Peripheral: Observable + F: stasis::EntitlementLock>::Vinm0>, + F::Resource: stasis::Freeze { $opamp::configure_pga(gain, PgaMode::PgaExternalFilter) } @@ -732,8 +729,8 @@ macro_rules! opamps { gain: Gain, ) -> Pga<$opamp, P, InternalOutput> where - N: ObservationLock>::Vinm0>, - N::Peripheral: Observable + N: stasis::EntitlementLock>::Vinm0>, + N::Resource: stasis::Freeze { $opamp::configure_pga(gain, PgaMode::PgaExternalBias) } @@ -747,8 +744,8 @@ macro_rules! opamps { gain: Gain, ) -> Pga<$opamp, P, InternalOutput> where - N: ObservationLock>::Vinm0>, - F: ObservationLock>::Vinm1>, + N: stasis::EntitlementLock>::Vinm0>, + F: stasis::EntitlementLock>::Vinm1>, { $opamp::configure_pga(gain, PgaMode::PgaExternalBiasAndFilter) }