diff --git a/CHANGELOG.md b/CHANGELOG.md index 00b9a345..7e5b9ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed +- `Adc::new` instead of `Adc::adcX` and `AdcExt` trait - Update `bxcan`, `heapless`, `mfrc522`, reenable `mpu9250` example [#513] - PWM timer auto reload value is now preloaded/buffered [#453] - Move from bors/manual merge to GH merge queue [#467] diff --git a/Cargo.toml b/Cargo.toml index a4305743..e44869cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ features = ["stm32f103", "rtic", "high"] default-target = "x86_64-unknown-linux-gnu" [dependencies] -defmt = { version = "0.3.8", optional = true } +defmt = { version = "1.0", optional = true } cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.3" nb = "1.1" @@ -36,7 +36,7 @@ vcell = "0.1.3" [dependencies.stm32f1] package = "stm32f1-staging" -version = "0.19.0" +version = "0.20.0" features = ["atomics"] [dependencies.embedded-hal-02] @@ -58,7 +58,7 @@ version = "0.7.0" optional = true [dev-dependencies] -panic-halt = "0.2.0" +panic-halt = "1.0.0" panic-semihosting = "0.6.0" panic-itm = "0.4.2" cortex-m-rtic = "1.1.3" diff --git a/examples/adc-dma-circ.rs b/examples/adc-dma-circ.rs index ae24a9f3..ec8c7c54 100644 --- a/examples/adc-dma-circ.rs +++ b/examples/adc-dma-circ.rs @@ -28,7 +28,7 @@ fn main() -> ! { let dma_ch1 = p.DMA1.split().1; // Setup ADC - let adc1 = adc::Adc::adc1(p.ADC1, &clocks); + let adc1 = adc::Adc::new(p.ADC1, &clocks); // Setup GPIOA let mut gpioa = p.GPIOA.split(); diff --git a/examples/adc-dma-rx.rs b/examples/adc-dma-rx.rs index ce9f8aab..4aeb3e25 100644 --- a/examples/adc-dma-rx.rs +++ b/examples/adc-dma-rx.rs @@ -28,7 +28,7 @@ fn main() -> ! { let dma_ch1 = p.DMA1.split().1; // Setup ADC - let adc1 = adc::Adc::adc1(p.ADC1, &clocks); + let adc1 = adc::Adc::new(p.ADC1, &clocks); // Setup GPIOA let mut gpioa = p.GPIOA.split(); diff --git a/examples/adc.rs b/examples/adc.rs index 79823392..dab7ec32 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -25,10 +25,10 @@ fn main() -> ! { hprintln!("adc freq: {}", clocks.adcclk()); // Setup ADC - let mut adc1 = adc::Adc::adc1(p.ADC1, &clocks); + let mut adc1 = adc::Adc::new(p.ADC1, &clocks); #[cfg(any(feature = "stm32f103", feature = "connectivity"))] - let mut adc2 = adc::Adc::adc2(p.ADC2, &clocks); + let mut adc2 = adc::Adc::new(p.ADC2, &clocks); // Setup GPIOB let mut gpiob = p.GPIOB.split(); diff --git a/examples/adc_temperature.rs b/examples/adc_temperature.rs index b4d637f6..19f62820 100644 --- a/examples/adc_temperature.rs +++ b/examples/adc_temperature.rs @@ -5,7 +5,7 @@ use panic_semihosting as _; use cortex_m_rt::entry; -use stm32f1xx_hal::{adc, pac, prelude::*}; +use stm32f1xx_hal::{pac, prelude::*}; use cortex_m_semihosting::hprintln; @@ -38,7 +38,7 @@ fn main() -> ! { hprintln!("adc freq: {}", clocks.adcclk()); // Setup ADC - let mut adc = adc::Adc::adc1(p.ADC1, &clocks); + let mut adc = p.ADC1.adc(&clocks); // Read temperature sensor loop { diff --git a/src/adc.rs b/src/adc.rs index 72498d9f..1820438d 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -1,6 +1,7 @@ //! # API for the Analog to Digital converter use core::marker::PhantomData; +use core::ops::Deref; use embedded_hal_02::adc::{Channel, OneShot}; use fugit::HertzU32 as Hertz; @@ -15,6 +16,7 @@ use cortex_m::asm::delay; use embedded_dma::WriteBuffer; use crate::pac::{self, RCC}; +use crate::pacext::adc::{AdcRB, Cr1W, Cr2R, Cr2W, Dr, ExtSelW}; /// Continuous mode pub struct Continuous; @@ -61,18 +63,18 @@ impl Default for SampleTime { } } -impl From for u8 { +impl From for pac::adc1::smpr1::SMP10 { fn from(val: SampleTime) -> Self { use SampleTime::*; match val { - T_1 => 0, - T_7 => 1, - T_13 => 2, - T_28 => 3, - T_41 => 4, - T_55 => 5, - T_71 => 6, - T_239 => 7, + T_1 => Self::Cycles1_5, + T_7 => Self::Cycles7_5, + T_13 => Self::Cycles13_5, + T_28 => Self::Cycles28_5, + T_41 => Self::Cycles41_5, + T_55 => Self::Cycles55_5, + T_71 => Self::Cycles71_5, + T_239 => Self::Cycles239_5, } } } @@ -93,11 +95,11 @@ impl Default for Align { } } -impl From for bool { +impl From for pac::adc1::cr2::ALIGN { fn from(val: Align) -> Self { match val { - Align::Right => false, - Align::Left => true, + Align::Right => Self::Right, + Align::Left => Self::Left, } } } @@ -174,305 +176,325 @@ adc_pins!(pac::ADC3, #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] pub struct StoredConfig(SampleTime, Align); -macro_rules! adc_hal { - ($( - $ADC:ty: ($adc:ident), - )+) => { - $( +pub trait Instance: + crate::Sealed + crate::Ptr + Deref + Reset + Enable +{ + type ExtSel; + #[doc(hidden)] + fn set_extsel(&self, trigger: Self::ExtSel); +} - impl Adc<$ADC> { - /// Init a new Adc - /// - /// Sets all configurable parameters to one-shot defaults, - /// performs a boot-time calibration. - pub fn $adc(adc: $ADC, clocks: &Clocks) -> Self { - let mut s = Self { - rb: adc, - sample_time: SampleTime::default(), - align: Align::default(), - sysclk: clocks.sysclk(), - adcclk: clocks.adcclk(), - }; - s.enable_clock(); - s.power_down(); - s.reset(); - s.setup_oneshot(); - s.power_up(); - - // The manual states that we need to wait two ADC clocks cycles after power-up - // before starting calibration, we already delayed in the power-up process, but - // if the adc clock is too low that was not enough. - if s.adcclk < kHz(2500) { - let two_adc_cycles = s.sysclk / s.adcclk * 2; - let already_delayed = s.sysclk / kHz(800); - if two_adc_cycles > already_delayed { - delay(two_adc_cycles - already_delayed); - } - } - s.calibrate(); - s - } +impl Instance for pac::ADC1 { + type ExtSel = crate::pac::adc1::cr2::EXTSEL; + fn set_extsel(&self, trigger: Self::ExtSel) { + self.cr2().modify(|_, w| w.extsel().variant(trigger)); + } +} +#[cfg(any(feature = "stm32f103", feature = "connectivity"))] +impl Instance for pac::ADC2 { + type ExtSel = crate::pac::adc2::cr2::EXTSEL; + fn set_extsel(&self, trigger: Self::ExtSel) { + self.cr2().modify(|_, w| w.extsel().variant(trigger)); + } +} +#[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl")))] +impl Instance for pac::ADC3 { + type ExtSel = crate::pac::adc3::cr2::EXTSEL; + fn set_extsel(&self, trigger: Self::ExtSel) { + self.cr2().modify(|_, w| w.extsel().variant(trigger)); + } +} - /// Save current ADC config - pub fn save_cfg(&mut self) -> StoredConfig { - StoredConfig(self.sample_time, self.align) - } +pub trait AdcExt: Sized + Instance { + fn adc(self, clocks: &Clocks) -> Adc; +} - /// Restore saved ADC config - pub fn restore_cfg(&mut self, cfg: StoredConfig) { - self.sample_time = cfg.0; - self.align = cfg.1; - } +impl AdcExt for ADC { + fn adc(self, clocks: &Clocks) -> Adc { + Adc::new(self, clocks) + } +} - /// Reset the ADC config to default, return existing config - pub fn default_cfg(&mut self) -> StoredConfig { - let cfg = self.save_cfg(); - self.sample_time = SampleTime::default(); - self.align = Align::default(); - cfg - } +impl Adc { + /// Init a new Adc + /// + /// Sets all configurable parameters to one-shot defaults, + /// performs a boot-time calibration. + pub fn new(adc: ADC, clocks: &Clocks) -> Self { + let mut s = Self { + rb: adc, + sample_time: SampleTime::default(), + align: Align::default(), + sysclk: clocks.sysclk(), + adcclk: clocks.adcclk(), + }; + s.enable_clock(); + s.power_down(); + s.reset(); + s.setup_oneshot(); + s.power_up(); + + // The manual states that we need to wait two ADC clocks cycles after power-up + // before starting calibration, we already delayed in the power-up process, but + // if the adc clock is too low that was not enough. + if s.adcclk < kHz(2500) { + let two_adc_cycles = s.sysclk / s.adcclk * 2; + let already_delayed = s.sysclk / kHz(800); + if two_adc_cycles > already_delayed { + delay(two_adc_cycles - already_delayed); + } + } + s.calibrate(); + s + } - /// Set ADC sampling time - /// - /// Options can be found in [SampleTime]. - pub fn set_sample_time(&mut self, t_samp: SampleTime) { - self.sample_time = t_samp; - } + /// Save current ADC config + pub fn save_cfg(&mut self) -> StoredConfig { + StoredConfig(self.sample_time, self.align) + } - /// Set the Adc result alignment - /// - /// Options can be found in [Align]. - pub fn set_align(&mut self, align: Align) { - self.align = align; - } + /// Restore saved ADC config + pub fn restore_cfg(&mut self, cfg: StoredConfig) { + self.sample_time = cfg.0; + self.align = cfg.1; + } - /// Returns the largest possible sample value for the current settings - pub fn max_sample(&self) -> u16 { - match self.align { - Align::Left => u16::MAX, - Align::Right => (1 << 12) - 1, - } - } + /// Reset the ADC config to default, return existing config + pub fn default_cfg(&mut self) -> StoredConfig { + let cfg = self.save_cfg(); + self.sample_time = SampleTime::default(); + self.align = Align::default(); + cfg + } - #[inline(always)] - pub fn set_external_trigger(&mut self, trigger: crate::pac::$adc::cr2::EXTSEL) { - self.rb.cr2().modify(|_, w| w.extsel().variant(trigger)); - } + /// Set ADC sampling time + /// + /// Options can be found in [SampleTime]. + pub fn set_sample_time(&mut self, t_samp: SampleTime) { + self.sample_time = t_samp; + } - fn power_up(&mut self) { - self.rb.cr2().modify(|_, w| w.adon().set_bit()); + /// Set the Adc result alignment + /// + /// Options can be found in [Align]. + pub fn set_align(&mut self, align: Align) { + self.align = align; + } - // The reference manual says that a stabilization time is needed after power_up, - // this time can be found in the datasheets. - // Here we are delaying for approximately 1us, considering 1.25 instructions per - // cycle. Do we support a chip which needs more than 1us ? - delay(self.sysclk / kHz(800)); - } + /// Returns the largest possible sample value for the current settings + pub fn max_sample(&self) -> u16 { + match self.align { + Align::Left => u16::MAX, + Align::Right => (1 << 12) - 1, + } + } - fn power_down(&mut self) { - self.rb.cr2().modify(|_, w| w.adon().clear_bit()); - } + #[inline(always)] + pub fn set_external_trigger(&mut self, trigger: ADC::ExtSel) { + self.rb.set_extsel(trigger); + } - fn reset(&mut self) { - let rcc = unsafe { &(*RCC::ptr()) }; - <$ADC>::reset(rcc); - } + fn power_up(&mut self) { + self.rb.cr2().modify(|_, w| w.adon().set_bit()); - fn enable_clock(&mut self) { - let rcc = unsafe { &(*RCC::ptr()) }; - <$ADC>::enable(rcc); - } + // The reference manual says that a stabilization time is needed after power_up, + // this time can be found in the datasheets. + // Here we are delaying for approximately 1us, considering 1.25 instructions per + // cycle. Do we support a chip which needs more than 1us ? + delay(self.sysclk / kHz(800)); + } - fn disable_clock(&mut self) { - let rcc = unsafe { &(*RCC::ptr()) }; - <$ADC>::disable(rcc); - } + fn power_down(&mut self) { + self.rb.cr2().modify(|_, w| w.adon().clear_bit()); + } - fn calibrate(&mut self) { - /* reset calibration */ - self.rb.cr2().modify(|_, w| w.rstcal().set_bit()); - while self.rb.cr2().read().rstcal().bit_is_set() {} + fn reset(&mut self) { + let rcc = unsafe { &(*RCC::ptr()) }; + ADC::reset(rcc); + } - /* calibrate */ - self.rb.cr2().modify(|_, w| w.cal().set_bit()); - while self.rb.cr2().read().cal().bit_is_set() {} - } + fn enable_clock(&mut self) { + let rcc = unsafe { &(*RCC::ptr()) }; + ADC::enable(rcc); + } - fn setup_oneshot(&mut self) { - self.rb.cr2().modify(|_, w| w - .cont().clear_bit() - .exttrig().set_bit() - .extsel().swstart() - ); + fn disable_clock(&mut self) { + let rcc = unsafe { &(*RCC::ptr()) }; + ADC::disable(rcc); + } - self.rb.cr1().modify(|_, w| w - .scan().clear_bit() - .discen().set_bit() - ); + fn calibrate(&mut self) { + /* reset calibration */ + self.rb.cr2().modify(|_, w| w.rstcal().set_bit()); + while self.rb.cr2().read().rstcal().bit_is_set() {} - self.rb.sqr1().modify(|_, w| w.l().set(0b0)); - } + /* calibrate */ + self.rb.cr2().modify(|_, w| w.cal().set_bit()); + while self.rb.cr2().read().cal().bit_is_set() {} + } - fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime) { - let sample_time = sample_time.into(); - match chan { - 0 => self.rb.smpr2().modify(|_, w| w.smp0().set(sample_time)), - 1 => self.rb.smpr2().modify(|_, w| w.smp1().set(sample_time)), - 2 => self.rb.smpr2().modify(|_, w| w.smp2().set(sample_time)), - 3 => self.rb.smpr2().modify(|_, w| w.smp3().set(sample_time)), - 4 => self.rb.smpr2().modify(|_, w| w.smp4().set(sample_time)), - 5 => self.rb.smpr2().modify(|_, w| w.smp5().set(sample_time)), - 6 => self.rb.smpr2().modify(|_, w| w.smp6().set(sample_time)), - 7 => self.rb.smpr2().modify(|_, w| w.smp7().set(sample_time)), - 8 => self.rb.smpr2().modify(|_, w| w.smp8().set(sample_time)), - 9 => self.rb.smpr2().modify(|_, w| w.smp9().set(sample_time)), - - 10 => self.rb.smpr1().modify(|_, w| w.smp10().set(sample_time)), - 11 => self.rb.smpr1().modify(|_, w| w.smp11().set(sample_time)), - 12 => self.rb.smpr1().modify(|_, w| w.smp12().set(sample_time)), - 13 => self.rb.smpr1().modify(|_, w| w.smp13().set(sample_time)), - 14 => self.rb.smpr1().modify(|_, w| w.smp14().set(sample_time)), - 15 => self.rb.smpr1().modify(|_, w| w.smp15().set(sample_time)), - 16 => self.rb.smpr1().modify(|_, w| w.smp16().set(sample_time)), - 17 => self.rb.smpr1().modify(|_, w| w.smp17().set(sample_time)), - _ => unreachable!(), - }; - } + fn setup_oneshot(&mut self) { + self.rb.cr2().modify(|_, w| { + w.cont().clear_bit(); + w.exttrig().set_bit(); + w.select_swstart() + }); + + self.rb + .cr1() + .modify(|_, w| w.scan().clear_bit().discen().set_bit()); - fn set_regular_sequence (&mut self, channels: &[u8]) { - let len = channels.len(); - let bits = channels.iter().take(6).enumerate().fold(0u32, |s, (i, c)| - s | ((*c as u32) << (i * 5)) - ); - self.rb.sqr3().write(|w| unsafe { w - .bits( bits ) - }); - if len > 6 { - let bits = channels.iter().skip(6).take(6).enumerate().fold(0u32, |s, (i, c)| - s | ((*c as u32) << (i * 5)) - ); - self.rb.sqr2().write(|w| unsafe { w - .bits( bits ) - }); + self.rb.sqr1().modify(|_, w| w.l().set(0b0)); + } + + fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime) { + let sample_time = sample_time.into(); + match chan { + 0..=9 => self + .rb + .smpr2() + .modify(|_, w| w.smp(chan).variant(sample_time)), + 10..=17 => self + .rb + .smpr1() + .modify(|_, w| w.smp(chan - 10).variant(sample_time)), + _ => unreachable!(), + }; + } + + fn set_regular_sequence(&mut self, channels: &[u8]) { + let mut iter = channels.chunks(6); + unsafe { + if let Some(chunk) = iter.next() { + self.rb.sqr3().write(|w| { + for (i, &c) in chunk.iter().enumerate() { + w.sq(i as u8).bits(c); } - if len > 12 { - let bits = channels.iter().skip(12).take(4).enumerate().fold(0u32, |s, (i, c)| - s | ((*c as u32) << (i * 5)) - ); - self.rb.sqr1().write(|w| unsafe { w - .bits( bits ) - }); + w + }); + } + if let Some(chunk) = iter.next() { + self.rb.sqr2().write(|w| { + for (i, &c) in chunk.iter().enumerate() { + w.sq(i as u8).bits(c); + } + w + }); + } + self.rb.sqr1().write(|w| { + if let Some(chunk) = iter.next() { + for (i, &c) in chunk.iter().enumerate() { + w.sq(i as u8).bits(c); } - self.rb.sqr1().modify(|_, w| w.l().set((len-1) as u8)); } + w.l().set((channels.len() - 1) as u8) + }); + } + } - fn set_continuous_mode(&mut self, continuous: bool) { - self.rb.cr2().modify(|_, w| w.cont().bit(continuous)); - } + fn set_continuous_mode(&mut self, continuous: bool) { + self.rb.cr2().modify(|_, w| w.cont().bit(continuous)); + } - fn set_discontinuous_mode(&mut self, channels_count: Option) { - self.rb.cr1().modify(|_, w| match channels_count { - Some(count) => w.discen().set_bit().discnum().set(count), - None => w.discen().clear_bit(), - }); - } + fn set_discontinuous_mode(&mut self, channels_count: Option) { + self.rb.cr1().modify(|_, w| match channels_count { + Some(count) => w.discen().set_bit().discnum().set(count), + None => w.discen().clear_bit(), + }); + } - /** - Performs an ADC conversion - - NOTE: Conversions can be started by writing a 1 to the ADON - bit in the `CR2` while it is already 1, and no other bits - are being written in the same operation. This means that - the EOC bit *might* be set already when entering this function - which can cause a read of stale values - - The check for `cr2.swstart.bit_is_set` *should* fix it, but - does not. Therefore, ensure you do not do any no-op modifications - to `cr2` just before calling this function - */ - fn convert(&mut self, chan: u8) -> u16 { - // Dummy read in case something accidentally triggered - // a conversion by writing to CR2 without changing any - // of the bits - self.rb.dr().read().data().bits(); - - self.set_channel_sample_time(chan, self.sample_time); - self.rb.sqr3().modify(|_, w| unsafe { w.sq1().bits(chan) }); - - // ADC start conversion of regular sequence - self.rb.cr2().modify(|_, w| { - w.swstart().set_bit(); - w.align().bit(self.align.into()) - }); - while self.rb.cr2().read().swstart().bit_is_set() {} - // ADC wait for conversion results - while self.rb.sr().read().eoc().bit_is_clear() {} - - let res = self.rb.dr().read().data().bits(); - res - } + /** + Performs an ADC conversion + + NOTE: Conversions can be started by writing a 1 to the ADON + bit in the `CR2` while it is already 1, and no other bits + are being written in the same operation. This means that + the EOC bit *might* be set already when entering this function + which can cause a read of stale values + + The check for `cr2.swstart.bit_is_set` *should* fix it, but + does not. Therefore, ensure you do not do any no-op modifications + to `cr2` just before calling this function + */ + fn convert(&mut self, chan: u8) -> u16 { + // Dummy read in case something accidentally triggered + // a conversion by writing to CR2 without changing any + // of the bits + self.rb.dr().read().data().bits(); + + self.set_channel_sample_time(chan, self.sample_time); + self.rb.sqr3().modify(|_, w| unsafe { w.sq1().bits(chan) }); + + // ADC start conversion of regular sequence + self.rb.cr2().modify(|_, w| { + w.swstart().set_bit(); + w.align().variant(self.align.into()) + }); + while self.rb.cr2().read().swstart().bit_is_set() {} + // ADC wait for conversion results + while self.rb.sr().read().eoc().bit_is_clear() {} + + let res = self.rb.dr().read().data().bits(); + res + } - /// Powers down the ADC, disables the ADC clock and releases the ADC Peripheral - pub fn release(mut self) -> $ADC { - self.power_down(); - self.disable_clock(); - self.rb - } + /// Powers down the ADC, disables the ADC clock and releases the ADC Peripheral + pub fn release(mut self) -> ADC { + self.power_down(); + self.disable_clock(); + self.rb + } - /// Enable interrupt for EOC (end of convert) - pub fn enable_eoc_interrupt(&mut self) { - self.rb.cr1().write(|w| w.eocie().set_bit()); - } + /// Enable interrupt for EOC (end of convert) + pub fn enable_eoc_interrupt(&mut self) { + self.rb.cr1().write(|w| w.eocie().set_bit()); + } - /// Disable interrupt for EOC (end of convert) - pub fn disable_eoc_interrupt(&mut self) { - self.rb.cr1().write(|w| w.eocie().clear_bit()); - } + /// Disable interrupt for EOC (end of convert) + pub fn disable_eoc_interrupt(&mut self) { + self.rb.cr1().write(|w| w.eocie().clear_bit()); + } - /// Enable interrupt for JEOC (EOC for injected channels) - pub fn enable_jeoc_interrupt(&mut self) { - self.rb.cr1().write(|w| w.jeocie().set_bit()); - } + /// Enable interrupt for JEOC (EOC for injected channels) + pub fn enable_jeoc_interrupt(&mut self) { + self.rb.cr1().write(|w| w.jeocie().set_bit()); + } - /// Disable interrupt for JEOC (EOC for injected channels) - pub fn disable_jeoc_interrupt(&mut self) { - self.rb.cr1().write(|w| w.jeocie().clear_bit()); - } - } + /// Disable interrupt for JEOC (EOC for injected channels) + pub fn disable_jeoc_interrupt(&mut self) { + self.rb.cr1().write(|w| w.jeocie().clear_bit()); + } +} - impl ChannelTimeSequence for Adc<$ADC> { - #[inline(always)] - fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime) { - self.set_channel_sample_time(chan, sample_time); - } - #[inline(always)] - fn set_regular_sequence (&mut self, channels: &[u8]) { - self.set_regular_sequence(channels); - } - #[inline(always)] - fn set_continuous_mode(&mut self, continuous: bool) { - self.set_continuous_mode(continuous); - } - #[inline(always)] - fn set_discontinuous_mode(&mut self, channels: Option) { - self.set_discontinuous_mode(channels); - } - } +impl ChannelTimeSequence for Adc { + #[inline(always)] + fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime) { + self.set_channel_sample_time(chan, sample_time); + } + #[inline(always)] + fn set_regular_sequence(&mut self, channels: &[u8]) { + self.set_regular_sequence(channels); + } + #[inline(always)] + fn set_continuous_mode(&mut self, continuous: bool) { + self.set_continuous_mode(continuous); + } + #[inline(always)] + fn set_discontinuous_mode(&mut self, channels: Option) { + self.set_discontinuous_mode(channels); + } +} - impl OneShot<$ADC, WORD, PIN> for Adc<$ADC> - where - WORD: From, - PIN: Channel<$ADC, ID = u8>, - { - type Error = (); - - fn read(&mut self, _pin: &mut PIN) -> nb::Result { - let res = self.convert(PIN::channel()); - Ok(res.into()) - } - } +impl OneShot for Adc +where + WORD: From, + PIN: Channel, +{ + type Error = (); - )+ + fn read(&mut self, _pin: &mut PIN) -> nb::Result { + let res = self.convert(PIN::channel()); + Ok(res.into()) } } @@ -559,20 +581,6 @@ impl Adc { } } -adc_hal! { - pac::ADC1: (adc1), -} - -#[cfg(any(feature = "stm32f103", feature = "connectivity"))] -adc_hal! { - pac::ADC2: (adc2), -} - -#[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl")))] -adc_hal! { - pac::ADC3: (adc3), -} - pub struct AdcPayload { adc: Adc, pins: PINS, @@ -672,7 +680,7 @@ macro_rules! adcdma { self.rb.cr1().modify(|_, w| w.discen().clear_bit()); self.rb .cr2() - .modify(|_, w| w.align().bit(self.align.into())); + .modify(|_, w| w.align().variant(self.align.into())); self.set_channel_sample_time(PIN::channel(), self.sample_time); self.rb .sqr3() @@ -702,7 +710,7 @@ macro_rules! adcdma { w.adon().clear_bit(); w.dma().clear_bit(); w.cont().clear_bit(); - w.align().bit(self.align.into()) + w.align().variant(self.align.into()) }); self.rb .cr1() diff --git a/src/dma.rs b/src/dma.rs index bd73630d..4e7b6662 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -51,12 +51,10 @@ where } } -pub trait DmaExt { +pub trait DmaExt: crate::Ptr { type Channels; fn split(self) -> Self::Channels; - - fn ptr() -> *const pac::dma1::RegisterBlock; } pub trait TransferPayload { @@ -463,10 +461,6 @@ macro_rules! dma { Channels((), $(super::Ch::<$DMAX, $ch>(super::PhantomData)),+) } - - fn ptr() -> *const crate::pac::dma1::RegisterBlock { - Self::ptr() - } } } } diff --git a/src/lib.rs b/src/lib.rs index 6c1ccc57..c062a6ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,6 +113,8 @@ compile_error!( "Multiple targets specified. Only a single `--features ` can be specified." ); +pub mod pacext; + pub use embedded_hal as hal; pub use embedded_hal_02 as hal_02; @@ -159,16 +161,41 @@ mod sealed { use sealed::Sealed; use stm32f1::Periph; -pub trait Ptr { +impl Sealed for Periph {} + +pub trait Ptr: Sealed { /// RegisterBlock structure type RB; /// Return the pointer to the register block fn ptr() -> *const Self::RB; } -impl Ptr for Periph { +impl Ptr for Periph { type RB = RB; fn ptr() -> *const Self::RB { Self::ptr() } } + +pub trait Steal: Sealed { + /// Steal an instance of this peripheral + /// + /// # Safety + /// + /// Ensure that the new instance of the peripheral cannot be used in a way + /// that may race with any existing instances, for example by only + /// accessing read-only or write-only registers, or by consuming the + /// original peripheral and using critical sections to coordinate + /// access between multiple new instances. + /// + /// Additionally the HAL may rely on only one + /// peripheral instance existing to ensure memory safety; ensure + /// no stolen instances are passed to such software. + unsafe fn steal() -> Self; +} + +impl Steal for Periph { + unsafe fn steal() -> Self { + Self::steal() + } +} diff --git a/src/pacext.rs b/src/pacext.rs new file mode 100644 index 00000000..8240206e --- /dev/null +++ b/src/pacext.rs @@ -0,0 +1,79 @@ +use stm32f1::{Readable, Reg, RegisterSpec, Resettable, Writable, R, W}; + +pub mod adc; +pub mod uart; + +macro_rules! wrap_r { + (pub trait $TrR:ident { + $(fn $f:ident(&self $(, $n:ident: u8)?) -> $fr:path;)* + }) => { + pub trait $TrR { + $(fn $f(&self $(, $n: u8)?) -> $fr;)* + } + impl $TrR for R { + $( + #[inline(always)] + fn $f(&self $(, $n: u8)?) -> $fr { + REG::$f(self $(, $n)?) + } + )* + } + }; +} +pub(crate) use wrap_r; + +macro_rules! wrap_w { + (pub trait $TrR:ident { + $(fn $f:ident(&mut self $(, $n:ident: u8)?) -> $fr:path;)* + }) => { + pub trait $TrR { + $(fn $f(&mut self $(, $n: u8)?) -> $fr;)* + } + + impl $TrR for W { + $( + #[inline(always)] + fn $f(&mut self $(, $n: u8)?) -> $fr { + REG::$f(self $(, $n)?) + } + )* + } + }; +} +pub(crate) use wrap_w; + +macro_rules! impl_reg { + ($($r:ident $(: $n:ident)? -> &$rty:path;)*) => { + $( + #[inline(always)] + fn $r(&self $(, $n: usize)?) -> &$rty { + self.$r($($n)?) + } + )* + }; +} +pub(crate) use impl_reg; + +macro_rules! impl_read { + ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { + $( + #[inline(always)] + fn $f(r: &R $(, $n: u8)?) -> $fty { + r.$f($($n)?) + } + )* + }; +} +pub(crate) use impl_read; + +macro_rules! impl_write { + ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { + $( + #[inline(always)] + fn $f(w: &mut W $(, $n: u8)?) -> $fty { + w.$f($($n)?) + } + )* + }; +} +pub(crate) use impl_write; diff --git a/src/pacext/adc.rs b/src/pacext/adc.rs new file mode 100644 index 00000000..c380fce2 --- /dev/null +++ b/src/pacext/adc.rs @@ -0,0 +1,317 @@ +use crate::Sealed; + +use super::*; +use crate::pac::adc1; +#[cfg(not(feature = "stm32f100"))] +use crate::pac::adc2; +#[cfg(not(feature = "stm32f100"))] +use crate::pac::adc3; + +pub trait AdcRB: Sealed { + fn sr(&self) -> &adc1::SR; + type CR1rs: reg::Cr1R + reg::Cr1W; + fn cr1(&self) -> &Reg; + type CR2rs: reg::Cr2R + reg::Cr2W; + fn cr2(&self) -> &Reg; + fn htr(&self) -> &adc1::HTR; + fn jdr(&self, n: usize) -> &adc1::JDR; + fn jdr1(&self) -> &adc1::JDR { + self.jdr(0) + } + fn jdr2(&self) -> &adc1::JDR { + self.jdr(1) + } + fn jdr3(&self) -> &adc1::JDR { + self.jdr(2) + } + fn jdr4(&self) -> &adc1::JDR { + self.jdr(3) + } + fn jofr(&self, n: usize) -> &adc1::JOFR; + fn jofr1(&self) -> &adc1::JOFR { + self.jofr(0) + } + fn jofr2(&self) -> &adc1::JOFR { + self.jofr(1) + } + fn jofr3(&self) -> &adc1::JOFR { + self.jofr(2) + } + fn jofr4(&self) -> &adc1::JOFR { + self.jofr(3) + } + fn jsqr(&self) -> &adc1::JSQR; + fn ltr(&self) -> &adc1::LTR; + fn smpr1(&self) -> &adc1::SMPR1; + fn smpr2(&self) -> &adc1::SMPR2; + fn sqr1(&self) -> &adc1::SQR1; + fn sqr2(&self) -> &adc1::SQR2; + fn sqr3(&self) -> &adc1::SQR3; + type DRrs: reg::Dr; + fn dr(&self) -> &Reg; +} + +wrap_r! { + pub trait Cr1R { + fn awdch(&self) -> adc1::cr1::AWDCH_R; + fn eocie(&self) -> adc1::cr1::EOCIE_R; + fn awdie(&self) -> adc1::cr1::AWDIE_R; + fn jeocie(&self) -> adc1::cr1::JEOCIE_R; + fn scan(&self) -> adc1::cr1::SCAN_R; + fn awdsgl(&self) -> adc1::cr1::AWDSGL_R; + fn jauto(&self) -> adc1::cr1::JAUTO_R; + fn discen(&self) -> adc1::cr1::DISCEN_R; + fn jdiscen(&self) -> adc1::cr1::JDISCEN_R; + fn discnum(&self) -> adc1::cr1::DISCNUM_R; + fn jawden(&self) -> adc1::cr1::JAWDEN_R; + fn awden(&self) -> adc1::cr1::AWDEN_R; + } +} + +wrap_w! { + pub trait Cr1W { + fn awdch(&mut self) -> adc1::cr1::AWDCH_W; + fn eocie(&mut self) -> adc1::cr1::EOCIE_W; + fn awdie(&mut self) -> adc1::cr1::AWDIE_W; + fn jeocie(&mut self) -> adc1::cr1::JEOCIE_W; + fn scan(&mut self) -> adc1::cr1::SCAN_W; + fn awdsgl(&mut self) -> adc1::cr1::AWDSGL_W; + fn jauto(&mut self) -> adc1::cr1::JAUTO_W; + fn discen(&mut self) -> adc1::cr1::DISCEN_W; + fn jdiscen(&mut self) -> adc1::cr1::JDISCEN_W; + fn discnum(&mut self) -> adc1::cr1::DISCNUM_W; + fn jawden(&mut self) -> adc1::cr1::JAWDEN_W; + fn awden(&mut self) -> adc1::cr1::AWDEN_W; + } +} + +wrap_r! { + pub trait Cr2R { + fn adon(&self) -> adc1::cr2::ADON_R; + fn cont(&self) -> adc1::cr2::CONT_R; + fn cal(&self) -> adc1::cr2::CAL_R; + fn rstcal(&self) -> adc1::cr2::RSTCAL_R; + fn dma(&self) -> adc1::cr2::DMA_R; + fn align(&self) -> adc1::cr2::ALIGN_R; + fn jexttrig(&self) -> adc1::cr2::JEXTTRIG_R; + fn exttrig(&self) -> adc1::cr2::EXTTRIG_R; + fn jswstart(&self) -> adc1::cr2::JSWSTART_R; + fn swstart(&self) -> adc1::cr2::SWSTART_R; + fn tsvrefe(&self) -> adc1::cr2::TSVREFE_R; + } +} + +wrap_w! { + pub trait Cr2W { + fn adon(&mut self) -> adc1::cr2::ADON_W; + fn cont(&mut self) -> adc1::cr2::CONT_W; + fn cal(&mut self) -> adc1::cr2::CAL_W; + fn rstcal(&mut self) -> adc1::cr2::RSTCAL_W; + fn dma(&mut self) -> adc1::cr2::DMA_W; + fn align(&mut self) -> adc1::cr2::ALIGN_W; + fn jexttrig(&mut self) -> adc1::cr2::JEXTTRIG_W; + fn exttrig(&mut self) -> adc1::cr2::EXTTRIG_W; + fn jswstart(&mut self) -> adc1::cr2::JSWSTART_W; + fn swstart(&mut self) -> adc1::cr2::SWSTART_W; + fn tsvrefe(&mut self) -> adc1::cr2::TSVREFE_W; + } +} + +pub trait ExtSelW { + fn select_swstart(&mut self) -> &mut Self; +} + +impl ExtSelW for W { + fn select_swstart(&mut self) -> &mut Self { + REG::select_swstart(self) + } +} + +wrap_r! { + pub trait Dr { + fn data(&self) -> adc1::dr::DATA_R; + } +} + +mod reg { + use super::*; + + pub trait Cr1R: RegisterSpec + Readable + Sized { + fn awdch(r: &R) -> adc1::cr1::AWDCH_R; + fn eocie(r: &R) -> adc1::cr1::EOCIE_R; + fn awdie(r: &R) -> adc1::cr1::AWDIE_R; + fn jeocie(r: &R) -> adc1::cr1::JEOCIE_R; + fn scan(r: &R) -> adc1::cr1::SCAN_R; + fn awdsgl(r: &R) -> adc1::cr1::AWDSGL_R; + fn jauto(r: &R) -> adc1::cr1::JAUTO_R; + fn discen(r: &R) -> adc1::cr1::DISCEN_R; + fn jdiscen(r: &R) -> adc1::cr1::JDISCEN_R; + fn discnum(r: &R) -> adc1::cr1::DISCNUM_R; + fn jawden(r: &R) -> adc1::cr1::JAWDEN_R; + fn awden(r: &R) -> adc1::cr1::AWDEN_R; + } + + pub trait Cr1W: RegisterSpec + Writable + Resettable + Sized { + fn awdch(w: &mut W) -> adc1::cr1::AWDCH_W; + fn eocie(w: &mut W) -> adc1::cr1::EOCIE_W; + fn awdie(w: &mut W) -> adc1::cr1::AWDIE_W; + fn jeocie(w: &mut W) -> adc1::cr1::JEOCIE_W; + fn scan(w: &mut W) -> adc1::cr1::SCAN_W; + fn awdsgl(w: &mut W) -> adc1::cr1::AWDSGL_W; + fn jauto(w: &mut W) -> adc1::cr1::JAUTO_W; + fn discen(w: &mut W) -> adc1::cr1::DISCEN_W; + fn jdiscen(w: &mut W) -> adc1::cr1::JDISCEN_W; + fn discnum(w: &mut W) -> adc1::cr1::DISCNUM_W; + fn jawden(w: &mut W) -> adc1::cr1::JAWDEN_W; + fn awden(w: &mut W) -> adc1::cr1::AWDEN_W; + } + + pub trait Cr2R: RegisterSpec + Readable + Sized { + fn adon(r: &R) -> adc1::cr2::ADON_R; + fn cont(r: &R) -> adc1::cr2::CONT_R; + fn cal(r: &R) -> adc1::cr2::CAL_R; + fn rstcal(r: &R) -> adc1::cr2::RSTCAL_R; + fn dma(r: &R) -> adc1::cr2::DMA_R; + fn align(r: &R) -> adc1::cr2::ALIGN_R; + fn jexttrig(r: &R) -> adc1::cr2::JEXTTRIG_R; + fn exttrig(r: &R) -> adc1::cr2::EXTTRIG_R; + fn jswstart(r: &R) -> adc1::cr2::JSWSTART_R; + fn swstart(r: &R) -> adc1::cr2::SWSTART_R; + fn tsvrefe(r: &R) -> adc1::cr2::TSVREFE_R; + } + pub trait Cr2W: RegisterSpec + Writable + Resettable + Sized + ExtSelW { + fn adon(w: &mut W) -> adc1::cr2::ADON_W; + fn cont(w: &mut W) -> adc1::cr2::CONT_W; + fn cal(w: &mut W) -> adc1::cr2::CAL_W; + fn rstcal(w: &mut W) -> adc1::cr2::RSTCAL_W; + fn dma(w: &mut W) -> adc1::cr2::DMA_W; + fn align(w: &mut W) -> adc1::cr2::ALIGN_W; + fn jexttrig(w: &mut W) -> adc1::cr2::JEXTTRIG_W; + fn exttrig(w: &mut W) -> adc1::cr2::EXTTRIG_W; + fn jswstart(w: &mut W) -> adc1::cr2::JSWSTART_W; + fn swstart(w: &mut W) -> adc1::cr2::SWSTART_W; + fn tsvrefe(w: &mut W) -> adc1::cr2::TSVREFE_W; + } + pub trait Dr: RegisterSpec + Readable + Sized { + fn data(r: &R) -> adc1::dr::DATA_R; + } + + pub trait ExtSelW: RegisterSpec + Sized { + fn select_swstart(w: &mut W) -> &mut W; + } +} + +macro_rules! impl_ext { + ($adc:ident) => { + impl Sealed for $adc::RegisterBlock {} + impl AdcRB for $adc::RegisterBlock { + type CR1rs = $adc::cr1::CR1rs; + type CR2rs = $adc::cr2::CR2rs; + type DRrs = $adc::dr::DRrs; + impl_reg! { + sr -> &adc1::SR; + cr1 -> &Reg; + cr2 -> &Reg; + htr -> &adc1::HTR; + jdr: n -> &adc1::JDR; + jofr: n -> &adc1::JOFR; + jsqr -> &adc1::JSQR; + ltr -> &adc1::LTR; + smpr1 -> &adc1::SMPR1; + smpr2 -> &adc1::SMPR2; + sqr1 -> &adc1::SQR1; + sqr2 -> &adc1::SQR2; + sqr3 -> &adc1::SQR3; + dr -> &Reg; + } + } + + impl reg::Cr1R for $adc::cr1::CR1rs { + impl_read! { + awdch -> adc1::cr1::AWDCH_R; + eocie -> adc1::cr1::EOCIE_R; + awdie -> adc1::cr1::AWDIE_R; + jeocie -> adc1::cr1::JEOCIE_R; + scan -> adc1::cr1::SCAN_R; + awdsgl -> adc1::cr1::AWDSGL_R; + jauto -> adc1::cr1::JAUTO_R; + discen -> adc1::cr1::DISCEN_R; + jdiscen -> adc1::cr1::JDISCEN_R; + discnum -> adc1::cr1::DISCNUM_R; + jawden -> adc1::cr1::JAWDEN_R; + awden -> adc1::cr1::AWDEN_R; + } + } + impl reg::Cr1W for $adc::cr1::CR1rs { + impl_write! { + awdch -> adc1::cr1::AWDCH_W; + eocie -> adc1::cr1::EOCIE_W; + awdie -> adc1::cr1::AWDIE_W; + jeocie -> adc1::cr1::JEOCIE_W; + scan -> adc1::cr1::SCAN_W; + awdsgl -> adc1::cr1::AWDSGL_W; + jauto -> adc1::cr1::JAUTO_W; + discen -> adc1::cr1::DISCEN_W; + jdiscen -> adc1::cr1::JDISCEN_W; + discnum -> adc1::cr1::DISCNUM_W; + jawden -> adc1::cr1::JAWDEN_W; + awden -> adc1::cr1::AWDEN_W; + } + } + impl reg::Dr for $adc::dr::DRrs { + impl_read! { + data -> adc1::dr::DATA_R; + } + } + }; +} + +macro_rules! impl_cr2 { + ($adc:ident) => { + impl reg::Cr2R for $adc::cr2::CR2rs { + impl_read! { + adon -> adc1::cr2::ADON_R; + cont -> adc1::cr2::CONT_R; + cal -> adc1::cr2::CAL_R; + rstcal -> adc1::cr2::RSTCAL_R; + dma -> adc1::cr2::DMA_R; + align -> adc1::cr2::ALIGN_R; + jexttrig -> adc1::cr2::JEXTTRIG_R; + exttrig -> adc1::cr2::EXTTRIG_R; + jswstart -> adc1::cr2::JSWSTART_R; + swstart -> adc1::cr2::SWSTART_R; + tsvrefe -> adc1::cr2::TSVREFE_R; + } + } + impl reg::Cr2W for $adc::cr2::CR2rs { + impl_write! { + adon -> adc1::cr2::ADON_W; + cont -> adc1::cr2::CONT_W; + cal -> adc1::cr2::CAL_W; + rstcal -> adc1::cr2::RSTCAL_W; + dma -> adc1::cr2::DMA_W; + align -> adc1::cr2::ALIGN_W; + jexttrig -> adc1::cr2::JEXTTRIG_W; + exttrig -> adc1::cr2::EXTTRIG_W; + jswstart -> adc1::cr2::JSWSTART_W; + swstart -> adc1::cr2::SWSTART_W; + tsvrefe -> adc1::cr2::TSVREFE_W; + } + } + impl reg::ExtSelW for $adc::cr2::CR2rs { + fn select_swstart(w: &mut W) -> &mut W { + w.extsel().swstart() + } + } + }; +} + +impl_ext!(adc1); +impl_cr2!(adc1); + +#[cfg(not(feature = "stm32f100"))] +impl_ext!(adc2); +#[cfg(not(feature = "stm32f100"))] +impl_ext!(adc3); +#[cfg(not(feature = "stm32f100"))] +impl_cr2!(adc3); diff --git a/src/serial/ext.rs b/src/pacext/uart.rs similarity index 82% rename from src/serial/ext.rs rename to src/pacext/uart.rs index c8d3829c..aabd18c5 100644 --- a/src/serial/ext.rs +++ b/src/pacext/uart.rs @@ -2,11 +2,11 @@ use crate::{sealed, Sealed}; +use super::*; use crate::pac::uart4; use crate::pac::usart1; -use stm32f1::{Readable, Reg, RegisterSpec, Resettable, Writable, R, W}; -pub trait UartExt: Sealed { +pub trait UartRB: Sealed { fn cr1(&self) -> &usart1::CR1; fn dr(&self) -> &usart1::DR; fn brr(&self) -> &usart1::BRR; @@ -20,43 +20,6 @@ pub trait UartExt: Sealed { fn gtpr(&self) -> &Reg; } -macro_rules! wrap_r { - (pub trait $TrR:ident { - $(fn $f:ident(&self $(, $n:ident: u8)?) -> $fr:path;)* - }) => { - pub trait $TrR { - $(fn $f(&self $(, $n: u8)?) -> $fr;)* - } - impl $TrR for R { - $( - #[inline(always)] - fn $f(&self $(, $n: u8)?) -> $fr { - REG::$f(self $(, $n)?) - } - )* - } - }; -} - -macro_rules! wrap_w { - (pub trait $TrR:ident { - $(fn $f:ident(&mut self $(, $n:ident: u8)?) -> $fr:path;)* - }) => { - pub trait $TrR { - $(fn $f(&mut self $(, $n: u8)?) -> $fr;)* - } - - impl $TrR for W { - $( - #[inline(always)] - fn $f(&mut self $(, $n: u8)?) -> $fr { - REG::$f(self $(, $n)?) - } - )* - } - }; -} - wrap_r! { pub trait SrR { fn pe(&self) -> usart1::sr::PE_R; @@ -185,42 +148,10 @@ mod reg { } } -macro_rules! impl_reg { - ($($r:ident -> &$rty:path;)*) => { - $( - #[inline(always)] - fn $r(&self) -> &$rty { - self.$r() - } - )* - }; -} - -macro_rules! impl_read { - ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { - $( - #[inline(always)] - fn $f(r: &R $(, $n: u8)?) -> $fty { - r.$f($($n)?) - } - )* - }; -} -macro_rules! impl_write { - ($($f:ident $(: $n:ident)? -> $fty:path;)*) => { - $( - #[inline(always)] - fn $f(w: &mut W $(, $n: u8)?) -> $fty { - w.$f($($n)?) - } - )* - }; -} - macro_rules! impl_ext { ($(#[$attr:meta])* $uart:ident) => { impl Sealed for $uart::RegisterBlock {} - impl UartExt for $uart::RegisterBlock { + impl UartRB for $uart::RegisterBlock { type SRrs = $uart::sr::SRrs; type CR2rs = $uart::cr2::CR2rs; type CR3rs = $uart::cr3::CR3rs; diff --git a/src/prelude.rs b/src/prelude.rs index 65c7f48e..dcdb3c1c 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,4 @@ +pub use crate::adc::AdcExt as _; pub use crate::adc::ChannelTimeSequence as _stm32_hal_adc_ChannelTimeSequence; pub use crate::afio::AfioExt as _stm32_hal_afio_AfioExt; pub use crate::afio::RFrom as _; diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index cf5670e3..3f055748 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -4,8 +4,6 @@ use crate::bb; macro_rules! bus { ($($PER:ident => ($apbX:ty, $bit:literal),)+) => { $( - impl crate::Sealed for crate::pac::$PER {} - impl RccBus for crate::pac::$PER { type Bus = $apbX; } @@ -39,8 +37,6 @@ macro_rules! bus { macro_rules! ahb_bus { ($($PER:ident => ($bit:literal),)+) => { $( - impl crate::Sealed for crate::pac::$PER {} - impl RccBus for crate::pac::$PER { type Bus = AHB; } diff --git a/src/serial.rs b/src/serial.rs index 2ac2f214..e67f16cb 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -104,11 +104,10 @@ use crate::pac::{self, RCC}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::{Bps, U32Ext}; -pub mod ext; mod hal_02; mod hal_1; -use ext::{SrR, UartExt}; +use crate::pacext::uart::{SrR, UartRB}; pub trait SerialExt: Sized + Instance { fn serial( @@ -164,7 +163,7 @@ impl SerialExt for USART { } } -pub trait RBExt: UartExt { +pub trait RBExt: UartRB { fn set_stopbits(&self, bits: StopBits); }