diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 23dd6c16a8..8716696d97 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Previously unavailable memory is available via `.dram2_uninit` section (#2079) - You can now use `Input`, `Output`, `OutputOpenDrain` and `Flex` pins as EXTI and RTCIO wakeup sources (#2095) - Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883) +- Added APIs to allow connecting signals through the GPIO matrix. (#2128) ### Changed @@ -37,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The (previously undocumented) `ErasedPin` enum has been replaced with the `ErasedPin` struct. (#2094) - Renamed and merged `Rtc::get_time_us` and `Rtc::get_time_ms` into `Rtc::time_since_boot` (#1883) - ESP32: Added support for touch sensing on GPIO32 and 33 (#2109) +- Replaced `AnyPin` with `InputSignal` and `OutputSignal` and renamed `ErasedPin` to `AnyPin` (#2128) ### Fixed diff --git a/esp-hal/MIGRATING-0.20.md b/esp-hal/MIGRATING-0.20.md index c1907594fd..52b1a7a0c4 100644 --- a/esp-hal/MIGRATING-0.20.md +++ b/esp-hal/MIGRATING-0.20.md @@ -48,7 +48,7 @@ You no longer have to spell out the GPIO pin type for `Input`, `Output`, `Output However, if you want to, you can keep using their typed form! ```rust -let pin = Input::new(io.gpio0); // pin will have the type `Input<'some>` (or `Input<'some, ErasedPin>` if you want to be explicit about it) +let pin = Input::new(io.gpio0); // pin will have the type `Input<'some>` (or `Input<'some, AnyPin>` if you want to be explicit about it) let pin = Input::new_typed(io.gpio0); // pin will have the type `Input<'some, GpioPin<0>>` ``` diff --git a/esp-hal/src/gpio/any_pin.rs b/esp-hal/src/gpio/any_pin.rs deleted file mode 100644 index 93c59da4d9..0000000000 --- a/esp-hal/src/gpio/any_pin.rs +++ /dev/null @@ -1,169 +0,0 @@ -use super::*; - -/// A type-erased GPIO pin, with additional configuration options. -/// -/// Note that accessing unsupported pin functions (e.g. trying to use an -/// input-only pin as output) will panic. -pub struct AnyPin<'d> { - pin: ErasedPin, - is_inverted: bool, - _phantom: PhantomData<&'d ()>, -} - -impl<'d> AnyPin<'d> { - /// Create wrapper for the given pin. - #[inline] - pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self - where - P: Pin, - { - crate::into_ref!(pin); - let pin = pin.degrade_internal(private::Internal); - - Self { - pin, - is_inverted: false, - _phantom: PhantomData, - } - } - - /// Create wrapper for the given pin. The peripheral signal will be - /// inverted. - #[inline] - pub fn new_inverted

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self - where - P: Pin, - { - crate::into_ref!(pin); - let pin = pin.degrade_internal(private::Internal); - - Self { - pin, - is_inverted: true, - _phantom: PhantomData, - } - } -} - -impl<'d> crate::peripheral::Peripheral for AnyPin<'d> { - type P = Self; - - unsafe fn clone_unchecked(&mut self) -> Self::P { - Self { - pin: unsafe { self.pin.clone_unchecked() }, - is_inverted: self.is_inverted, - _phantom: PhantomData, - } - } -} - -impl<'d> private::Sealed for AnyPin<'d> {} - -impl<'d> Pin for AnyPin<'d> { - delegate::delegate! { - to self.pin { - fn number(&self, _internal: private::Internal) -> u8; - fn degrade_internal(&self, _internal: private::Internal) -> ErasedPin; - fn sleep_mode(&mut self, on: bool, _internal: private::Internal); - fn set_alternate_function(&mut self, alternate: AlternateFunction, _internal: private::Internal); - fn is_listening(&self, _internal: private::Internal) -> bool; - fn listen_with_options( - &mut self, - event: Event, - int_enable: bool, - nmi_enable: bool, - wake_up_from_light_sleep: bool, - _internal: private::Internal, - ); - fn unlisten(&mut self, _internal: private::Internal); - fn is_interrupt_set(&self, _internal: private::Internal) -> bool; - fn clear_interrupt(&mut self, _internal: private::Internal); - } - } -} - -impl<'d> OutputPin for AnyPin<'d> { - delegate::delegate! { - to self.pin { - fn set_to_open_drain_output(&mut self, _internal: private::Internal); - fn set_to_push_pull_output(&mut self, _internal: private::Internal); - fn enable_output(&mut self, on: bool, _internal: private::Internal); - fn set_output_high(&mut self, on: bool, _internal: private::Internal); - fn set_drive_strength(&mut self, strength: DriveStrength, _internal: private::Internal); - fn enable_open_drain(&mut self, on: bool, _internal: private::Internal); - fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); - fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); - fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); - fn internal_pull_up(&mut self, on: bool, _internal: private::Internal); - fn internal_pull_down(&mut self, on: bool, _internal: private::Internal); - fn disconnect_peripheral_from_output(&mut self, _internal: private::Internal); - fn is_set_high(&self, _internal: private::Internal) -> bool; - } - } - - fn connect_peripheral_to_output_with_options( - &mut self, - signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, - _internal: private::Internal, - ) { - if self.is_inverted { - self.pin.connect_peripheral_to_output_with_options( - signal, - true, - false, - false, - true, - private::Internal, - ); - } else { - self.pin.connect_peripheral_to_output_with_options( - signal, - invert, - invert_enable, - enable_from_gpio, - force_via_gpio_mux, - private::Internal, - ); - } - } -} - -impl<'d> InputPin for AnyPin<'d> { - delegate::delegate! { - to self.pin { - fn init_input(&self, pull_down: bool, pull_up: bool, _internal: private::Internal); - fn enable_input(&mut self, on: bool, _internal: private::Internal); - fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); - fn is_input_high(&self, _internal: private::Internal) -> bool; - fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _internal: private::Internal); - } - } - - fn connect_input_to_peripheral_with_options( - &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, - _internal: private::Internal, - ) { - if self.is_inverted { - self.pin.connect_input_to_peripheral_with_options( - signal, - true, - true, - private::Internal, - ); - } else { - self.pin.connect_input_to_peripheral_with_options( - signal, - invert, - force_via_gpio_mux, - private::Internal, - ); - } - } -} diff --git a/esp-hal/src/gpio/dummy_pin.rs b/esp-hal/src/gpio/dummy_pin.rs index cbc41d1fc9..478628c647 100644 --- a/esp-hal/src/gpio/dummy_pin.rs +++ b/esp-hal/src/gpio/dummy_pin.rs @@ -1,11 +1,12 @@ -//! "Dummy" pins". +//! Placeholder pins. +//! //! These are useful to pass them into peripheral drivers where you don't want //! an actual pin but one is required. use super::*; /// DummyPin, not useful everywhere as it panics if number() is called -#[derive(Default)] +#[derive(Default, Clone)] pub struct DummyPin { value: bool, } @@ -27,43 +28,72 @@ impl crate::peripheral::Peripheral for DummyPin { impl private::Sealed for DummyPin {} -impl Pin for DummyPin { - fn number(&self, _: private::Internal) -> u8 { - panic!("DummyPin not supported here!"); +impl PeripheralInput for DummyPin { + fn input_signals(&self, _: private::Internal) -> [Option; 6] { + [None; 6] } - fn degrade_internal(&self, _: private::Internal) -> ErasedPin { - panic!("Can not type erase the DummyPin!"); - } + fn init_input(&self, _pull: Pull, _: private::Internal) {} - fn sleep_mode(&mut self, _on: bool, _: private::Internal) {} + fn enable_input(&mut self, _on: bool, _: private::Internal) {} - fn set_alternate_function(&mut self, _alternate: AlternateFunction, _: private::Internal) {} + fn enable_input_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {} - fn is_listening(&self, _: private::Internal) -> bool { - false + fn is_input_high(&self, _: private::Internal) -> bool { + self.value } - fn listen_with_options( - &mut self, - _event: Event, - _int_enable: bool, - _nmi_enable: bool, - _wake_up_from_light_sleep: bool, - _: private::Internal, - ) { + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + let value = if self.value { ONE_INPUT } else { ZERO_INPUT }; + + unsafe { &*GPIO::PTR } + .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) + .modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(false) + .in_sel() + .bits(value) + }); } - fn unlisten(&mut self, _: private::Internal) {} + fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {} +} + +impl PeripheralSignal for Level { + delegate::delegate! { + to match self { + Level::High => DummyPin { value: true }, + Level::Low => DummyPin { value: false }, + } { + fn pull_direction(&self, pull: Pull, _internal: private::Internal); + } + } +} - fn is_interrupt_set(&self, _: private::Internal) -> bool { - false +impl PeripheralInput for Level { + delegate::delegate! { + to match self { + Level::High => DummyPin { value: true }, + Level::Low => DummyPin { value: false }, + } { + fn init_input(&self, _pull: Pull, _internal: private::Internal); + fn enable_input(&mut self, _on: bool, _internal: private::Internal); + fn enable_input_in_sleep_mode(&mut self, _on: bool, _internal: private::Internal); + fn is_input_high(&self, _internal: private::Internal) -> bool; + fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal); + fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal); + fn input_signals(&self, _internal: private::Internal) -> [Option; 6]; + } } +} - fn clear_interrupt(&mut self, _: private::Internal) {} +impl PeripheralSignal for DummyPin { + fn pull_direction(&self, _pull: Pull, _internal: private::Internal) {} } -impl OutputPin for DummyPin { +impl PeripheralOutput for DummyPin { fn set_to_open_drain_output(&mut self, _: private::Internal) {} fn set_to_push_pull_output(&mut self, _: private::Internal) {} @@ -84,53 +114,17 @@ impl OutputPin for DummyPin { fn internal_pull_down_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {} - fn internal_pull_up(&mut self, _on: bool, _: private::Internal) {} - - fn internal_pull_down(&mut self, _on: bool, _: private::Internal) {} - - fn connect_peripheral_to_output(&mut self, _signal: OutputSignal, _: private::Internal) {} - - fn connect_peripheral_to_output_with_options( - &mut self, - _signal: OutputSignal, - _invert: bool, - _invert_enable: bool, - _enable_from_gpio: bool, - _force_via_gpio_mux: bool, - _: private::Internal, - ) { - } - - fn disconnect_peripheral_from_output(&mut self, _: private::Internal) {} - fn is_set_high(&self, _: private::Internal) -> bool { self.value } -} -impl InputPin for DummyPin { - fn init_input(&self, _pull_down: bool, _pull_up: bool, _: private::Internal) {} - - fn enable_input(&mut self, _on: bool, _: private::Internal) {} - - fn enable_input_in_sleep_mode(&mut self, _on: bool, _: private::Internal) {} - - fn is_input_high(&self, _: private::Internal) -> bool { - self.value + fn output_signals(&self, _: private::Internal) -> [Option; 6] { + [None; 6] } - fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {} - - fn connect_input_to_peripheral_with_options( - &mut self, - _signal: InputSignal, - _invert: bool, - _force_via_gpio_mux: bool, - _: private::Internal, - ) { - } + fn connect_peripheral_to_output(&mut self, _signal: OutputSignal, _: private::Internal) {} - fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _: private::Internal) {} + fn disconnect_from_peripheral_output(&mut self, _signal: OutputSignal, _: private::Internal) {} } impl embedded_hal_02::digital::v2::OutputPin for DummyPin { @@ -147,10 +141,10 @@ impl embedded_hal_02::digital::v2::OutputPin for DummyPin { } impl embedded_hal_02::digital::v2::StatefulOutputPin for DummyPin { fn is_set_high(&self) -> Result { - Ok(OutputPin::is_set_high(self, private::Internal)) + Ok(PeripheralOutput::is_set_high(self, private::Internal)) } fn is_set_low(&self) -> Result { - Ok(!OutputPin::is_set_high(self, private::Internal)) + Ok(!PeripheralOutput::is_set_high(self, private::Internal)) } } @@ -172,10 +166,10 @@ impl embedded_hal::digital::OutputPin for DummyPin { impl embedded_hal::digital::StatefulOutputPin for DummyPin { fn is_set_high(&mut self) -> Result { - Ok(OutputPin::is_set_high(self, private::Internal)) + Ok(PeripheralOutput::is_set_high(self, private::Internal)) } fn is_set_low(&mut self) -> Result { - Ok(!OutputPin::is_set_high(self, private::Internal)) + Ok(!PeripheralOutput::is_set_high(self, private::Internal)) } } diff --git a/esp-hal/src/gpio/etm.rs b/esp-hal/src/gpio/etm.rs index 7cfe6d8b6a..8e4da7b712 100644 --- a/esp-hal/src/gpio/etm.rs +++ b/esp-hal/src/gpio/etm.rs @@ -152,11 +152,7 @@ impl GpioEtmEventChannel { { crate::into_ref!(pin); - pin.init_input( - pin_config.pull == Pull::Down, - pin_config.pull == Pull::Up, - private::Internal, - ); + pin.init_input(pin_config.pull, private::Internal); enable_event_channel(C, pin.number(private::Internal)); GpioEtmEventChannelRising { _pin: pin } @@ -173,11 +169,7 @@ impl GpioEtmEventChannel { { crate::into_ref!(pin); - pin.init_input( - pin_config.pull == Pull::Down, - pin_config.pull == Pull::Up, - private::Internal, - ); + pin.init_input(pin_config.pull, private::Internal); enable_event_channel(C, pin.number(private::Internal)); GpioEtmEventChannelFalling { _pin: pin } @@ -194,11 +186,7 @@ impl GpioEtmEventChannel { { crate::into_ref!(pin); - pin.init_input( - pin_config.pull == Pull::Down, - pin_config.pull == Pull::Up, - private::Internal, - ); + pin.init_input(pin_config.pull, private::Internal); enable_event_channel(C, pin.number(private::Internal)); GpioEtmEventChannelAny { _pin: pin } @@ -318,8 +306,7 @@ impl GpioEtmTaskChannel { pin.set_output_high(pin_config.initial_state.into(), private::Internal); if pin_config.open_drain { - pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal); - pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal); + pin.pull_direction(pin_config.pull, private::Internal); pin.set_to_open_drain_output(private::Internal); } else { pin.set_to_push_pull_output(private::Internal); @@ -342,8 +329,7 @@ impl GpioEtmTaskChannel { pin.set_output_high(pin_config.initial_state.into(), private::Internal); if pin_config.open_drain { - pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal); - pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal); + pin.pull_direction(pin_config.pull, private::Internal); pin.set_to_open_drain_output(private::Internal); } else { pin.set_to_push_pull_output(private::Internal); @@ -366,8 +352,7 @@ impl GpioEtmTaskChannel { pin.set_output_high(pin_config.initial_state.into(), private::Internal); if pin_config.open_drain { - pin.internal_pull_down(pin_config.pull == Pull::Down, private::Internal); - pin.internal_pull_up(pin_config.pull == Pull::Up, private::Internal); + pin.pull_direction(pin_config.pull, private::Internal); pin.set_to_open_drain_output(private::Internal); } else { pin.set_to_push_pull_output(private::Internal); diff --git a/esp-hal/src/gpio/interconnect.rs b/esp-hal/src/gpio/interconnect.rs new file mode 100644 index 0000000000..cc9333598c --- /dev/null +++ b/esp-hal/src/gpio/interconnect.rs @@ -0,0 +1,418 @@ +//! Peripheral signal interconnect using IOMUX or GPIOMUX. + +use crate::{ + gpio::{ + self, + AlternateFunction, + AnyPin, + DummyPin, + GpioPin, + GpioProperties, + InputPin, + Level, + OutputSignalType, + PeripheralInput, + PeripheralOutput, + PeripheralSignal, + Pin, + Pull, + FUNC_IN_SEL_OFFSET, + GPIO_FUNCTION, + INPUT_SIGNAL_MAX, + OUTPUT_SIGNAL_MAX, + }, + peripheral::Peripheral, + peripherals::GPIO, + private::{self, Sealed}, +}; + +/// A configurable input signal between a peripheral and a GPIO pin. +/// +/// Obtained by calling [`GpioPin::peripheral_input()`], +/// [`super::Flex::peripheral_input()`] or [`super::Input::peripheral_input()`]. +/// +/// Multiple input signals can be connected to one pin. +pub struct InputSignal { + pin: AnyPin, + is_inverted: bool, +} + +impl Clone for InputSignal { + fn clone(&self) -> Self { + Self { + pin: unsafe { self.pin.clone_unchecked() }, + is_inverted: self.is_inverted, + } + } +} + +impl Peripheral for InputSignal { + type P = Self; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + self.clone() + } +} + +impl Sealed for InputSignal {} + +impl InputSignal { + pub(crate) fn new(pin: AnyPin) -> Self { + Self { + pin, + is_inverted: false, + } + } + + /// Inverts the peripheral's input signal. + /// + /// Calling this function multiple times toggles the setting. + pub fn invert(&mut self) { + self.is_inverted = !self.is_inverted; + } + + /// Consumed the signal and returns a new one that inverts the peripheral's + /// input signal. + /// + /// Calling this function multiple times toggles the setting. + pub fn inverted(mut self) -> Self { + self.invert(); + self + } + + /// - signal: The input signal to connect to the pin + /// - invert: Configures whether or not to invert the input value + /// - input: The GPIO number to connect to the input signal + fn connect(&self, signal: usize, invert: bool, input: u8) { + unsafe { &*GPIO::PTR } + .func_in_sel_cfg(signal - FUNC_IN_SEL_OFFSET) + .modify(|_, w| unsafe { + w.sel() + .set_bit() + .in_inv_sel() + .bit(invert) + .in_sel() + .bits(input) + }); + } +} + +impl PeripheralSignal for InputSignal { + delegate::delegate! { + to self.pin { + fn pull_direction(&self, pull: Pull, _internal: private::Internal); + } + } +} + +impl PeripheralInput for InputSignal { + /// Connect the pin to a peripheral input signal. + /// + /// Since there can only be one input signal connected to a peripheral at a + /// time, this function will disconnect any previously connected input + /// signals. + fn connect_input_to_peripheral(&mut self, signal: gpio::InputSignal, _: private::Internal) { + let signal_nr = signal as usize; + + let af = if self.is_inverted { + GPIO_FUNCTION + } else { + self.pin + .input_signals(private::Internal) + .into_iter() + .position(|s| s == Some(signal)) + .ok_or(()) + .and_then(AlternateFunction::try_from) + .unwrap_or(GPIO_FUNCTION) + }; + + if af == GPIO_FUNCTION && signal_nr > INPUT_SIGNAL_MAX as usize { + panic!("Cannot connect GPIO to this peripheral"); + } + + self.pin.set_alternate_function(af, private::Internal); + + if signal_nr <= INPUT_SIGNAL_MAX as usize { + self.connect( + signal_nr, + self.is_inverted, + self.pin.number(private::Internal), + ); + } + } + + /// Remove this pin from a connected peripheral input. + /// + /// Clears the entry in the GPIO matrix / Io mux that associates this input + /// pin with the given [input `signal`](`InputSignal`). Any other + /// connected signals remain intact. + fn disconnect_input_from_peripheral( + &mut self, + signal: gpio::InputSignal, + _: private::Internal, + ) { + self.pin + .set_alternate_function(GPIO_FUNCTION, private::Internal); + + unsafe { &*GPIO::PTR } + .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) + .modify(|_, w| w.sel().clear_bit()); + } + + delegate::delegate! { + to self.pin { + fn init_input(&self, pull: Pull, _internal: private::Internal); + fn is_input_high(&self, _internal: private::Internal) -> bool; + fn input_signals(&self, _internal: private::Internal) -> [Option; 6]; + fn enable_input(&mut self, on: bool, _internal: private::Internal); + fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + } + } +} + +/// A configurable output signal between a peripheral and a GPIO pin. +/// +/// Obtained by calling [`GpioPin::into_peripheral_output()`], +/// [`super::Flex::into_peripheral_output()`] or +/// [`super::Output::into_peripheral_output()`]. +/// +/// Multiple pins can be connected to one output signal. +pub struct OutputSignal { + pin: AnyPin, + is_inverted: bool, +} + +impl Peripheral for OutputSignal { + type P = Self; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + Self { + pin: self.pin.clone_unchecked(), + is_inverted: self.is_inverted, + } + } +} + +impl Sealed for OutputSignal {} + +impl OutputSignal { + pub(crate) fn new(pin: AnyPin) -> Self { + Self { + pin, + is_inverted: false, + } + } + + /// Inverts the peripheral's output signal. + /// + /// Calling this function multiple times toggles the setting. + pub fn invert(&mut self) { + self.is_inverted = !self.is_inverted; + } + + /// Consumed the signal and returns a new one that inverts the peripheral's + /// output signal. + /// + /// Calling this function multiple times toggles the setting. + pub fn inverted(mut self) -> Self { + self.invert(); + self + } + + /// - signal: The output signal to connect to the pin + /// - invert: Configures whether or not to invert the output value + /// - invert_enable: Configures whether or not to invert the output enable + /// signal + /// - enable_from_gpio: Configures to select the source of output enable + /// signal. + /// - false: Use output enable signal from peripheral + /// - true: Force the output enable signal to be sourced from bit n of + /// GPIO_ENABLE_REG + /// - output: The GPIO number to connect to the output signal + fn connect( + &self, + signal: OutputSignalType, + invert: bool, + invert_enable: bool, + enable_from_gpio: bool, + output: u8, + ) { + unsafe { &*GPIO::PTR } + .func_out_sel_cfg(output as usize) + .modify(|_, w| unsafe { + w.out_sel() + .bits(signal) + .inv_sel() + .bit(invert) + .oen_sel() + .bit(enable_from_gpio) + .oen_inv_sel() + .bit(invert_enable) + }); + } +} + +impl PeripheralSignal for OutputSignal { + delegate::delegate! { + to self.pin { + fn pull_direction(&self, pull: Pull, _internal: private::Internal); + } + } +} + +impl PeripheralOutput for OutputSignal { + /// Connect the pin to a peripheral output signal. + fn connect_peripheral_to_output(&mut self, signal: gpio::OutputSignal, _: private::Internal) { + let af = if self.is_inverted { + GPIO_FUNCTION + } else { + self.pin + .output_signals(private::Internal) + .into_iter() + .position(|s| s == Some(signal)) + .ok_or(()) + .and_then(AlternateFunction::try_from) + .unwrap_or(GPIO_FUNCTION) + }; + + self.pin.set_alternate_function(af, private::Internal); + + let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize { + signal as OutputSignalType + } else { + OUTPUT_SIGNAL_MAX + }; + + self.connect( + clipped_signal, + self.is_inverted, + false, + false, + self.pin.number(private::Internal), + ); + } + + /// Remove this output pin from a connected [signal](`OutputSignal`). + /// + /// Clears the entry in the GPIO matrix / Io mux that associates this output + /// pin with a previously connected [signal](`OutputSignal`). Any other + /// outputs connected to the peripheral remain intact. + fn disconnect_from_peripheral_output( + &mut self, + signal: gpio::OutputSignal, + _: private::Internal, + ) { + self.pin + .set_alternate_function(GPIO_FUNCTION, private::Internal); + + unsafe { &*GPIO::PTR } + .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) + .modify(|_, w| w.sel().clear_bit()); + } + + delegate::delegate! { + to self.pin { + fn set_to_open_drain_output(&mut self, _internal: private::Internal); + fn set_to_push_pull_output(&mut self, _internal: private::Internal); + fn enable_output(&mut self, on: bool, _internal: private::Internal); + fn set_output_high(&mut self, on: bool, _internal: private::Internal); + fn set_drive_strength(&mut self, strength: gpio::DriveStrength, _internal: private::Internal); + fn enable_open_drain(&mut self, on: bool, _internal: private::Internal); + fn enable_output_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn is_set_high(&self, _internal: private::Internal) -> bool; + fn output_signals(&self, _internal: private::Internal) -> [Option; 6]; + } + } +} + +#[derive(Clone)] +enum AnyInputSignalInner { + Input(InputSignal), + Constant(Level), + Dummy(DummyPin), +} + +/// A type-erased input signal. +#[derive(Clone)] +pub struct AnyInputSignal(AnyInputSignalInner); + +impl Peripheral for AnyInputSignal { + type P = Self; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + self.clone() + } +} + +impl From for AnyInputSignal { + fn from(input: InputSignal) -> Self { + Self(AnyInputSignalInner::Input(input)) + } +} + +impl From for AnyInputSignal { + fn from(level: Level) -> Self { + Self(AnyInputSignalInner::Constant(level)) + } +} + +impl From for AnyInputSignal { + fn from(pin: DummyPin) -> Self { + Self(AnyInputSignalInner::Dummy(pin)) + } +} + +impl From for AnyInputSignal { + fn from(input: AnyPin) -> Self { + Self(AnyInputSignalInner::Input(input.peripheral_input())) + } +} + +impl From> for AnyInputSignal +where + GpioPin: InputPin + GpioProperties, +{ + fn from(pin: GpioPin) -> Self { + Self(AnyInputSignalInner::Input(pin.peripheral_input())) + } +} + +impl Sealed for AnyInputSignal {} +impl PeripheralSignal for AnyInputSignal { + delegate::delegate! { + to match &self.0 { + AnyInputSignalInner::Input(pin) => pin, + AnyInputSignalInner::Constant(level) => level, + AnyInputSignalInner::Dummy(pin) => pin, + } { + fn pull_direction(&self, pull: Pull, _internal: private::Internal); + } + } +} + +impl PeripheralInput for AnyInputSignal { + delegate::delegate! { + to match &self.0 { + AnyInputSignalInner::Input(pin) => pin, + AnyInputSignalInner::Constant(level) => level, + AnyInputSignalInner::Dummy(pin) => pin, + } { + fn init_input(&self, pull: Pull, _internal: private::Internal); + fn is_input_high(&self, _internal: private::Internal) -> bool; + fn input_signals(&self, _internal: private::Internal) -> [Option; 6]; + } + + to match &mut self.0 { + AnyInputSignalInner::Input(pin) => pin, + AnyInputSignalInner::Constant(level) => level, + AnyInputSignalInner::Dummy(pin) => pin, + } { + fn enable_input(&mut self, on: bool, _internal: private::Internal); + fn enable_input_in_sleep_mode(&mut self, on: bool, _internal: private::Internal); + fn connect_input_to_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal); + fn disconnect_input_from_peripheral(&mut self, signal: crate::gpio::InputSignal, _internal: private::Internal); + } + } +} diff --git a/esp-hal/src/gpio/lp_io.rs b/esp-hal/src/gpio/lp_io.rs index bf59e9164c..8f1fd6e715 100644 --- a/esp-hal/src/gpio/lp_io.rs +++ b/esp-hal/src/gpio/lp_io.rs @@ -264,7 +264,7 @@ macro_rules! lp_gpio { ($this:expr, $inner:ident, $code:tt) => { match $this { $( - ErasedPinInner::[]($inner) => { + AnyPinInner::[]($inner) => { $code }, )+ diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 41dafe45ae..8965533a3b 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -2,8 +2,8 @@ //! //! ## Overview //! -//! Each pin can be used as a general-purpose I/O, or be connected to an -//! internal peripheral signal. +//! Each pin can be used as a general-purpose I/O, or be connected to one or +//! more internal peripheral signals. //! //! ## Configuration //! @@ -18,7 +18,7 @@ //! provide a common interface for GPIO pins. //! //! To get access to the pins, you first need to convert them into a HAL -//! designed struct from the pac struct `GPIO` and `IO_MUX` using `Io::new`. +//! designed struct from the pac struct `GPIO` and `IO_MUX` using [`Io::new`]. //! //! ### Pin Types //! @@ -29,6 +29,12 @@ //! - [DummyPin] is a useful for cases where peripheral driver requires a pin, //! but real pin cannot be used. //! +//! ### GPIO interconnect +//! +//! Each GPIO can be connected to one output signal and any number of input +//! signals. This allows connections inside of the MCU without allocating and +//! connecting multiple pins for loopback functionality. +//! //! ## Examples //! //! ### Set up a GPIO as an Output @@ -52,8 +58,6 @@ //! [Commonly Used Setup]: ../index.html#commonly-used-setup //! [Inverting TX and RX Pins]: ../uart/index.html#inverting-tx-and-rx-pins -use core::marker::PhantomData; - use portable_atomic::{AtomicPtr, Ordering}; use procmacros::ram; @@ -69,14 +73,13 @@ use crate::{ interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::{GPIO, IO_MUX}, - private, + private::{self, Sealed}, InterruptConfigurable, }; -mod any_pin; mod dummy_pin; +pub mod interconnect; -pub use any_pin::AnyPin; pub use dummy_pin::DummyPin; #[cfg(soc_etm)] @@ -153,6 +156,8 @@ pub enum Level { High, } +impl Sealed for Level {} + impl core::ops::Not for Level { type Output = Self; @@ -229,6 +234,22 @@ pub enum AlternateFunction { Function5 = 5, } +impl TryFrom for AlternateFunction { + type Error = (); + + fn try_from(value: usize) -> Result { + match value { + 0 => Ok(AlternateFunction::Function0), + 1 => Ok(AlternateFunction::Function1), + 2 => Ok(AlternateFunction::Function2), + 3 => Ok(AlternateFunction::Function3), + 4 => Ok(AlternateFunction::Function4), + 5 => Ok(AlternateFunction::Function5), + _ => Err(()), + } + } +} + /// RTC function #[derive(PartialEq)] pub enum RtcFunction { @@ -269,16 +290,16 @@ pub trait RtcPinWithResistors: RtcPin { } /// Common trait implemented by pins -pub trait Pin: private::Sealed { +pub trait Pin: Sealed { /// GPIO number fn number(&self, _: private::Internal) -> u8; - /// Type-erase (degrade) this pin into an ErasedPin. + /// Type-erase (degrade) this pin into an AnyPin. /// /// This converts pin singletons (`GpioPin<0>`, …), which are all different /// types, into the same type. It is useful for creating arrays of pins, /// or avoiding generics. - fn degrade(self) -> ErasedPin + fn degrade(self) -> AnyPin where Self: Sized, { @@ -286,7 +307,7 @@ pub trait Pin: private::Sealed { } #[doc(hidden)] - fn degrade_internal(&self, _: private::Internal) -> ErasedPin; + fn degrade_internal(&self, _: private::Internal) -> AnyPin; /// Enable/disable sleep-mode fn sleep_mode(&mut self, on: bool, _: private::Internal); @@ -294,45 +315,21 @@ pub trait Pin: private::Sealed { /// Configure the alternate function fn set_alternate_function(&mut self, alternate: AlternateFunction, _: private::Internal); - /// Listen for interrupts - fn listen(&mut self, event: Event, _: private::Internal) { - self.listen_with_options(event, true, false, false, private::Internal) - } - - /// Checks if listening for interrupts is enabled for this Pin - fn is_listening(&self, _: private::Internal) -> bool { - is_listening(self.number(private::Internal)) - } - - /// Listen for interrupts - fn listen_with_options( - &mut self, - event: Event, - int_enable: bool, - nmi_enable: bool, - wake_up_from_light_sleep: bool, - _: private::Internal, - ); - - /// Stop listening for interrupts - fn unlisten(&mut self, _: private::Internal); - - /// Checks if the interrupt status bit for this Pin is set - fn is_interrupt_set(&self, _: private::Internal) -> bool; - - /// Clear the interrupt status bit for this Pin - fn clear_interrupt(&mut self, _: private::Internal); + /// Enable or disable the GPIO pin output buffer. + fn output_enable(&mut self, enable: bool, _: private::Internal); +} - /// Enable this pin as a wake up source - fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _: private::Internal) { - self.listen_with_options(event.into(), false, false, enable, private::Internal); - } +/// Common trait implemented by signals which can be used as peripheral inputs +/// or outputs. +pub trait PeripheralSignal: Sealed { + /// Configure the pullup and pulldown resistors + fn pull_direction(&self, pull: Pull, _: private::Internal); } -/// Trait implemented by pins which can be used as inputs -pub trait InputPin: Pin { +/// Trait implemented by pins which can be used as peripheral inputs. +pub trait PeripheralInput: PeripheralSignal { /// Init as input with the given pull-up/pull-down - fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal); + fn init_input(&self, pull: Pull, _: private::Internal); /// Enable input for the pin fn enable_input(&mut self, on: bool, _: private::Internal); @@ -343,33 +340,19 @@ pub trait InputPin: Pin { /// The current state of the input fn is_input_high(&self, _: private::Internal) -> bool; - /// Connect the pin to a peripheral input signal - fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { - self.connect_input_to_peripheral_with_options(signal, false, false, private::Internal); - } + /// Returns the list of input signals that can be connected to this pin + /// using IO_MUX. + fn input_signals(&self, _: private::Internal) -> [Option; 6]; - /// Connect the pin to a peripheral input signal. - /// - /// Optionally invert the signal. When `force_via_gpio_mux` is true it will - /// won't use the alternate function even if it matches - fn connect_input_to_peripheral_with_options( - &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, - _: private::Internal, - ); + /// Connect the pin to a peripheral. + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal); - /// Remove a connected `signal` from this input pin. - /// - /// Clears the entry in the GPIO matrix / Io mux that associates this input - /// pin with the given [input `signal`](`InputSignal`). Any other - /// connected signals remain intact. + /// Disconnect the pin from a peripheral. fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal); } -/// Trait implemented by pins which can be used as outputs -pub trait OutputPin: Pin { +/// Trait implemented by pins which can be used as peripheral outputs. +pub trait PeripheralOutput: PeripheralSignal { /// Configure open-drain mode fn set_to_open_drain_output(&mut self, _: private::Internal); @@ -397,60 +380,60 @@ pub trait OutputPin: Pin { /// Configure internal pull-down resistor in sleep mode fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _: private::Internal); - /// Enable/disable internal pull-up resistor for normal operation - fn internal_pull_up(&mut self, on: bool, _: private::Internal); + /// Is the output set to high + fn is_set_high(&self, _: private::Internal) -> bool; - /// Enable/disable internal pull-down resistor for normal operation - fn internal_pull_down(&mut self, on: bool, _: private::Internal); + /// Returns the list of output signals that can be connected to this pin + /// using IO_MUX. + fn output_signals(&self, _: private::Internal) -> [Option; 6]; - /// Connect the pin to a peripheral output signal - fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal) { - self.connect_peripheral_to_output_with_options( - signal, - false, - false, - false, - false, - private::Internal, - ) + /// Connect the pin to a peripheral. + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal); + + /// Disconnect the pin from a peripheral. + fn disconnect_from_peripheral_output(&mut self, signal: OutputSignal, _: private::Internal); +} + +/// Trait implemented by pins which can be used as inputs. +pub trait InputPin: Pin + PeripheralInput { + /// Listen for interrupts + fn listen(&mut self, event: Event, _: private::Internal) { + self.listen_with_options(event, true, false, false, private::Internal) } - /// Connect the pin to a peripheral output signal. - /// - /// invert: Configures whether or not to invert the output value - /// - /// invert_enable: Configures whether or not to invert the output enable - /// signal - /// - /// enable_from_gpio: Configures to select the source of output enable - /// signal. - /// - false = Use output enable signal from peripheral - /// - true = Force the output enable signal to be sourced from bit n of - /// GPIO_ENABLE_REG - /// - /// force_via_gpio_mux: if true don't use the alternate function even if it - /// matches - fn connect_peripheral_to_output_with_options( + /// Checks if listening for interrupts is enabled for this Pin + fn is_listening(&self, _: private::Internal) -> bool { + is_listening(self.number(private::Internal)) + } + + /// Listen for interrupts + fn listen_with_options( &mut self, - signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, _: private::Internal, ); - /// Remove this output pin from a connected [signal](`InputSignal`). - /// - /// Clears the entry in the GPIO matrix / Io mux that associates this output - /// pin with a previously connected [signal](`InputSignal`). Any other - /// outputs connected to the signal remain intact. - fn disconnect_peripheral_from_output(&mut self, _: private::Internal); + /// Stop listening for interrupts + fn unlisten(&mut self, _: private::Internal); - /// Is the output set to high - fn is_set_high(&self, _: private::Internal) -> bool; + /// Checks if the interrupt status bit for this Pin is set + fn is_interrupt_set(&self, _: private::Internal) -> bool; + + /// Clear the interrupt status bit for this Pin + fn clear_interrupt(&mut self, _: private::Internal); + + /// Enable this pin as a wake up source + fn wakeup_enable(&mut self, enable: bool, event: WakeEvent, _: private::Internal) { + self.listen_with_options(event.into(), false, false, enable, private::Internal); + } } +/// Trait implemented by pins which can be used as outputs. +pub trait OutputPin: Pin + PeripheralOutput {} + /// Trait implemented by pins which can be used as analog pins pub trait AnalogPin: Pin { /// Configure the pin for analog operation @@ -531,12 +514,6 @@ where } } -#[doc(hidden)] -pub trait GpioSignal { - fn output_signals() -> [Option; 6]; - fn input_signals() -> [Option; 6]; -} - #[doc(hidden)] pub struct Bank0GpioRegisterAccess; @@ -651,34 +628,6 @@ impl BankGpioRegisterAccess for Bank1GpioRegisterAccess { } } -/// Connect an always-low signal to the peripheral input signal -pub fn connect_low_to_peripheral(signal: InputSignal) { - unsafe { &*GPIO::PTR } - .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) - .modify(|_, w| unsafe { - w.sel() - .set_bit() - .in_inv_sel() - .bit(false) - .in_sel() - .bits(ZERO_INPUT) - }); -} - -/// Connect an always-high signal to the peripheral input signal -pub fn connect_high_to_peripheral(signal: InputSignal) { - unsafe { &*GPIO::PTR } - .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) - .modify(|_, w| unsafe { - w.sel() - .set_bit() - .in_inv_sel() - .bit(false) - .in_sel() - .bits(ONE_INPUT) - }); -} - #[doc(hidden)] pub trait BooleanType {} @@ -717,6 +666,15 @@ where ::Bank::write_out_en_clear(1 << (GPIONUM % 32)); } } + + /// Returns a peripheral [input][interconnect::InputSignal] connected to + /// this pin. + /// + /// The input signal can be passed to peripherals in place of an input pin. + #[inline] + pub fn peripheral_input(&self) -> interconnect::InputSignal { + interconnect::InputSignal::new(self.degrade_internal(private::Internal)) + } } /// Workaround to make D+ and D- work on the ESP32-C3 and ESP32-S3, which by @@ -749,21 +707,66 @@ fn disable_usb_pads(gpionum: u8) { } } -impl InputPin for GpioPin +impl Peripheral for GpioPin where Self: GpioProperties, { - fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal) { - let gpio = unsafe { &*GPIO::PTR }; + type P = GpioPin; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + core::ptr::read(self as *const _) + } +} - self.write_out_en(false); +impl private::Sealed for GpioPin where Self: GpioProperties {} - gpio.func_out_sel_cfg(GPIONUM as usize) - .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); +impl Pin for GpioPin +where + Self: GpioProperties, +{ + fn number(&self, _: private::Internal) -> u8 { + GPIONUM + } + + fn degrade_internal(&self, _: private::Internal) -> AnyPin { + self.degrade_pin(private::Internal) + } + + fn sleep_mode(&mut self, on: bool, _: private::Internal) { + get_io_mux_reg(GPIONUM).modify(|_, w| w.slp_sel().bit(on)); + } + + fn set_alternate_function(&mut self, alternate: AlternateFunction, _: private::Internal) { + get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) }); + } + + fn output_enable(&mut self, enable: bool, _: private::Internal) { + self.write_out_en(enable); + } +} + +impl PeripheralSignal for GpioPin +where + Self: GpioProperties, +{ + fn pull_direction(&self, pull: Pull, _: private::Internal) { + let pull_up = pull == Pull::Up; + let pull_down = pull == Pull::Down; #[cfg(esp32)] crate::soc::gpio::errata36(GPIONUM, Some(pull_up), Some(pull_down)); + get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpd().bit(pull_down).fun_wpu().bit(pull_up)); + } +} + +impl PeripheralInput for GpioPin +where + Self: GpioProperties, +{ + fn init_input(&self, pull: Pull, _: private::Internal) { + self.pull_direction(pull, private::Internal); + #[cfg(any(esp32c3, esp32s3))] disable_usb_pads(GPIONUM); @@ -772,10 +775,6 @@ where .bits(GPIO_FUNCTION as u8) .fun_ie() .set_bit() - .fun_wpd() - .bit(pull_down) - .fun_wpu() - .bit(pull_up) .slp_sel() .clear_bit() }); @@ -793,85 +792,25 @@ where ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 } - fn connect_input_to_peripheral_with_options( - &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, - _: private::Internal, - ) { - let af = if force_via_gpio_mux { - GPIO_FUNCTION - } else { - let mut res = GPIO_FUNCTION; - for (i, input_signal) in ::Signals::input_signals() - .iter() - .enumerate() - { - if let Some(input_signal) = input_signal { - if *input_signal == signal { - res = match i { - 0 => AlternateFunction::Function0, - 1 => AlternateFunction::Function1, - 2 => AlternateFunction::Function2, - 3 => AlternateFunction::Function3, - 4 => AlternateFunction::Function4, - 5 => AlternateFunction::Function5, - _ => unreachable!(), - }; - break; - } - } - } - res - }; - if af == GPIO_FUNCTION && signal as usize > INPUT_SIGNAL_MAX as usize { - panic!("Cannot connect GPIO to this peripheral"); - } - self.set_alternate_function(af, private::Internal); - if (signal as usize) <= INPUT_SIGNAL_MAX as usize { - unsafe { &*GPIO::PTR } - .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) - .modify(|_, w| unsafe { - w.sel() - .set_bit() - .in_inv_sel() - .bit(invert) - .in_sel() - .bits(GPIONUM) - }); - } + fn input_signals(&self, _: private::Internal) -> [Option; 6] { + ::input_signals() } - fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal) { - self.set_alternate_function(GPIO_FUNCTION, private::Internal); + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + self.peripheral_input() + .connect_input_to_peripheral(signal, private::Internal); + } - unsafe { &*GPIO::PTR } - .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) - .modify(|_, w| w.sel().clear_bit()); + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + self.peripheral_input() + .disconnect_input_from_peripheral(signal, private::Internal); } } -impl Pin for GpioPin +impl InputPin for GpioPin where Self: GpioProperties, { - fn number(&self, _: private::Internal) -> u8 { - GPIONUM - } - - fn degrade_internal(&self, _: private::Internal) -> ErasedPin { - self.degrade_pin(private::Internal) - } - - fn sleep_mode(&mut self, on: bool, _: private::Internal) { - get_io_mux_reg(GPIONUM).modify(|_, w| w.slp_sel().bit(on)); - } - - fn set_alternate_function(&mut self, alternate: AlternateFunction, _: private::Internal) { - get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) }); - } - fn listen_with_options( &mut self, event: Event, @@ -914,58 +853,7 @@ where } } -impl Peripheral for GpioPin -where - Self: GpioProperties, -{ - type P = GpioPin; - - unsafe fn clone_unchecked(&mut self) -> Self::P { - core::ptr::read(self as *const _) - } -} - -impl private::Sealed for GpioPin where Self: GpioProperties {} - -impl GpioPin -where - Self: GpioProperties, -{ - fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { - let gpio = unsafe { &*GPIO::PTR }; - - #[cfg(esp32)] - crate::soc::gpio::errata36(GPIONUM, Some(false), Some(false)); - - self.write_out_en(true); - - gpio.pin(GPIONUM as usize) - .modify(|_, w| w.pad_driver().bit(open_drain)); - - gpio.func_out_sel_cfg(GPIONUM as usize) - .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); - - #[cfg(any(esp32c3, esp32s3))] - disable_usb_pads(GPIONUM); - - get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { - w.mcu_sel() - .bits(alternate as u8) - .fun_ie() - .bit(open_drain) - .fun_wpd() - .clear_bit() - .fun_wpu() - .clear_bit() - .fun_drv() - .bits(DriveStrength::I20mA as u8) - .slp_sel() - .clear_bit() - }); - } -} - -impl OutputPin for GpioPin +impl PeripheralOutput for GpioPin where Self: GpioProperties, { @@ -1011,86 +899,65 @@ where get_io_mux_reg(GPIONUM).modify(|_, w| w.mcu_oe().bit(on)); } - fn internal_pull_up(&mut self, on: bool, _: private::Internal) { - #[cfg(esp32)] - crate::soc::gpio::errata36(GPIONUM, Some(on), None); - - get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpu().bit(on)); + fn is_set_high(&self, _: private::Internal) -> bool { + ::Bank::read_output() & (1 << (GPIONUM % 32)) != 0 } - fn internal_pull_down(&mut self, on: bool, _: private::Internal) { - #[cfg(esp32)] - crate::soc::gpio::errata36(GPIONUM, None, Some(on)); + fn output_signals(&self, _: private::Internal) -> [Option; 6] { + ::output_signals() + } - get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpd().bit(on)); + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal) { + self.degrade_internal(private::Internal) + .connect_peripheral_to_output(signal, private::Internal); } - fn connect_peripheral_to_output_with_options( - &mut self, - signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, - _: private::Internal, - ) { - let af = if force_via_gpio_mux { - GPIO_FUNCTION - } else { - let mut res = GPIO_FUNCTION; - for (i, output_signal) in ::Signals::output_signals() - .iter() - .enumerate() - { - if let Some(output_signal) = output_signal { - if *output_signal == signal { - res = match i { - 0 => AlternateFunction::Function0, - 1 => AlternateFunction::Function1, - 2 => AlternateFunction::Function2, - 3 => AlternateFunction::Function3, - 4 => AlternateFunction::Function4, - 5 => AlternateFunction::Function5, - _ => unreachable!(), - }; - break; - } - } - } - res - }; - if af == GPIO_FUNCTION && signal as usize > OUTPUT_SIGNAL_MAX as usize { - panic!("Cannot connect this peripheral to GPIO"); - } - self.set_alternate_function(af, private::Internal); - let clipped_signal = if signal as usize <= OUTPUT_SIGNAL_MAX as usize { - signal as OutputSignalType - } else { - OUTPUT_SIGNAL_MAX - }; - unsafe { &*GPIO::PTR } - .func_out_sel_cfg(GPIONUM as usize) - .modify(|_, w| unsafe { - w.out_sel() - .bits(clipped_signal) - .inv_sel() - .bit(invert) - .oen_sel() - .bit(enable_from_gpio) - .oen_inv_sel() - .bit(invert_enable) - }); + fn disconnect_from_peripheral_output(&mut self, signal: OutputSignal, _: private::Internal) { + self.degrade_internal(private::Internal) + .disconnect_from_peripheral_output(signal, private::Internal); } +} - fn disconnect_peripheral_from_output(&mut self, _: private::Internal) { - self.set_alternate_function(GPIO_FUNCTION, private::Internal); - unsafe { &*GPIO::PTR } - .func_out_sel_cfg(GPIONUM as usize) +impl OutputPin for GpioPin where Self: GpioProperties {} + +impl GpioPin +where + Self: GpioProperties, +{ + fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { + self.write_out_en(true); + + let gpio = unsafe { &*GPIO::PTR }; + + gpio.pin(GPIONUM as usize) + .modify(|_, w| w.pad_driver().bit(open_drain)); + + gpio.func_out_sel_cfg(GPIONUM as usize) .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); + + #[cfg(any(esp32c3, esp32s3))] + disable_usb_pads(GPIONUM); + + get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { + w.mcu_sel() + .bits(alternate as u8) + .fun_ie() + .bit(open_drain) + .fun_drv() + .bits(DriveStrength::I20mA as u8) + .slp_sel() + .clear_bit() + }); } - fn is_set_high(&self, _: private::Internal) -> bool { - ::Bank::read_output() & (1 << (GPIONUM % 32)) != 0 + /// Turns the pin object into a peripheral + /// [output][interconnect::OutputSignal]. + /// + /// The output signal can be passed to peripherals in place of an output + /// pin. + #[inline] + pub fn into_peripheral_output(self) -> interconnect::OutputSignal { + interconnect::OutputSignal::new(self.degrade_internal(private::Internal)) } } @@ -1174,13 +1041,14 @@ fn on_pin_irq(pin_nr: u8) { pub trait GpioProperties { type Bank: BankGpioRegisterAccess; type InterruptStatus: InterruptStatusRegisterAccess; - type Signals: GpioSignal; type IsOutput: BooleanType; type IsAnalog: BooleanType; type IsTouch: BooleanType; - fn degrade_pin(&self, _: private::Internal) -> ErasedPin; + fn degrade_pin(&self, _: private::Internal) -> AnyPin; + fn output_signals() -> [Option; 6]; + fn input_signals() -> [Option; 6]; } #[doc(hidden)] @@ -1253,21 +1121,15 @@ macro_rules! gpio { impl $crate::gpio::GpioProperties for GpioPin<$gpionum> { type Bank = $crate::gpio::[< Bank $bank GpioRegisterAccess >]; type InterruptStatus = $crate::gpio::[< InterruptStatusRegisterAccessBank $bank >]; - type Signals = [< Gpio $gpionum Signals >]; $crate::pin_types!($type); - fn degrade_pin(&self, _: $crate::private::Internal) -> ErasedPin { - ErasedPin($crate::gpio::ErasedPinInner::[< Gpio $gpionum >](unsafe { Self::steal() })) + fn degrade_pin(&self, _: $crate::private::Internal) -> AnyPin { + AnyPin($crate::gpio::AnyPinInner::[< Gpio $gpionum >](unsafe { Self::steal() })) } - } - #[doc(hidden)] - pub struct []; - - impl $crate::gpio::GpioSignal for [] { fn output_signals() -> [Option; 6]{ #[allow(unused_mut)] - let mut output_signals = [None, None, None, None, None, None]; + let mut output_signals = [None; 6]; $( $( @@ -1279,7 +1141,7 @@ macro_rules! gpio { } fn input_signals() -> [Option; 6] { #[allow(unused_mut)] - let mut input_signals = [None, None, None, None, None, None]; + let mut input_signals = [None; 6]; $( $( @@ -1300,29 +1162,29 @@ macro_rules! gpio { )+ } - pub(crate) enum ErasedPinInner { + pub(crate) enum AnyPinInner { $( [](GpioPin<$gpionum>), )+ } /// Type-erased GPIO pin - pub struct ErasedPin(pub(crate) ErasedPinInner); + pub struct AnyPin(pub(crate) AnyPinInner); - impl ErasedPin { + impl AnyPin { pub(crate) unsafe fn clone_unchecked(&self) -> Self { match self.0 { - $(ErasedPinInner::[](_) => { - Self(ErasedPinInner::[< Gpio $gpionum >](unsafe { GpioPin::steal() })) + $(AnyPinInner::[](_) => { + Self(AnyPinInner::[< Gpio $gpionum >](unsafe { GpioPin::steal() })) })+ } } } - impl $crate::peripheral::Peripheral for ErasedPin { - type P = ErasedPin; + impl $crate::peripheral::Peripheral for AnyPin { + type P = AnyPin; unsafe fn clone_unchecked(&mut self) -> Self { - ErasedPin::clone_unchecked(self) + AnyPin::clone_unchecked(self) } } @@ -1334,7 +1196,7 @@ macro_rules! gpio { ($this:expr, $inner:ident, $code:tt) => { match $this { $( - ErasedPinInner::[]($inner) => if_output_pin!($type, { + AnyPinInner::[]($inner) => if_output_pin!($type, { $code } else {{ let _ = $inner; @@ -1351,7 +1213,7 @@ macro_rules! gpio { ($this:expr, $inner:ident, $code:tt) => { match $this { $( - ErasedPinInner::[]($inner) => $code + AnyPinInner::[]($inner) => $code )+ } } @@ -1441,7 +1303,7 @@ macro_rules! rtc_pins { ($this:expr, $inner:ident, $code:tt) => { match $this { $( - paste::paste! { ErasedPinInner::[]($inner) } => { + paste::paste! { AnyPinInner::[]($inner) } => { $code }, )+ @@ -1459,7 +1321,7 @@ macro_rules! rtc_pins { match $this { $( $( - paste::paste! { ErasedPinInner::[]($inner) } => { + paste::paste! { AnyPinInner::[]($inner) } => { // FIXME: replace with $(ignore($rue)) once stable handle_rtcio_with_resistors!(@ignore $rue, $rde); $code @@ -1531,7 +1393,7 @@ macro_rules! rtc_pins { ($this:expr, $inner:ident, $code:tt) => { match $this { $( - paste::paste! { ErasedPinInner::[]($inner) } => { + paste::paste! { AnyPinInner::[]($inner) } => { $code }, )+ @@ -1761,7 +1623,7 @@ macro_rules! touch { } /// GPIO output driver. -pub struct Output<'d, P = ErasedPin> { +pub struct Output<'d, P = AnyPin> { pin: Flex<'d, P>, } @@ -1848,13 +1710,24 @@ where } /// Configure the [DriveStrength] of the pin + #[inline] pub fn set_drive_strength(&mut self, strength: DriveStrength) { self.pin.set_drive_strength(strength); } + + /// Turns the pin object into a peripheral + /// [output][interconnect::OutputSignal]. + /// + /// The output signal can be passed to peripherals in place of an output + /// pin. + #[inline] + pub fn into_peripheral_output(self) -> interconnect::OutputSignal { + self.pin.into_peripheral_output() + } } /// GPIO input driver. -pub struct Input<'d, P = ErasedPin> { +pub struct Input<'d, P = AnyPin> { pin: Flex<'d, P>, } @@ -1922,6 +1795,7 @@ where } /// Stop listening for interrupts + #[inline] pub fn unlisten(&mut self) { self.pin.unlisten(); } @@ -1945,10 +1819,19 @@ where pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) { self.pin.wakeup_enable(enable, event); } + + /// Returns a peripheral [input][interconnect::InputSignal] connected to + /// this pin. + /// + /// The input signal can be passed to peripherals in place of an input pin. + #[inline] + pub fn peripheral_input(&self) -> interconnect::InputSignal { + self.pin.peripheral_input() + } } /// GPIO open-drain output driver. -pub struct OutputOpenDrain<'d, P = ErasedPin> { +pub struct OutputOpenDrain<'d, P = AnyPin> { pin: Flex<'d, P>, } @@ -2074,10 +1957,20 @@ where pub fn set_drive_strength(&mut self, strength: DriveStrength) { self.pin.set_drive_strength(strength); } + + /// Turns the pin object into a peripheral + /// [output][interconnect::OutputSignal]. + /// + /// The output signal can be passed to peripherals in place of an output + /// pin. + #[inline] + pub fn into_peripheral_output(self) -> interconnect::OutputSignal { + self.pin.into_peripheral_output() + } } /// Flexible pin driver. -pub struct Flex<'d, P = ErasedPin> { +pub struct Flex<'d, P = AnyPin> { pin: PeripheralRef<'d, P>, } @@ -2120,8 +2013,8 @@ where { /// Set the GPIO to input mode. pub fn set_as_input(&mut self, pull: Pull) { - self.pin - .init_input(pull == Pull::Down, pull == Pull::Up, private::Internal); + self.pin.init_input(pull, private::Internal); + self.pin.output_enable(false, private::Internal); } /// Get whether the pin input level is high. @@ -2172,6 +2065,15 @@ where pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) { self.pin.wakeup_enable(enable, event, private::Internal); } + + /// Returns a peripheral [input][interconnect::InputSignal] connected to + /// this pin. + /// + /// The input signal can be passed to peripherals in place of an input pin. + #[inline] + pub fn peripheral_input(&self) -> interconnect::InputSignal { + interconnect::InputSignal::new(self.pin.degrade_internal(private::Internal)) + } } impl<'d, P> Flex<'d, P> @@ -2227,9 +2129,20 @@ where } /// Configure the [DriveStrength] of the pin + #[inline] pub fn set_drive_strength(&mut self, strength: DriveStrength) { self.pin.set_drive_strength(strength, private::Internal); } + + /// Turns the pin object into a peripheral + /// [output][interconnect::OutputSignal]. + /// + /// The output signal can be passed to peripherals in place of an output + /// pin. + #[inline] + pub fn into_peripheral_output(self) -> interconnect::OutputSignal { + interconnect::OutputSignal::new(self.pin.degrade_internal(private::Internal)) + } } impl<'d, P> Flex<'d, P> @@ -2239,24 +2152,43 @@ where /// Set the GPIO to open-drain mode. pub fn set_as_open_drain(&mut self, pull: Pull) { self.pin.set_to_open_drain_output(private::Internal); - self.pin - .internal_pull_down(pull == Pull::Down, private::Internal); - self.pin - .internal_pull_up(pull == Pull::Up, private::Internal); + self.pin.pull_direction(pull, private::Internal); } } pub(crate) mod internal { use super::*; - impl private::Sealed for ErasedPin {} + impl private::Sealed for AnyPin {} - impl Pin for ErasedPin { + impl AnyPin { + /// Returns a peripheral [input][interconnect::InputSignal] connected to + /// this pin. + /// + /// The input signal can be passed to peripherals in place of an input + /// pin. + #[inline] + pub fn peripheral_input(&self) -> interconnect::InputSignal { + handle_gpio_input!(&self.0, target, { target.peripheral_input() }) + } + + /// Turns the pin object into a peripheral + /// [output][interconnect::OutputSignal]. + /// + /// The output signal can be passed to peripherals in place of an output + /// pin. + #[inline] + pub fn into_peripheral_output(self) -> interconnect::OutputSignal { + handle_gpio_output!(self.0, target, { target.into_peripheral_output() }) + } + } + + impl Pin for AnyPin { fn number(&self, _: private::Internal) -> u8 { handle_gpio_input!(&self.0, target, { Pin::number(target, private::Internal) }) } - fn degrade_internal(&self, _: private::Internal) -> ErasedPin { + fn degrade_internal(&self, _: private::Internal) -> AnyPin { unsafe { self.clone_unchecked() } } @@ -2272,199 +2204,195 @@ pub(crate) mod internal { }) } - fn listen_with_options( - &mut self, - event: Event, - int_enable: bool, - nmi_enable: bool, - wake_up_from_light_sleep: bool, - _: private::Internal, - ) { + fn output_enable(&mut self, enable: bool, _: private::Internal) { handle_gpio_input!(&mut self.0, target, { - Pin::listen_with_options( - target, - event, - int_enable, - nmi_enable, - wake_up_from_light_sleep, - private::Internal, - ) - }) - } - - fn unlisten(&mut self, _: private::Internal) { - handle_gpio_input!(&mut self.0, target, { - Pin::unlisten(target, private::Internal) + Pin::output_enable(target, enable, private::Internal) }) } + } - fn is_interrupt_set(&self, _: private::Internal) -> bool { + impl PeripheralSignal for AnyPin { + fn pull_direction(&self, pull: Pull, _: private::Internal) { handle_gpio_input!(&self.0, target, { - Pin::is_interrupt_set(target, private::Internal) - }) - } - - fn clear_interrupt(&mut self, _: private::Internal) { - handle_gpio_input!(&mut self.0, target, { - Pin::clear_interrupt(target, private::Internal) + PeripheralSignal::pull_direction(target, pull, private::Internal) }) } } - impl InputPin for ErasedPin { - fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal) { + impl PeripheralInput for AnyPin { + fn init_input(&self, pull: Pull, _: private::Internal) { handle_gpio_input!(&self.0, target, { - InputPin::init_input(target, pull_down, pull_up, private::Internal) - }) + PeripheralInput::init_input(target, pull, private::Internal) + }); } fn enable_input(&mut self, on: bool, _: private::Internal) { handle_gpio_input!(&mut self.0, target, { - InputPin::enable_input(target, on, private::Internal) + PeripheralInput::enable_input(target, on, private::Internal) }); } fn enable_input_in_sleep_mode(&mut self, on: bool, _: private::Internal) { handle_gpio_input!(&mut self.0, target, { - InputPin::enable_input_in_sleep_mode(target, on, private::Internal) + PeripheralInput::enable_input_in_sleep_mode(target, on, private::Internal) }); } fn is_input_high(&self, _: private::Internal) -> bool { handle_gpio_input!(&self.0, target, { - InputPin::is_input_high(target, private::Internal) + PeripheralInput::is_input_high(target, private::Internal) }) } - fn connect_input_to_peripheral_with_options( + fn input_signals(&self, _: private::Internal) -> [Option; 6] { + handle_gpio_input!(&self.0, target, { + PeripheralInput::input_signals(target, private::Internal) + }) + } + + fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + interconnect::InputSignal::new(self.degrade_internal(private::Internal)) + .connect_input_to_peripheral(signal, private::Internal); + } + + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + interconnect::InputSignal::new(self.degrade_internal(private::Internal)) + .disconnect_input_from_peripheral(signal, private::Internal); + } + } + + impl InputPin for AnyPin { + fn listen_with_options( &mut self, - signal: InputSignal, - invert: bool, - force_via_gpio_mux: bool, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, _: private::Internal, ) { handle_gpio_input!(&mut self.0, target, { - InputPin::connect_input_to_peripheral_with_options( + InputPin::listen_with_options( target, - signal, - invert, - force_via_gpio_mux, + event, + int_enable, + nmi_enable, + wake_up_from_light_sleep, private::Internal, ) - }); + }) } - fn disconnect_input_from_peripheral(&mut self, signal: InputSignal, _: private::Internal) { + fn unlisten(&mut self, _: private::Internal) { handle_gpio_input!(&mut self.0, target, { - InputPin::disconnect_input_from_peripheral(target, signal, private::Internal) - }); + InputPin::unlisten(target, private::Internal) + }) + } + + fn is_interrupt_set(&self, _: private::Internal) -> bool { + handle_gpio_input!(&self.0, target, { + InputPin::is_interrupt_set(target, private::Internal) + }) + } + + fn clear_interrupt(&mut self, _: private::Internal) { + handle_gpio_input!(&mut self.0, target, { + InputPin::clear_interrupt(target, private::Internal) + }) + } + + fn listen(&mut self, event: Event, _: private::Internal) { + handle_gpio_input!(&mut self.0, target, { + InputPin::listen(target, event, private::Internal) + }) } } - impl OutputPin for ErasedPin { + impl PeripheralOutput for AnyPin { fn set_to_open_drain_output(&mut self, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::set_to_open_drain_output(target, private::Internal) + PeripheralOutput::set_to_open_drain_output(target, private::Internal) }); } fn set_to_push_pull_output(&mut self, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::set_to_push_pull_output(target, private::Internal) + PeripheralOutput::set_to_push_pull_output(target, private::Internal) }); } fn enable_output(&mut self, on: bool, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::enable_output(target, on, private::Internal) + PeripheralOutput::enable_output(target, on, private::Internal) }); } fn set_output_high(&mut self, on: bool, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::set_output_high(target, on, private::Internal) + PeripheralOutput::set_output_high(target, on, private::Internal) }); } fn set_drive_strength(&mut self, strength: DriveStrength, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::set_drive_strength(target, strength, private::Internal) + PeripheralOutput::set_drive_strength(target, strength, private::Internal) }); } fn enable_open_drain(&mut self, on: bool, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::enable_open_drain(target, on, private::Internal) + PeripheralOutput::enable_open_drain(target, on, private::Internal) }); } fn enable_output_in_sleep_mode(&mut self, on: bool, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::enable_output_in_sleep_mode(target, on, private::Internal) + PeripheralOutput::enable_output_in_sleep_mode(target, on, private::Internal) }); } fn internal_pull_up_in_sleep_mode(&mut self, on: bool, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::internal_pull_up_in_sleep_mode(target, on, private::Internal) + PeripheralOutput::internal_pull_up_in_sleep_mode(target, on, private::Internal) }); } fn internal_pull_down_in_sleep_mode(&mut self, on: bool, _: private::Internal) { handle_gpio_output!(&mut self.0, target, { - OutputPin::internal_pull_down_in_sleep_mode(target, on, private::Internal) + PeripheralOutput::internal_pull_down_in_sleep_mode(target, on, private::Internal) }); } - fn internal_pull_up(&mut self, on: bool, _: private::Internal) { - handle_gpio_output!(&mut self.0, target, { - OutputPin::internal_pull_up(target, on, private::Internal) - }); + fn is_set_high(&self, _: private::Internal) -> bool { + handle_gpio_output!(&self.0, target, { + PeripheralOutput::is_set_high(target, private::Internal) + }) } - fn internal_pull_down(&mut self, on: bool, _: private::Internal) { - handle_gpio_output!(&mut self.0, target, { - OutputPin::internal_pull_down(target, on, private::Internal) - }); + fn output_signals(&self, _: private::Internal) -> [Option; 6] { + handle_gpio_output!(&self.0, target, { + PeripheralOutput::output_signals(target, private::Internal) + }) + } + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal, _: private::Internal) { + interconnect::OutputSignal::new(self.degrade_internal(private::Internal)) + .connect_peripheral_to_output(signal, private::Internal); } - fn connect_peripheral_to_output_with_options( + fn disconnect_from_peripheral_output( &mut self, signal: OutputSignal, - invert: bool, - invert_enable: bool, - enable_from_gpio: bool, - force_via_gpio_mux: bool, _: private::Internal, ) { - handle_gpio_output!(&mut self.0, target, { - OutputPin::connect_peripheral_to_output_with_options( - target, - signal, - invert, - invert_enable, - enable_from_gpio, - force_via_gpio_mux, - private::Internal, - ) - }); - } - - fn disconnect_peripheral_from_output(&mut self, _: private::Internal) { - handle_gpio_output!(&mut self.0, target, { - OutputPin::disconnect_peripheral_from_output(target, private::Internal) - }); - } - - fn is_set_high(&self, _: private::Internal) -> bool { - handle_gpio_output!(&self.0, target, { - OutputPin::is_set_high(target, private::Internal) - }) + interconnect::OutputSignal::new(self.degrade_internal(private::Internal)) + .disconnect_from_peripheral_output(signal, private::Internal); } } + impl OutputPin for AnyPin {} + #[cfg(any(xtensa, esp32c2, esp32c3, esp32c6))] - impl RtcPin for ErasedPin { + impl RtcPin for AnyPin { #[cfg(xtensa)] #[allow(unused_braces)] // False positive :/ fn rtc_number(&self) -> u8 { @@ -2493,7 +2421,7 @@ pub(crate) mod internal { } #[cfg(any(esp32c2, esp32c3, esp32c6, xtensa))] - impl RtcPinWithResistors for ErasedPin { + impl RtcPinWithResistors for AnyPin { fn rtcio_pullup(&mut self, enable: bool) { handle_rtcio_with_resistors!(&mut self.0, target, { RtcPinWithResistors::rtcio_pullup(target, enable) diff --git a/esp-hal/src/i2c.rs b/esp-hal/src/i2c.rs index 69bc04ab73..d7a73fc205 100644 --- a/esp-hal/src/i2c.rs +++ b/esp-hal/src/i2c.rs @@ -57,7 +57,7 @@ use fugit::HertzU32; use crate::{ clock::Clocks, - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::i2c0::{RegisterBlock, COMD}, @@ -321,7 +321,10 @@ impl<'d, T, DM: crate::Mode> I2C<'d, T, DM> where T: Instance, { - fn new_internal( + fn new_internal< + SDA: PeripheralOutput + PeripheralInput, + SCL: PeripheralOutput + PeripheralInput, + >( i2c: impl Peripheral

+ 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, @@ -355,27 +358,29 @@ where scl.set_to_open_drain_output(crate::private::Internal); scl.enable_input(true, crate::private::Internal); - scl.internal_pull_up(true, crate::private::Internal); - scl.connect_peripheral_to_output( - i2c.peripheral.scl_output_signal(), - crate::private::Internal, - ); + scl.pull_direction(Pull::Up, crate::private::Internal); + scl.connect_input_to_peripheral( i2c.peripheral.scl_input_signal(), crate::private::Internal, ); + scl.connect_peripheral_to_output( + i2c.peripheral.scl_output_signal(), + crate::private::Internal, + ); sda.set_to_open_drain_output(crate::private::Internal); sda.enable_input(true, crate::private::Internal); - sda.internal_pull_up(true, crate::private::Internal); - sda.connect_peripheral_to_output( - i2c.peripheral.sda_output_signal(), - crate::private::Internal, - ); + sda.pull_direction(Pull::Up, crate::private::Internal); + sda.connect_input_to_peripheral( i2c.peripheral.sda_input_signal(), crate::private::Internal, ); + sda.connect_peripheral_to_output( + i2c.peripheral.sda_output_signal(), + crate::private::Internal, + ); i2c.peripheral.setup(frequency, timeout); i2c @@ -396,7 +401,7 @@ where /// Create a new I2C instance /// This will enable the peripheral but the peripheral won't get /// automatically disabled when this gets dropped. - pub fn new( + pub fn new( i2c: impl Peripheral

+ 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, @@ -408,7 +413,10 @@ where /// Create a new I2C instance with a custom timeout value. /// This will enable the peripheral but the peripheral won't get /// automatically disabled when this gets dropped. - pub fn new_with_timeout( + pub fn new_with_timeout< + SDA: PeripheralOutput + PeripheralInput, + SCL: PeripheralOutput + PeripheralInput, + >( i2c: impl Peripheral

+ 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, @@ -437,7 +445,10 @@ where /// Create a new I2C instance /// This will enable the peripheral but the peripheral won't get /// automatically disabled when this gets dropped. - pub fn new_async( + pub fn new_async< + SDA: PeripheralOutput + PeripheralInput, + SCL: PeripheralOutput + PeripheralInput, + >( i2c: impl Peripheral

+ 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, @@ -449,7 +460,10 @@ where /// Create a new I2C instance with a custom timeout value. /// This will enable the peripheral but the peripheral won't get /// automatically disabled when this gets dropped. - pub fn new_with_timeout_async( + pub fn new_with_timeout_async< + SDA: PeripheralOutput + PeripheralInput, + SCL: PeripheralOutput + PeripheralInput, + >( i2c: impl Peripheral

+ 'd, sda: impl Peripheral

+ 'd, scl: impl Peripheral

+ 'd, diff --git a/esp-hal/src/i2s.rs b/esp-hal/src/i2s.rs index 3767a1431d..b6a196a620 100644 --- a/esp-hal/src/i2s.rs +++ b/esp-hal/src/i2s.rs @@ -107,7 +107,7 @@ use crate::{ TxPrivate, WriteBuffer, }, - gpio::OutputPin, + gpio::PeripheralOutput, interrupt::InterruptHandler, into_ref, peripheral::Peripheral, @@ -495,10 +495,11 @@ where } /// Configures the I2S peripheral to use a master clock (MCLK) output pin. - pub fn with_mclk(self, pin: impl Peripheral

+ 'd) -> Self { + pub fn with_mclk(self, pin: impl Peripheral

+ 'd) -> Self { into_ref!(pin); pin.set_to_push_pull_output(crate::private::Internal); pin.connect_peripheral_to_output(I::mclk_signal(), crate::private::Internal); + self } } @@ -890,7 +891,7 @@ mod private { use crate::peripherals::{i2s1::RegisterBlock, I2S1}; use crate::{ dma::{ChannelRx, ChannelTx, DmaChannel, DmaDescriptor, DmaPeripheral}, - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, into_ref, peripherals::I2S0, @@ -923,31 +924,34 @@ mod private { pub fn with_bclk

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self where - P: OutputPin, + P: PeripheralOutput, { into_ref!(pin); pin.set_to_push_pull_output(private::Internal); pin.connect_peripheral_to_output(T::bclk_signal(), private::Internal); + self } pub fn with_ws

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self where - P: OutputPin, + P: PeripheralOutput, { into_ref!(pin); pin.set_to_push_pull_output(private::Internal); pin.connect_peripheral_to_output(T::ws_signal(), private::Internal); + self } pub fn with_dout

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self where - P: OutputPin, + P: PeripheralOutput, { into_ref!(pin); pin.set_to_push_pull_output(private::Internal); pin.connect_peripheral_to_output(T::dout_signal(), private::Internal); + self } } @@ -976,31 +980,34 @@ mod private { pub fn with_bclk

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self where - P: OutputPin, + P: PeripheralOutput, { into_ref!(pin); - pin.set_to_push_pull_output(crate::private::Internal); - pin.connect_peripheral_to_output(T::bclk_rx_signal(), crate::private::Internal); + pin.set_to_push_pull_output(private::Internal); + pin.connect_peripheral_to_output(T::bclk_rx_signal(), private::Internal); + self } pub fn with_ws

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self where - P: OutputPin, + P: PeripheralOutput, { into_ref!(pin); - pin.set_to_push_pull_output(crate::private::Internal); - pin.connect_peripheral_to_output(T::ws_rx_signal(), crate::private::Internal); + pin.set_to_push_pull_output(private::Internal); + pin.connect_peripheral_to_output(T::ws_rx_signal(), private::Internal); + self } pub fn with_din

(self, pin: impl crate::peripheral::Peripheral

+ 'd) -> Self where - P: InputPin, + P: PeripheralInput, { into_ref!(pin); - pin.init_input(false, false, crate::private::Internal); - pin.connect_input_to_peripheral(T::din_signal(), crate::private::Internal); + pin.init_input(crate::gpio::Pull::None, private::Internal); + pin.connect_input_to_peripheral(T::din_signal(), private::Internal); + self } } diff --git a/esp-hal/src/lcd_cam/cam.rs b/esp-hal/src/lcd_cam/cam.rs index 41e30c1b6b..2eefd8d7ff 100644 --- a/esp-hal/src/lcd_cam/cam.rs +++ b/esp-hal/src/lcd_cam/cam.rs @@ -81,7 +81,7 @@ use crate::{ RxPrivate, WriteBuffer, }, - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputPin, InputSignal, OutputPin, OutputSignal, Pull}, lcd_cam::{cam::private::RxPins, private::calculate_clkm, BitOrder, ByteOrder}, peripheral::{Peripheral, PeripheralRef}, peripherals::LCD_CAM, @@ -311,7 +311,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { pub fn with_pixel_clock(self, pclk: impl Peripheral

+ 'd) -> Self { crate::into_ref!(pclk); - pclk.init_input(false, false, crate::private::Internal); + pclk.init_input(Pull::None, crate::private::Internal); pclk.connect_input_to_peripheral(InputSignal::CAM_PCLK, crate::private::Internal); self @@ -327,9 +327,9 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { crate::into_ref!(vsync); crate::into_ref!(h_enable); - vsync.init_input(false, false, crate::private::Internal); + vsync.init_input(Pull::None, crate::private::Internal); vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal); - h_enable.init_input(false, false, crate::private::Internal); + h_enable.init_input(Pull::None, crate::private::Internal); h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal); self.lcd_cam @@ -351,11 +351,11 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> { crate::into_ref!(hsync); crate::into_ref!(h_enable); - vsync.init_input(false, false, crate::private::Internal); + vsync.init_input(Pull::None, crate::private::Internal); vsync.connect_input_to_peripheral(InputSignal::CAM_V_SYNC, crate::private::Internal); - hsync.init_input(false, false, crate::private::Internal); + hsync.init_input(Pull::None, crate::private::Internal); hsync.connect_input_to_peripheral(InputSignal::CAM_H_SYNC, crate::private::Internal); - h_enable.init_input(false, false, crate::private::Internal); + h_enable.init_input(Pull::None, crate::private::Internal); h_enable.connect_input_to_peripheral(InputSignal::CAM_H_ENABLE, crate::private::Internal); self.lcd_cam @@ -475,21 +475,21 @@ impl RxEightBits { crate::into_ref!(pin_6); crate::into_ref!(pin_7); - pin_0.init_input(false, false, crate::private::Internal); + pin_0.init_input(Pull::None, crate::private::Internal); pin_0.connect_input_to_peripheral(InputSignal::CAM_DATA_0, crate::private::Internal); - pin_1.init_input(false, false, crate::private::Internal); + pin_1.init_input(Pull::None, crate::private::Internal); pin_1.connect_input_to_peripheral(InputSignal::CAM_DATA_1, crate::private::Internal); - pin_2.init_input(false, false, crate::private::Internal); + pin_2.init_input(Pull::None, crate::private::Internal); pin_2.connect_input_to_peripheral(InputSignal::CAM_DATA_2, crate::private::Internal); - pin_3.init_input(false, false, crate::private::Internal); + pin_3.init_input(Pull::None, crate::private::Internal); pin_3.connect_input_to_peripheral(InputSignal::CAM_DATA_3, crate::private::Internal); - pin_4.init_input(false, false, crate::private::Internal); + pin_4.init_input(Pull::None, crate::private::Internal); pin_4.connect_input_to_peripheral(InputSignal::CAM_DATA_4, crate::private::Internal); - pin_5.init_input(false, false, crate::private::Internal); + pin_5.init_input(Pull::None, crate::private::Internal); pin_5.connect_input_to_peripheral(InputSignal::CAM_DATA_5, crate::private::Internal); - pin_6.init_input(false, false, crate::private::Internal); + pin_6.init_input(Pull::None, crate::private::Internal); pin_6.connect_input_to_peripheral(InputSignal::CAM_DATA_6, crate::private::Internal); - pin_7.init_input(false, false, crate::private::Internal); + pin_7.init_input(Pull::None, crate::private::Internal); pin_7.connect_input_to_peripheral(InputSignal::CAM_DATA_7, crate::private::Internal); Self { _pins: () } @@ -563,37 +563,37 @@ impl RxSixteenBits { crate::into_ref!(pin_14); crate::into_ref!(pin_15); - pin_0.init_input(false, false, crate::private::Internal); + pin_0.init_input(Pull::None, crate::private::Internal); pin_0.connect_input_to_peripheral(InputSignal::CAM_DATA_0, crate::private::Internal); - pin_1.init_input(false, false, crate::private::Internal); + pin_1.init_input(Pull::None, crate::private::Internal); pin_1.connect_input_to_peripheral(InputSignal::CAM_DATA_1, crate::private::Internal); - pin_2.init_input(false, false, crate::private::Internal); + pin_2.init_input(Pull::None, crate::private::Internal); pin_2.connect_input_to_peripheral(InputSignal::CAM_DATA_2, crate::private::Internal); - pin_3.init_input(false, false, crate::private::Internal); + pin_3.init_input(Pull::None, crate::private::Internal); pin_3.connect_input_to_peripheral(InputSignal::CAM_DATA_3, crate::private::Internal); - pin_4.init_input(false, false, crate::private::Internal); + pin_4.init_input(Pull::None, crate::private::Internal); pin_4.connect_input_to_peripheral(InputSignal::CAM_DATA_4, crate::private::Internal); - pin_5.init_input(false, false, crate::private::Internal); + pin_5.init_input(Pull::None, crate::private::Internal); pin_5.connect_input_to_peripheral(InputSignal::CAM_DATA_5, crate::private::Internal); - pin_6.init_input(false, false, crate::private::Internal); + pin_6.init_input(Pull::None, crate::private::Internal); pin_6.connect_input_to_peripheral(InputSignal::CAM_DATA_6, crate::private::Internal); - pin_7.init_input(false, false, crate::private::Internal); + pin_7.init_input(Pull::None, crate::private::Internal); pin_7.connect_input_to_peripheral(InputSignal::CAM_DATA_7, crate::private::Internal); - pin_8.init_input(false, false, crate::private::Internal); + pin_8.init_input(Pull::None, crate::private::Internal); pin_8.connect_input_to_peripheral(InputSignal::CAM_DATA_8, crate::private::Internal); - pin_9.init_input(false, false, crate::private::Internal); + pin_9.init_input(Pull::None, crate::private::Internal); pin_9.connect_input_to_peripheral(InputSignal::CAM_DATA_9, crate::private::Internal); - pin_10.init_input(false, false, crate::private::Internal); + pin_10.init_input(Pull::None, crate::private::Internal); pin_10.connect_input_to_peripheral(InputSignal::CAM_DATA_10, crate::private::Internal); - pin_11.init_input(false, false, crate::private::Internal); + pin_11.init_input(Pull::None, crate::private::Internal); pin_11.connect_input_to_peripheral(InputSignal::CAM_DATA_11, crate::private::Internal); - pin_12.init_input(false, false, crate::private::Internal); + pin_12.init_input(Pull::None, crate::private::Internal); pin_12.connect_input_to_peripheral(InputSignal::CAM_DATA_12, crate::private::Internal); - pin_13.init_input(false, false, crate::private::Internal); + pin_13.init_input(Pull::None, crate::private::Internal); pin_13.connect_input_to_peripheral(InputSignal::CAM_DATA_13, crate::private::Internal); - pin_14.init_input(false, false, crate::private::Internal); + pin_14.init_input(Pull::None, crate::private::Internal); pin_14.connect_input_to_peripheral(InputSignal::CAM_DATA_14, crate::private::Internal); - pin_15.init_input(false, false, crate::private::Internal); + pin_15.init_input(Pull::None, crate::private::Internal); pin_15.connect_input_to_peripheral(InputSignal::CAM_DATA_15, crate::private::Internal); Self { _pins: () } diff --git a/esp-hal/src/lcd_cam/lcd/i8080.rs b/esp-hal/src/lcd_cam/lcd/i8080.rs index 8539bd7a3e..37316afad9 100644 --- a/esp-hal/src/lcd_cam/lcd/i8080.rs +++ b/esp-hal/src/lcd_cam/lcd/i8080.rs @@ -76,7 +76,7 @@ use crate::{ ReadBuffer, TxPrivate, }, - gpio::{OutputPin, OutputSignal}, + gpio::{OutputSignal, PeripheralOutput}, lcd_cam::{ asynch::LcdDoneFuture, lcd::{i8080::private::TxPins, ClockMode, DelayMode, Phase, Polarity}, @@ -309,7 +309,7 @@ where } /// Associates a CS pin with the I8080 interface. - pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { + pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { crate::into_ref!(cs); cs.set_to_push_pull_output(crate::private::Internal); cs.connect_peripheral_to_output(OutputSignal::LCD_CS, crate::private::Internal); @@ -318,7 +318,7 @@ where } /// Configures the control pins for the I8080 interface. - pub fn with_ctrl_pins( + pub fn with_ctrl_pins( self, dc: impl Peripheral

+ 'd, wrx: impl Peripheral

+ 'd, @@ -593,14 +593,14 @@ pub struct TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7> { impl<'d, P0, P1, P2, P3, P4, P5, P6, P7> TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7> where - P0: OutputPin, - P1: OutputPin, - P2: OutputPin, - P3: OutputPin, - P4: OutputPin, - P5: OutputPin, - P6: OutputPin, - P7: OutputPin, + P0: PeripheralOutput, + P1: PeripheralOutput, + P2: PeripheralOutput, + P3: PeripheralOutput, + P4: PeripheralOutput, + P5: PeripheralOutput, + P6: PeripheralOutput, + P7: PeripheralOutput, { #[allow(clippy::too_many_arguments)] /// Creates a new `TxEightBits` instance with the provided output pins. @@ -638,14 +638,14 @@ where impl<'d, P0, P1, P2, P3, P4, P5, P6, P7> TxPins for TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7> where - P0: OutputPin, - P1: OutputPin, - P2: OutputPin, - P3: OutputPin, - P4: OutputPin, - P5: OutputPin, - P6: OutputPin, - P7: OutputPin, + P0: PeripheralOutput, + P1: PeripheralOutput, + P2: PeripheralOutput, + P3: PeripheralOutput, + P4: PeripheralOutput, + P5: PeripheralOutput, + P6: PeripheralOutput, + P7: PeripheralOutput, { type Word = u8; @@ -701,22 +701,22 @@ pub struct TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> where - P0: OutputPin, - P1: OutputPin, - P2: OutputPin, - P3: OutputPin, - P4: OutputPin, - P5: OutputPin, - P6: OutputPin, - P7: OutputPin, - P8: OutputPin, - P9: OutputPin, - P10: OutputPin, - P11: OutputPin, - P12: OutputPin, - P13: OutputPin, - P14: OutputPin, - P15: OutputPin, + P0: PeripheralOutput, + P1: PeripheralOutput, + P2: PeripheralOutput, + P3: PeripheralOutput, + P4: PeripheralOutput, + P5: PeripheralOutput, + P6: PeripheralOutput, + P7: PeripheralOutput, + P8: PeripheralOutput, + P9: PeripheralOutput, + P10: PeripheralOutput, + P11: PeripheralOutput, + P12: PeripheralOutput, + P13: PeripheralOutput, + P14: PeripheralOutput, + P15: PeripheralOutput, { #[allow(clippy::too_many_arguments)] /// Creates a new `TxSixteenBits` instance with the provided output pins. @@ -779,22 +779,22 @@ where impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> TxPins for TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> where - P0: OutputPin, - P1: OutputPin, - P2: OutputPin, - P3: OutputPin, - P4: OutputPin, - P5: OutputPin, - P6: OutputPin, - P7: OutputPin, - P8: OutputPin, - P9: OutputPin, - P10: OutputPin, - P11: OutputPin, - P12: OutputPin, - P13: OutputPin, - P14: OutputPin, - P15: OutputPin, + P0: PeripheralOutput, + P1: PeripheralOutput, + P2: PeripheralOutput, + P3: PeripheralOutput, + P4: PeripheralOutput, + P5: PeripheralOutput, + P6: PeripheralOutput, + P7: PeripheralOutput, + P8: PeripheralOutput, + P9: PeripheralOutput, + P10: PeripheralOutput, + P11: PeripheralOutput, + P12: PeripheralOutput, + P13: PeripheralOutput, + P14: PeripheralOutput, + P15: PeripheralOutput, { type Word = u16; fn configure(&mut self) { diff --git a/esp-hal/src/ledc/channel.rs b/esp-hal/src/ledc/channel.rs index a838fccc36..dd3bd18cd2 100644 --- a/esp-hal/src/ledc/channel.rs +++ b/esp-hal/src/ledc/channel.rs @@ -11,7 +11,7 @@ use super::timer::{TimerIFace, TimerSpeed}; use crate::{ - gpio::{OutputPin, OutputSignal}, + gpio::{OutputSignal, PeripheralOutput}, peripheral::{Peripheral, PeripheralRef}, peripherals::ledc::RegisterBlock, }; @@ -95,7 +95,7 @@ pub mod config { } /// Channel interface -pub trait ChannelIFace<'a, S: TimerSpeed + 'a, O: OutputPin + 'a> +pub trait ChannelIFace<'a, S: TimerSpeed + 'a, O: PeripheralOutput + 'a> where Channel<'a, S, O>: ChannelHW, { @@ -118,7 +118,7 @@ where } /// Channel HW interface -pub trait ChannelHW { +pub trait ChannelHW { /// Configure Channel HW except for the duty which is set via /// [`Self::set_duty_hw`]. fn configure_hw(&mut self) -> Result<(), Error>; @@ -144,14 +144,14 @@ pub trait ChannelHW { } /// Channel struct -pub struct Channel<'a, S: TimerSpeed, O: OutputPin> { +pub struct Channel<'a, S: TimerSpeed, O: PeripheralOutput> { ledc: &'a RegisterBlock, timer: Option<&'a dyn TimerIFace>, number: Number, output_pin: PeripheralRef<'a, O>, } -impl<'a, S: TimerSpeed, O: OutputPin> Channel<'a, S, O> { +impl<'a, S: TimerSpeed, O: PeripheralOutput> Channel<'a, S, O> { /// Return a new channel pub fn new(number: Number, output_pin: impl Peripheral

+ 'a) -> Self { crate::into_ref!(output_pin); @@ -165,7 +165,7 @@ impl<'a, S: TimerSpeed, O: OutputPin> Channel<'a, S, O> { } } -impl<'a, S: TimerSpeed, O: OutputPin> ChannelIFace<'a, S, O> for Channel<'a, S, O> +impl<'a, S: TimerSpeed, O: PeripheralOutput> ChannelIFace<'a, S, O> for Channel<'a, S, O> where Channel<'a, S, O>: ChannelHW, { @@ -337,7 +337,7 @@ mod ehal1 { } } -impl<'a, O: OutputPin, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> { +impl<'a, O: PeripheralOutput, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> { #[cfg(esp32)] fn set_channel(&mut self, timer_number: u8) { if S::IS_HS { @@ -537,7 +537,7 @@ impl<'a, O: OutputPin, S: crate::ledc::timer::TimerSpeed> Channel<'a, S, O> { impl<'a, O, S> ChannelHW for Channel<'a, S, O> where - O: OutputPin, + O: PeripheralOutput, S: crate::ledc::timer::TimerSpeed, { /// Configure Channel HW @@ -604,6 +604,7 @@ where #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))] Number::Channel7 => OutputSignal::LEDC_LS_SIG7, }; + self.output_pin .connect_peripheral_to_output(signal, crate::private::Internal); } else { diff --git a/esp-hal/src/mcpwm/operator.rs b/esp-hal/src/mcpwm/operator.rs index 8f4a153631..31d7e55fb7 100644 --- a/esp-hal/src/mcpwm/operator.rs +++ b/esp-hal/src/mcpwm/operator.rs @@ -12,7 +12,7 @@ use core::marker::PhantomData; use crate::{ - gpio::OutputPin, + gpio::PeripheralOutput, mcpwm::{timer::Timer, PwmPeripheral}, peripheral::{Peripheral, PeripheralRef}, private, @@ -204,7 +204,7 @@ impl Operator { } /// Use the A output with the given pin and configuration - pub fn with_pin_a<'d, Pin: OutputPin>( + pub fn with_pin_a<'d, Pin: PeripheralOutput>( self, pin: impl Peripheral

+ 'd, config: PwmPinConfig, @@ -213,7 +213,7 @@ impl Operator { } /// Use the B output with the given pin and configuration - pub fn with_pin_b<'d, Pin: OutputPin>( + pub fn with_pin_b<'d, Pin: PeripheralOutput>( self, pin: impl Peripheral

+ 'd, config: PwmPinConfig, @@ -222,7 +222,7 @@ impl Operator { } /// Use both the A and the B output with the given pins and configurations - pub fn with_pins<'d, PinA: OutputPin, PinB: OutputPin>( + pub fn with_pins<'d, PinA: PeripheralOutput, PinB: PeripheralOutput>( self, pin_a: impl Peripheral

+ 'd, config_a: PwmPinConfig, @@ -239,7 +239,7 @@ impl Operator { /// /// This is useful for complementary or mirrored signals with or without /// configured deadtime - pub fn with_linked_pins<'d, PinA: OutputPin, PinB: OutputPin>( + pub fn with_linked_pins<'d, PinA: PeripheralOutput, PinB: PeripheralOutput>( self, pin_a: impl Peripheral

+ 'd, config_a: PwmPinConfig, @@ -288,7 +288,7 @@ pub struct PwmPin<'d, Pin, PWM, const OP: u8, const IS_A: bool> { phantom: PhantomData, } -impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> +impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, Pin, PWM, OP, IS_A> { fn new(pin: impl Peripheral

+ 'd, config: PwmPinConfig) -> Self { @@ -304,6 +304,7 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> pin.pin .connect_peripheral_to_output(output_signal, private::Internal); pin.pin.enable_output(true, private::Internal); + pin } @@ -414,8 +415,8 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> } } -impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> embedded_hal_02::PwmPin - for PwmPin<'d, Pin, PWM, OP, IS_A> +impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> + embedded_hal_02::PwmPin for PwmPin<'d, Pin, PWM, OP, IS_A> { type Duty = u16; @@ -448,14 +449,14 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> emb } /// Implement no error type for the PwmPin because the method are infallible -impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> +impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> embedded_hal::pwm::ErrorType for PwmPin<'d, Pin, PWM, OP, IS_A> { type Error = core::convert::Infallible; } /// Implement the trait SetDutyCycle for PwmPin -impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> +impl<'d, Pin: PeripheralOutput, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> embedded_hal::pwm::SetDutyCycle for PwmPin<'d, Pin, PWM, OP, IS_A> { /// Get the max duty of the PwmPin @@ -522,7 +523,7 @@ pub struct LinkedPins<'d, PinA, PinB, PWM, const OP: u8> { pin_b: PwmPin<'d, PinB, PWM, OP, false>, } -impl<'d, PinA: OutputPin, PinB: OutputPin, PWM: PwmPeripheral, const OP: u8> +impl<'d, PinA: PeripheralOutput, PinB: PeripheralOutput, PWM: PwmPeripheral, const OP: u8> LinkedPins<'d, PinA, PinB, PWM, OP> { fn new( diff --git a/esp-hal/src/otg_fs.rs b/esp-hal/src/otg_fs.rs index 22a4c9b0fe..4883daa152 100644 --- a/esp-hal/src/otg_fs.rs +++ b/esp-hal/src/otg_fs.rs @@ -43,6 +43,7 @@ use crate::{ gpio::InputSignal, peripheral::{Peripheral, PeripheralRef}, peripherals, + private::Internal, system::{Peripheral as PeripheralEnable, PeripheralClockControl}, }; @@ -101,10 +102,12 @@ impl<'d> Usb<'d> { .modify(|_, w| w.sw_hw_usb_phy_sel().set_bit().sw_usb_phy_sel().set_bit()); } - crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_IDDIG); // connected connector is mini-B side - crate::gpio::connect_high_to_peripheral(InputSignal::USB_SRP_BVALID); // HIGH to force USB device mode - crate::gpio::connect_high_to_peripheral(InputSignal::USB_OTG_VBUSVALID); // receiving a valid Vbus from device - crate::gpio::connect_low_to_peripheral(InputSignal::USB_OTG_AVALID); + use crate::gpio::{Level, PeripheralInput}; + + Level::High.connect_input_to_peripheral(InputSignal::USB_OTG_IDDIG, Internal); // connected connector is mini-B side + Level::High.connect_input_to_peripheral(InputSignal::USB_SRP_BVALID, Internal); // HIGH to force USB device mode + Level::High.connect_input_to_peripheral(InputSignal::USB_OTG_VBUSVALID, Internal); // receiving a valid Vbus from device + Level::Low.connect_input_to_peripheral(InputSignal::USB_OTG_AVALID, Internal); } } diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 4105acb19b..0be79817c8 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -49,7 +49,7 @@ use crate::{ TxPrivate, WriteBuffer, }, - gpio::{InputPin, OutputPin}, + gpio::{PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{self, Peripheral}, peripherals, @@ -279,13 +279,13 @@ pub fn no_clk_pin() -> &'static mut NoClkPin { /// Wraps a GPIO pin which will be used as the clock output signal pub struct ClkOutPin<'d, P> where - P: OutputPin, + P: PeripheralOutput, { pin: PeripheralRef<'d, P>, } impl<'d, P> ClkOutPin<'d, P> where - P: OutputPin, + P: PeripheralOutput, { /// Create a ClkOutPin pub fn new(pin: impl Peripheral

+ 'd) -> Self { @@ -295,7 +295,7 @@ where } impl<'d, P> TxClkPin for ClkOutPin<'d, P> where - P: OutputPin, + P: PeripheralOutput, { fn configure(&mut self) { self.pin.set_to_push_pull_output(crate::private::Internal); @@ -309,13 +309,13 @@ where /// Wraps a GPIO pin which will be used as the TX clock input signal pub struct ClkInPin<'d, P> where - P: InputPin, + P: PeripheralInput, { pin: PeripheralRef<'d, P>, } impl<'d, P> ClkInPin<'d, P> where - P: InputPin, + P: PeripheralInput, { /// Create a new ClkInPin pub fn new(pin: impl Peripheral

+ 'd) -> Self { @@ -325,14 +325,15 @@ where } impl<'d, P> TxClkPin for ClkInPin<'d, P> where - P: InputPin, + P: PeripheralInput, { fn configure(&mut self) { let pcr = unsafe { &*crate::peripherals::PCR::PTR }; pcr.parl_clk_tx_conf() .modify(|_, w| unsafe { w.parl_clk_tx_sel().bits(3).parl_clk_tx_div_num().bits(0) }); // PAD_CLK_TX, no divider - self.pin.init_input(false, false, crate::private::Internal); + self.pin + .init_input(crate::gpio::Pull::None, crate::private::Internal); self.pin.connect_input_to_peripheral( crate::gpio::InputSignal::PARL_TX_CLK, crate::private::Internal, @@ -343,14 +344,14 @@ where /// Wraps a GPIO pin which will be used as the RX clock input signal pub struct RxClkInPin<'d, P> where - P: InputPin, + P: PeripheralInput, { pin: PeripheralRef<'d, P>, sample_edge: SampleEdge, } impl<'d, P> RxClkInPin<'d, P> where - P: InputPin, + P: PeripheralInput, { /// Create a new RxClkInPin pub fn new(pin: impl Peripheral

+ 'd, sample_edge: SampleEdge) -> Self { @@ -360,14 +361,15 @@ where } impl<'d, P> RxClkPin for RxClkInPin<'d, P> where - P: InputPin, + P: PeripheralInput, { fn configure(&mut self) { let pcr = unsafe { &*crate::peripherals::PCR::PTR }; pcr.parl_clk_rx_conf() .modify(|_, w| unsafe { w.parl_clk_rx_sel().bits(3).parl_clk_rx_div_num().bits(0) }); // PAD_CLK_TX, no divider - self.pin.init_input(false, false, crate::private::Internal); + self.pin + .init_input(crate::gpio::Pull::None, crate::private::Internal); self.pin.connect_input_to_peripheral( crate::gpio::InputSignal::PARL_RX_CLK, crate::private::Internal, @@ -381,7 +383,7 @@ where pub struct TxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + TxPins + ConfigurePins, - VP: OutputPin, + VP: PeripheralOutput, { tx_pins: P, valid_pin: PeripheralRef<'d, VP>, @@ -390,7 +392,7 @@ where impl<'d, P, VP> TxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + TxPins + ConfigurePins, - VP: OutputPin, + VP: PeripheralOutput, { /// Create a [TxPinConfigWithValidPin] pub fn new(tx_pins: P, valid_pin: impl Peripheral

+ 'd) -> Self { @@ -402,14 +404,14 @@ where impl<'d, P, VP> TxPins for TxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + TxPins + ConfigurePins, - VP: OutputPin, + VP: PeripheralOutput, { } impl<'d, P, VP> ConfigurePins for TxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + TxPins + ConfigurePins, - VP: OutputPin, + VP: PeripheralOutput, { fn configure(&mut self) -> Result<(), Error> { self.tx_pins.configure()?; @@ -472,7 +474,7 @@ macro_rules! tx_pins { impl<'d, $($pin),+> $name<'d, $($pin),+> where - $($pin: OutputPin),+ + $($pin: PeripheralOutput),+ { /// Create a new TX pin #[allow(clippy::too_many_arguments)] @@ -488,7 +490,7 @@ macro_rules! tx_pins { impl<'d, $($pin),+> ConfigurePins for $name<'d, $($pin),+> where - $($pin: OutputPin),+ + $($pin: PeripheralOutput),+ { fn configure(&mut self) -> Result<(), Error>{ $( @@ -590,7 +592,7 @@ impl<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> pub struct RxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + RxPins + ConfigurePins, - VP: InputPin, + VP: PeripheralInput, { rx_pins: P, valid_pin: PeripheralRef<'d, VP>, @@ -601,7 +603,7 @@ where impl<'d, P, VP> RxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + RxPins + ConfigurePins, - VP: InputPin, + VP: PeripheralInput, { /// Create a new [RxPinConfigWithValidPin] pub fn new( @@ -623,19 +625,19 @@ where impl<'d, P, VP> RxPins for RxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + RxPins + ConfigurePins, - VP: InputPin, + VP: PeripheralInput, { } impl<'d, P, VP> ConfigurePins for RxPinConfigWithValidPin<'d, P, VP> where P: NotContainsValidSignalPin + RxPins + ConfigurePins, - VP: InputPin, + VP: PeripheralInput, { fn configure(&mut self) -> Result<(), Error> { self.rx_pins.configure()?; self.valid_pin - .init_input(false, false, crate::private::Internal); + .init_input(crate::gpio::Pull::None, crate::private::Internal); self.valid_pin .connect_input_to_peripheral(Instance::rx_valid_pin_signal(), crate::private::Internal); Instance::set_rx_sw_en(false); @@ -719,7 +721,7 @@ macro_rules! rx_pins { impl<'d, $($pin),+> $name<'d, $($pin),+> where - $($pin: InputPin),+ + $($pin: PeripheralInput),+ { /// Create a new RX pin #[allow(clippy::too_many_arguments)] @@ -735,12 +737,12 @@ macro_rules! rx_pins { impl<'d, $($pin),+> ConfigurePins for $name<'d, $($pin),+> where - $($pin: InputPin),+ + $($pin: PeripheralInput),+ { fn configure(&mut self) -> Result<(), Error> { $( - self.[< pin_ $pin:lower >].init_input(false, false, $crate::private::Internal); - self.[< pin_ $pin:lower >].connect_input_to_peripheral(crate::gpio::InputSignal::$signal, $crate::private::Internal); + self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None, crate::private::Internal); + self.[< pin_ $pin:lower >].connect_input_to_peripheral(crate::gpio::InputSignal::$signal, crate::private::Internal); )+ private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]); diff --git a/esp-hal/src/pcnt/channel.rs b/esp-hal/src/pcnt/channel.rs index d0a2782486..6a0b13862e 100644 --- a/esp-hal/src/pcnt/channel.rs +++ b/esp-hal/src/pcnt/channel.rs @@ -9,11 +9,7 @@ use core::marker::PhantomData; -use crate::{ - gpio::{InputPin, InputSignal, Pull, ONE_INPUT, ZERO_INPUT}, - peripheral::Peripheral, - peripherals::GPIO, -}; +use crate::gpio::{interconnect::AnyInputSignal, InputSignal, PeripheralInput, Pull}; /// Configuration for an PCNT input pin #[derive(Clone, Copy, Debug)] @@ -32,55 +28,19 @@ impl Default for PcntInputConfig { pub use crate::peripherals::pcnt::unit::conf0::{CTRL_MODE as CtrlMode, EDGE_MODE as EdgeMode}; /// PcntPin can be always high, always low, or an actual pin -#[derive(Clone, Copy)] +#[derive(Clone)] pub struct PcntSource { - source: u8, - inverted: bool, + source: AnyInputSignal, } impl PcntSource { /// Creates a `PcntSource` from an input pin with the specified /// configuration. - pub fn from_pin<'a, P: InputPin>( - pin: impl Peripheral

+ 'a, - pin_config: PcntInputConfig, - ) -> Self { - crate::into_ref!(pin); + pub fn from(source: impl Into, pin_config: PcntInputConfig) -> Self { + let source = source.into(); + source.init_input(pin_config.pull, crate::private::Internal); - pin.init_input( - pin_config.pull == Pull::Down, - pin_config.pull == Pull::Up, - crate::private::Internal, - ); - - Self { - source: pin.number(crate::private::Internal), - inverted: false, - } - } - - /// Creates a `PcntSource` that is always high. - pub fn always_high() -> Self { - Self { - source: ONE_INPUT, - inverted: false, - } - } - - /// Creates a `PcntSource` that is always low. - pub fn always_low() -> Self { - Self { - source: ZERO_INPUT, - inverted: false, - } - } - - /// Inverts the `PcntSource` signal. - pub fn invert(self) -> Self { - Self { - source: self.source, - inverted: !self.inverted, - } + Self { source } } } @@ -135,7 +95,7 @@ impl<'d, const UNIT: usize, const NUM: usize> Channel<'d, UNIT, NUM> { } /// Set the control signal (pin/high/low) for this channel - pub fn set_ctrl_signal(&self, source: PcntSource) -> &Self { + pub fn set_ctrl_signal(&self, mut source: PcntSource) -> &Self { let signal = match UNIT { 0 => match NUM { 0 => InputSignal::PCNT0_CTRL_CH0, @@ -185,19 +145,15 @@ impl<'d, const UNIT: usize, const NUM: usize> Channel<'d, UNIT, NUM> { }; if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize { - unsafe { &*GPIO::PTR } - .func_in_sel_cfg(signal as usize) - .modify(|_, w| unsafe { - w.sel().set_bit(); - w.in_inv_sel().bit(source.inverted); - w.in_sel().bits(source.source) - }); + source + .source + .connect_input_to_peripheral(signal, crate::private::Internal); } self } /// Set the edge signal (pin/high/low) for this channel - pub fn set_edge_signal(&self, source: PcntSource) -> &Self { + pub fn set_edge_signal(&self, mut source: PcntSource) -> &Self { let signal = match UNIT { 0 => match NUM { 0 => InputSignal::PCNT0_SIG_CH0, @@ -247,13 +203,9 @@ impl<'d, const UNIT: usize, const NUM: usize> Channel<'d, UNIT, NUM> { }; if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize { - unsafe { &*GPIO::PTR } - .func_in_sel_cfg(signal as usize) - .modify(|_, w| unsafe { - w.sel().set_bit(); - w.in_inv_sel().bit(source.inverted); - w.in_sel().bits(source.source) - }); + source + .source + .connect_input_to_peripheral(signal, crate::private::Internal); } self } diff --git a/esp-hal/src/peripheral.rs b/esp-hal/src/peripheral.rs index 3f56ab9a3f..2f1a966c0c 100644 --- a/esp-hal/src/peripheral.rs +++ b/esp-hal/src/peripheral.rs @@ -35,10 +35,10 @@ use core::{ /// dedicated struct is memory efficiency: /// /// Peripheral singletons are typically either zero-sized (for concrete -/// peripherals like `PA9` or `Spi4`) or very small (for example `AnyPin` which -/// is 1 byte). However `&mut T` is always 4 bytes for 32-bit targets, even if T -/// is zero-sized. PeripheralRef stores a copy of `T` instead, so it's the same -/// size. +/// peripherals like `PA9` or `Spi4`) or very small (for example `AnyPin` +/// which is 1 byte). However `&mut T` is always 4 bytes for 32-bit targets, +/// even if T is zero-sized. PeripheralRef stores a copy of `T` instead, so it's +/// the same size. /// /// but it is the size of `T` not the size /// of a pointer. This is useful if T is a zero sized type. diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index 7ea901626c..fcd765c077 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -85,7 +85,7 @@ use core::marker::PhantomData; use fugit::HertzU32; use crate::{ - gpio::{InputPin, OutputPin}, + gpio::{PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::Peripheral, rmt::private::CreateInstance, @@ -295,10 +295,77 @@ impl<'d> Rmt<'d, crate::Async> { } } +fn configure_rx_channel< + 'd, + P: PeripheralInput, + T: private::RxChannelInternal, + M: crate::Mode, +>( + pin: impl Peripheral

+ 'd, + config: RxChannelConfig, +) -> Result { + if config.filter_threshold > 0b111_1111 { + return Err(Error::InvalidArgument); + } + + cfg_if::cfg_if! { + if #[cfg(any(esp32, esp32s2))] { + let threshold = 0b111_1111_1111_1111; + } else { + let threshold = 0b11_1111_1111_1111; + } + } + + if config.idle_threshold > threshold { + return Err(Error::InvalidArgument); + } + + crate::into_ref!(pin); + pin.init_input(crate::gpio::Pull::None, crate::private::Internal); + pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal); + + T::set_divider(config.clk_divider); + T::set_carrier( + config.carrier_modulation, + config.carrier_high, + config.carrier_low, + config.carrier_level, + ); + T::set_filter_threshold(config.filter_threshold); + T::set_idle_threshold(config.idle_threshold); + + Ok(T::new()) +} + +fn configure_tx_channel< + 'd, + P: PeripheralOutput, + T: private::TxChannelInternal, + M: crate::Mode, +>( + pin: impl Peripheral

+ 'd, + config: TxChannelConfig, +) -> Result { + crate::into_ref!(pin); + pin.set_to_push_pull_output(crate::private::Internal); + pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal); + + T::set_divider(config.clk_divider); + T::set_carrier( + config.carrier_modulation, + config.carrier_high, + config.carrier_low, + config.carrier_level, + ); + T::set_idle_output(config.idle_output, config.idle_output_level); + + Ok(T::new()) +} + /// Creates a TX channel pub trait TxChannelCreator<'d, T, P> where - P: OutputPin, + P: PeripheralOutput, T: TxChannel, { /// Configure the TX channel @@ -310,26 +377,14 @@ where where Self: Sized, { - crate::into_ref!(pin); - pin.set_to_push_pull_output(crate::private::Internal); - pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal); - T::set_divider(config.clk_divider); - T::set_carrier( - config.carrier_modulation, - config.carrier_high, - config.carrier_low, - config.carrier_level, - ); - T::set_idle_output(config.idle_output, config.idle_output_level); - - Ok(T::new()) + configure_tx_channel(pin, config) } } /// Creates a TX channel in async mode pub trait TxChannelCreatorAsync<'d, T, P> where - P: OutputPin, + P: PeripheralOutput, T: TxChannelAsync, { /// Configure the TX channel @@ -341,26 +396,14 @@ where where Self: Sized, { - crate::into_ref!(pin); - pin.set_to_push_pull_output(crate::private::Internal); - pin.connect_peripheral_to_output(T::output_signal(), crate::private::Internal); - T::set_divider(config.clk_divider); - T::set_carrier( - config.carrier_modulation, - config.carrier_high, - config.carrier_low, - config.carrier_level, - ); - T::set_idle_output(config.idle_output, config.idle_output_level); - - Ok(T::new()) + configure_tx_channel(pin, config) } } /// Creates a RX channel pub trait RxChannelCreator<'d, T, P> where - P: InputPin, + P: PeripheralInput, T: RxChannel, { /// Configure the RX channel @@ -372,41 +415,14 @@ where where Self: Sized, { - if config.filter_threshold > 0b111_1111 { - return Err(Error::InvalidArgument); - } - - #[cfg(any(esp32, esp32s2))] - if config.idle_threshold > 0b111_1111_1111_1111 { - return Err(Error::InvalidArgument); - } - - #[cfg(not(any(esp32, esp32s2)))] - if config.idle_threshold > 0b11_1111_1111_1111 { - return Err(Error::InvalidArgument); - } - - crate::into_ref!(pin); - pin.init_input(false, false, crate::private::Internal); - pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal); - T::set_divider(config.clk_divider); - T::set_carrier( - config.carrier_modulation, - config.carrier_high, - config.carrier_low, - config.carrier_level, - ); - T::set_filter_threshold(config.filter_threshold); - T::set_idle_threshold(config.idle_threshold); - - Ok(T::new()) + configure_rx_channel(pin, config) } } /// Creates a RX channel in async mode pub trait RxChannelCreatorAsync<'d, T, P> where - P: InputPin, + P: PeripheralInput, T: RxChannelAsync, { /// Configure the RX channel @@ -418,34 +434,7 @@ where where Self: Sized, { - if config.filter_threshold > 0b111_1111 { - return Err(Error::InvalidArgument); - } - - #[cfg(any(esp32, esp32s2))] - if config.idle_threshold > 0b111_1111_1111_1111 { - return Err(Error::InvalidArgument); - } - - #[cfg(not(any(esp32, esp32s2)))] - if config.idle_threshold > 0b11_1111_1111_1111 { - return Err(Error::InvalidArgument); - } - - crate::into_ref!(pin); - pin.init_input(false, false, crate::private::Internal); - pin.connect_input_to_peripheral(T::input_signal(), crate::private::Internal); - T::set_divider(config.clk_divider); - T::set_carrier( - config.carrier_modulation, - config.carrier_high, - config.carrier_low, - config.carrier_level, - ); - T::set_filter_threshold(config.filter_threshold); - T::set_idle_threshold(config.idle_threshold); - - Ok(T::new()) + configure_rx_channel(pin, config) } } @@ -586,7 +575,7 @@ macro_rules! impl_tx_channel_creator { impl<'d, P> $crate::rmt::TxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P> for ChannelCreator<$crate::Blocking, $channel> where - P: $crate::gpio::OutputPin, + P: $crate::gpio::PeripheralOutput, { } @@ -595,7 +584,7 @@ macro_rules! impl_tx_channel_creator { impl<'d, P> $crate::rmt::TxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P> for ChannelCreator<$crate::Async, $channel> where - P: $crate::gpio::OutputPin, + P: $crate::gpio::PeripheralOutput, { } @@ -608,7 +597,7 @@ macro_rules! impl_rx_channel_creator { impl<'d, P> $crate::rmt::RxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P> for ChannelCreator<$crate::Blocking, $channel> where - P: $crate::gpio::InputPin, + P: $crate::gpio::PeripheralInput, { } @@ -617,7 +606,7 @@ macro_rules! impl_rx_channel_creator { impl<'d, P> $crate::rmt::RxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P> for ChannelCreator<$crate::Async, $channel> where - P: $crate::gpio::InputPin, + P: $crate::gpio::PeripheralInput, { } diff --git a/esp-hal/src/spi/master.rs b/esp-hal/src/spi/master.rs index 6943ddeccd..e62b0588e6 100644 --- a/esp-hal/src/spi/master.rs +++ b/esp-hal/src/spi/master.rs @@ -82,7 +82,7 @@ use super::{ use crate::{ clock::Clocks, dma::{DmaPeripheral, DmaRxBuffer, DmaTxBuffer, Rx, Tx}, - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, @@ -457,6 +457,35 @@ pub struct Spi<'d, T, M> { _mode: PhantomData, } +impl<'d, T, M> Spi<'d, T, M> +where + T: Instance, +{ + /// Assign the SCK (Serial Clock) pin for the SPI instance. + /// + /// Sets the specified pin to push-pull output and connects it to the SPI + /// clock signal. + pub fn with_sck(self, sclk: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(sclk); + sclk.set_to_push_pull_output(private::Internal); + sclk.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); + + self + } + + /// Assign the CS (Chip Select) pin for the SPI instance. + /// + /// Sets the specified pin to push-pull output and connects it to the SPI CS + /// signal. + pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(cs); + cs.set_to_push_pull_output(private::Internal); + cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); + + self + } +} + impl<'d, T> Spi<'d, T, FullDuplexMode> where T: Instance, @@ -513,23 +542,11 @@ where Self::new_internal(spi, frequency, mode) } - /// Assign the SCK (Serial Clock) pin for the SPI instance. - /// - /// Sets the specified pin to push-pull output and connects it to the SPI - /// clock signal. - pub fn with_sck(self, sck: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(sck); - sck.set_to_push_pull_output(private::Internal); - sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); - - self - } - /// Assign the MOSI (Master Out Slave In) pin for the SPI instance. /// /// Sets the specified pin to push-pull output and connects it to the SPI /// MOSI signal. - pub fn with_mosi(self, mosi: impl Peripheral

+ 'd) -> Self { + pub fn with_mosi(self, mosi: impl Peripheral

+ 'd) -> Self { crate::into_ref!(mosi); mosi.set_to_push_pull_output(private::Internal); mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); @@ -540,26 +557,14 @@ where /// Assign the MISO (Master In Slave Out) pin for the SPI instance. /// /// Sets the specified pin to input and connects it to the SPI MISO signal. - pub fn with_miso(self, miso: impl Peripheral

+ 'd) -> Self { + pub fn with_miso(self, miso: impl Peripheral

+ 'd) -> Self { crate::into_ref!(miso); - miso.init_input(false, false, private::Internal); + miso.init_input(crate::gpio::Pull::None, private::Internal); miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); self } - /// Assign the CS (Chip Select) pin for the SPI instance. - /// - /// Sets the specified pin to push-pull output and connects it to the SPI CS - /// signal. - pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(cs); - cs.set_to_push_pull_output(private::Internal); - cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); - - self - } - /// Set the bit order for the SPI instance. /// /// The default is MSB first for both read and write. @@ -572,38 +577,43 @@ where /// /// All pins are optional. Pass [crate::gpio::NO_PIN] if you don't need the /// given pin. - pub fn with_pins( + pub fn with_pins< + SCK: PeripheralOutput, + MOSI: PeripheralOutput, + MISO: PeripheralInput, + CS: PeripheralOutput, + >( self, sck: Option + 'd>, mosi: Option + 'd>, miso: Option + 'd>, cs: Option + 'd>, ) -> Self { - if let Some(sck) = sck { - crate::into_ref!(sck); - sck.set_to_push_pull_output(private::Internal); - sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); - } + let this = if let Some(sck) = sck { + self.with_sck(sck) + } else { + self + }; - if let Some(mosi) = mosi { - crate::into_ref!(mosi); - mosi.set_to_push_pull_output(private::Internal); - mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); - } + let this = if let Some(mosi) = mosi { + this.with_mosi(mosi) + } else { + this + }; - if let Some(miso) = miso { - crate::into_ref!(miso); - miso.init_input(false, false, private::Internal); - miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); - } + let this = if let Some(miso) = miso { + this.with_miso(miso) + } else { + this + }; - if let Some(cs) = cs { - crate::into_ref!(cs); - cs.set_to_push_pull_output(private::Internal); - cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); - } + let this = if let Some(cs) = cs { + this.with_cs(cs) + } else { + this + }; - self + this } pub(crate) fn new_internal( @@ -651,32 +661,21 @@ where Self::new_internal(spi, frequency, mode) } - /// Assign the SCK (Serial Clock) pin for the SPI instance. - /// - /// Sets the specified pin to push-pull output and connects it to the SPI - /// clock signal. - pub fn with_sck(self, sck: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(sck); - sck.set_to_push_pull_output(private::Internal); - sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); - - self - } - /// Assign the MOSI (Master Out Slave In) pin for the SPI instance in /// half-duplex mode. /// /// Enables both input and output functionality for the pin, and connects it /// to the MOSI signal and SIO0 input signal. - pub fn with_mosi( + pub fn with_mosi( self, mosi: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(mosi); - mosi.enable_output(true, private::Internal); - mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); mosi.enable_input(true, private::Internal); + mosi.enable_output(true, private::Internal); + mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal); + mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); self } @@ -686,15 +685,16 @@ where /// /// Enables both input and output functionality for the pin, and connects it /// to the MISO signal and SIO1 input signal. - pub fn with_miso( + pub fn with_miso( self, miso: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(miso); - miso.enable_output(true, private::Internal); - miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); miso.enable_input(true, private::Internal); + miso.enable_output(true, private::Internal); + miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); + miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); self } @@ -703,15 +703,16 @@ where /// /// Enables both input and output functionality for the pin, and connects it /// to the SIO2 output and input signals. - pub fn with_sio2( + pub fn with_sio2( self, sio2: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(sio2); - sio2.enable_output(true, private::Internal); - sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal); sio2.enable_input(true, private::Internal); + sio2.enable_output(true, private::Internal); + sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal); + sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal); self } @@ -720,27 +721,16 @@ where /// /// Enables both input and output functionality for the pin, and connects it /// to the SIO3 output and input signals. - pub fn with_sio3( + pub fn with_sio3( self, sio3: impl Peripheral

+ 'd, ) -> Self { crate::into_ref!(sio3); - sio3.enable_output(true, private::Internal); - sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal); sio3.enable_input(true, private::Internal); - sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal); - - self - } + sio3.enable_output(true, private::Internal); - /// Assign the CS (Chip Select) pin for the SPI instance. - /// - /// Sets the specified pin to push-pull output and connects it to the SPI CS - /// signal. - pub fn with_cs(self, cs: impl Peripheral

+ 'd) -> Self { - crate::into_ref!(cs); - cs.set_to_push_pull_output(private::Internal); - cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); + sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal); + sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal); self } @@ -750,12 +740,12 @@ where /// All pins are optional. Pass [crate::gpio::NO_PIN] if you don't need the /// given pin. pub fn with_pins< - SCK: OutputPin, - MOSI: OutputPin + InputPin, - MISO: OutputPin + InputPin, - SIO2: OutputPin + InputPin, - SIO3: OutputPin + InputPin, - CS: OutputPin, + SCK: PeripheralOutput, + MOSI: PeripheralOutput + PeripheralInput, + MISO: PeripheralOutput + PeripheralInput, + SIO2: PeripheralOutput + PeripheralInput, + SIO3: PeripheralOutput + PeripheralInput, + CS: PeripheralOutput, >( self, sck: Option + 'd>, @@ -765,51 +755,43 @@ where sio3: Option + 'd>, cs: Option + 'd>, ) -> Self { - if let Some(sck) = sck { - crate::into_ref!(sck); - sck.set_to_push_pull_output(private::Internal); - sck.connect_peripheral_to_output(self.spi.sclk_signal(), private::Internal); - } + let this = if let Some(sck) = sck { + self.with_sck(sck) + } else { + self + }; - if let Some(mosi) = mosi { - crate::into_ref!(mosi); - mosi.enable_output(true, private::Internal); - mosi.connect_peripheral_to_output(self.spi.mosi_signal(), private::Internal); - mosi.enable_input(true, private::Internal); - mosi.connect_input_to_peripheral(self.spi.sio0_input_signal(), private::Internal); - } + let this = if let Some(mosi) = mosi { + this.with_mosi(mosi) + } else { + this + }; - if let Some(miso) = miso { - crate::into_ref!(miso); - miso.enable_output(true, private::Internal); - miso.connect_peripheral_to_output(self.spi.sio1_output_signal(), private::Internal); - miso.enable_input(true, private::Internal); - miso.connect_input_to_peripheral(self.spi.miso_signal(), private::Internal); - } + let this = if let Some(miso) = miso { + this.with_miso(miso) + } else { + this + }; - if let Some(sio2) = sio2 { - crate::into_ref!(sio2); - sio2.enable_output(true, private::Internal); - sio2.connect_peripheral_to_output(self.spi.sio2_output_signal(), private::Internal); - sio2.enable_input(true, private::Internal); - sio2.connect_input_to_peripheral(self.spi.sio2_input_signal(), private::Internal); - } + let this = if let Some(sio2) = sio2 { + this.with_sio2(sio2) + } else { + this + }; - if let Some(sio3) = sio3 { - crate::into_ref!(sio3); - sio3.enable_output(true, private::Internal); - sio3.connect_peripheral_to_output(self.spi.sio3_output_signal(), private::Internal); - sio3.enable_input(true, private::Internal); - sio3.connect_input_to_peripheral(self.spi.sio3_input_signal(), private::Internal); - } + let this = if let Some(sio3) = sio3 { + this.with_sio3(sio3) + } else { + this + }; - if let Some(cs) = cs { - crate::into_ref!(cs); - cs.set_to_push_pull_output(private::Internal); - cs.connect_peripheral_to_output(self.spi.cs_signal(), private::Internal); - } + let this = if let Some(cs) = cs { + this.with_cs(cs) + } else { + this + }; - self + this } pub(crate) fn new_internal( diff --git a/esp-hal/src/spi/slave.rs b/esp-hal/src/spi/slave.rs index 3a915d7f41..ca3d1ed2f6 100644 --- a/esp-hal/src/spi/slave.rs +++ b/esp-hal/src/spi/slave.rs @@ -73,7 +73,7 @@ use core::marker::PhantomData; use super::{Error, FullDuplexMode, SpiMode}; use crate::{ dma::{DescriptorChain, DmaPeripheral, Rx, Tx}, - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, peripheral::{Peripheral, PeripheralRef}, peripherals::spi2::RegisterBlock, private, @@ -106,25 +106,31 @@ where T: Instance, { /// Constructs an SPI instance in 8bit dataframe mode. - pub fn new( + pub fn new< + SCK: PeripheralInput, + MOSI: PeripheralInput, + MISO: PeripheralOutput, + CS: PeripheralInput, + >( spi: impl Peripheral

+ 'd, - sck: impl Peripheral

+ 'd, + sclk: impl Peripheral

+ 'd, mosi: impl Peripheral

+ 'd, miso: impl Peripheral

+ 'd, cs: impl Peripheral

+ 'd, mode: SpiMode, ) -> Spi<'d, T, FullDuplexMode> { - crate::into_ref!(spi, sck, mosi, miso, cs); - sck.init_input(false, false, private::Internal); - sck.connect_input_to_peripheral(spi.sclk_signal(), private::Internal); + crate::into_ref!(spi, sclk, mosi, miso, cs); - mosi.init_input(false, false, private::Internal); + sclk.init_input(Pull::None, private::Internal); + sclk.connect_input_to_peripheral(spi.sclk_signal(), private::Internal); + + mosi.init_input(Pull::None, private::Internal); mosi.connect_input_to_peripheral(spi.mosi_signal(), private::Internal); miso.set_to_push_pull_output(private::Internal); miso.connect_peripheral_to_output(spi.miso_signal(), private::Internal); - cs.init_input(false, false, private::Internal); + cs.init_input(Pull::None, private::Internal); cs.connect_input_to_peripheral(spi.cs_signal(), private::Internal); Self::new_internal(spi, mode) @@ -148,7 +154,7 @@ where } } -/// DMA (Direct Memory Access) funtionality (Slave). +/// DMA (Direct Memory Access) functionality (Slave). pub mod dma { use super::*; #[cfg(spi3)] diff --git a/esp-hal/src/twai/mod.rs b/esp-hal/src/twai/mod.rs index c8e3d943c3..30c451cd1a 100644 --- a/esp-hal/src/twai/mod.rs +++ b/esp-hal/src/twai/mod.rs @@ -133,7 +133,7 @@ use core::marker::PhantomData; use self::filter::{Filter, FilterType}; use crate::{ - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::twai0::RegisterBlock, @@ -716,7 +716,7 @@ where T: Instance, DM: crate::Mode, { - fn new_internal( + fn new_internal( _peripheral: impl Peripheral

+ 'd, rx_pin: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, @@ -736,13 +736,15 @@ where .mode() .write(|w| w.reset_mode().set_bit()); + rx_pin.init_input(Pull::None, crate::private::Internal); + rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL, crate::private::Internal); + if no_transceiver { tx_pin.set_to_open_drain_output(crate::private::Internal); + } else { + tx_pin.set_to_push_pull_output(crate::private::Internal); } - tx_pin.set_to_push_pull_output(crate::private::Internal); tx_pin.connect_peripheral_to_output(T::OUTPUT_SIGNAL, crate::private::Internal); - rx_pin.init_input(false, false, crate::private::Internal); - rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL, crate::private::Internal); // Set the operating mode based on provided option match mode { @@ -903,7 +905,7 @@ where /// Create a new instance of [TwaiConfiguration] /// /// You will need to use a transceiver to connect to the TWAI bus - pub fn new( + pub fn new( peripheral: impl Peripheral

+ 'd, rx_pin: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, @@ -918,7 +920,7 @@ where /// /// You don't need a transceiver by following the description in the /// `twai.rs` example - pub fn new_no_transceiver( + pub fn new_no_transceiver( peripheral: impl Peripheral

+ 'd, rx_pin: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, @@ -947,7 +949,7 @@ where /// Create a new instance of [TwaiConfiguration] in async mode /// /// You will need to use a transceiver to connect to the TWAI bus - pub fn new_async( + pub fn new_async( peripheral: impl Peripheral

+ 'd, rx_pin: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, @@ -964,7 +966,7 @@ where /// /// You don't need a transceiver by following the description in the /// `twai.rs` example - pub fn new_async_no_transceiver( + pub fn new_async_no_transceiver( peripheral: impl Peripheral

+ 'd, rx_pin: impl Peripheral

+ 'd, tx_pin: impl Peripheral

+ 'd, diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index b17858627d..0f3ee6c4e5 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -94,12 +94,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::uart::Uart; -//! use esp_hal::gpio::{AnyPin, Io}; +//! use esp_hal::gpio::Io; //! //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! -//! let rx = AnyPin::new_inverted(io.pins.gpio2); -//! let tx = AnyPin::new_inverted(io.pins.gpio1); +//! let rx = io.pins.gpio2.peripheral_input().inverted(); +//! let tx = io.pins.gpio1.into_peripheral_output().inverted(); //! let mut uart1 = Uart::new( //! peripherals.UART1, //! rx, @@ -112,7 +112,7 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::uart::{UartTx, UartRx}; -//! use esp_hal::gpio::{AnyPin, Io}; +//! use esp_hal::gpio::Io; //! //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! @@ -131,7 +131,7 @@ use core::marker::PhantomData; use self::config::Config; use crate::{ clock::Clocks, - gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, + gpio::{InputSignal, OutputSignal, PeripheralInput, PeripheralOutput, Pull}, interrupt::InterruptHandler, peripheral::{Peripheral, PeripheralRef}, peripherals::{uart0::RegisterBlock, Interrupt}, @@ -451,15 +451,15 @@ where } } - fn with_rx(self, rx: impl Peripheral

+ 'd) -> Self { + fn with_rx(self, rx: impl Peripheral

+ 'd) -> Self { crate::into_ref!(rx); - rx.init_input(false, false, Internal); + rx.init_input(Pull::Up, Internal); rx.connect_input_to_peripheral(T::rx_signal(), Internal); self } - fn with_tx(self, tx: impl Peripheral

+ 'd) -> Self { + fn with_tx(self, tx: impl Peripheral

+ 'd) -> Self { crate::into_ref!(tx); tx.set_to_push_pull_output(Internal); tx.connect_peripheral_to_output(T::tx_signal(), Internal); @@ -536,7 +536,7 @@ where } /// Configure RTS pin - pub fn with_rts(self, rts: impl Peripheral

+ 'd) -> Self { + pub fn with_rts(self, rts: impl Peripheral

+ 'd) -> Self { crate::into_ref!(rts); rts.set_to_push_pull_output(Internal); rts.connect_peripheral_to_output(T::rts_signal(), Internal); @@ -581,7 +581,7 @@ where T: Instance + 'd, { /// Create a new UART TX instance in [`Blocking`] mode. - pub fn new( + pub fn new( uart: impl Peripheral

+ 'd, tx: impl Peripheral

+ 'd, ) -> Result { @@ -590,7 +590,7 @@ where /// Create a new UART TX instance with configuration options in /// [`Blocking`] mode. - pub fn new_with_config( + pub fn new_with_config( uart: impl Peripheral

+ 'd, config: Config, tx: impl Peripheral

+ 'd, @@ -620,9 +620,9 @@ where } /// Configure CTS pin - pub fn with_cts(self, cts: impl Peripheral

+ 'd) -> Self { + pub fn with_cts(self, cts: impl Peripheral

+ 'd) -> Self { crate::into_ref!(cts); - cts.init_input(false, false, Internal); + cts.init_input(Pull::None, Internal); cts.connect_input_to_peripheral(T::cts_signal(), Internal); self @@ -794,7 +794,7 @@ where T: Instance + 'd, { /// Create a new UART RX instance in [`Blocking`] mode. - pub fn new( + pub fn new( uart: impl Peripheral

+ 'd, rx: impl Peripheral

+ 'd, ) -> Result { @@ -803,7 +803,7 @@ where /// Create a new UART RX instance with configuration options in /// [`Blocking`] mode. - pub fn new_with_config( + pub fn new_with_config( uart: impl Peripheral

+ 'd, config: Config, rx: impl Peripheral

+ 'd, @@ -820,7 +820,7 @@ where { /// Create a new UART instance with configuration options in [`Blocking`] /// mode. - pub fn new_with_config( + pub fn new_with_config( uart: impl Peripheral

+ 'd, config: Config, rx: impl Peripheral

+ 'd, @@ -835,7 +835,7 @@ where } /// Create a new UART instance with defaults in [`Blocking`] mode. - pub fn new( + pub fn new( uart: impl Peripheral

+ 'd, rx: impl Peripheral

+ 'd, tx: impl Peripheral

+ 'd, @@ -857,16 +857,16 @@ where } /// Configure CTS pin - pub fn with_cts(self, cts: impl Peripheral

+ 'd) -> Self { + pub fn with_cts(self, cts: impl Peripheral

+ 'd) -> Self { crate::into_ref!(cts); - cts.init_input(false, false, Internal); + cts.init_input(Pull::None, Internal); cts.connect_input_to_peripheral(T::cts_signal(), Internal); self } /// Configure RTS pin - pub fn with_rts(self, rts: impl Peripheral

+ 'd) -> Self { + pub fn with_rts(self, rts: impl Peripheral

+ 'd) -> Self { crate::into_ref!(rts); rts.set_to_push_pull_output(Internal); rts.connect_peripheral_to_output(T::rts_signal(), Internal); @@ -2058,7 +2058,7 @@ mod asynch { { /// Create a new UART instance with configuration options in [`Async`] /// mode. - pub fn new_async_with_config( + pub fn new_async_with_config( uart: impl Peripheral

+ 'd, config: Config, rx: impl Peripheral

+ 'd, @@ -2086,7 +2086,7 @@ mod asynch { } /// Create a new UART instance with defaults in [`Async`] mode. - pub fn new_async( + pub fn new_async( uart: impl Peripheral

+ 'd, rx: impl Peripheral

+ 'd, tx: impl Peripheral

+ 'd, @@ -2121,7 +2121,7 @@ mod asynch { T: Instance + 'd, { /// Create a new UART TX instance in [`Async`] mode. - pub fn new_async( + pub fn new_async( uart: impl Peripheral

+ 'd, tx: impl Peripheral

+ 'd, ) -> Result { @@ -2130,7 +2130,7 @@ mod asynch { /// Create a new UART TX instance with configuration options in /// [`Async`] mode. - pub fn new_async_with_config( + pub fn new_async_with_config( uart: impl Peripheral

+ 'd, config: Config, tx: impl Peripheral

+ 'd, @@ -2202,7 +2202,7 @@ mod asynch { T: Instance + 'd, { /// Create a new UART RX instance in [`Async`] mode. - pub fn new_async( + pub fn new_async( uart: impl Peripheral

+ 'd, rx: impl Peripheral

+ 'd, ) -> Result { @@ -2211,7 +2211,7 @@ mod asynch { /// Create a new UART RX instance with configuration options in /// [`Async`] mode. - pub fn new_async_with_config( + pub fn new_async_with_config( uart: impl Peripheral

+ 'd, config: Config, rx: impl Peripheral

+ 'd, diff --git a/esp-wifi/CHANGELOG.md b/esp-wifi/CHANGELOG.md index 0b3a39694d..9fe985aab4 100644 --- a/esp-wifi/CHANGELOG.md +++ b/esp-wifi/CHANGELOG.md @@ -12,13 +12,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `have-strchr` feature to disable including `strchr` (#2096) ### Changed + - esp-wifi now allocates memory from the global allocator provided by `esp-alloc` (#2099) ### Fixed + - Feature `wifi-logs` doesn't break the build anymore (#2117) ### Removed +- Removed the `clocks` parameter from `esp_wifi::initialize` (#1999) + ## 0.9.1 - 2024-09-03 ### Added @@ -43,8 +47,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed -- Removed the `clocks` parameter from `esp_wifi::initialize` (#1999) - ## 0.8.0 - 2024-08-29 ### Added diff --git a/examples/src/bin/blinky_erased_pins.rs b/examples/src/bin/blinky_erased_pins.rs index 93d23e56f9..48d9309f08 100644 --- a/examples/src/bin/blinky_erased_pins.rs +++ b/examples/src/bin/blinky_erased_pins.rs @@ -14,7 +14,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - gpio::{ErasedPin, Input, Io, Level, Output, Pin, Pull}, + gpio::{Input, Io, Level, Output, Pin, Pull}, prelude::*, }; @@ -47,7 +47,7 @@ fn main() -> ! { } } -fn toggle_pins(leds: &mut [Output], button: &Input) { +fn toggle_pins(leds: &mut [Output], button: &Input) { for pin in leds.iter_mut() { pin.toggle(); } diff --git a/examples/src/bin/embassy_i2c.rs b/examples/src/bin/embassy_i2c.rs index f9352e1fda..604cac1c18 100644 --- a/examples/src/bin/embassy_i2c.rs +++ b/examples/src/bin/embassy_i2c.rs @@ -6,7 +6,7 @@ //! This is an example of running the embassy executor with IC2. It uses an //! LIS3DH to get accelerometer data. //! -//! Folowing pins are used: +//! Following pins are used: //! - SDA => GPIO4 //! - SCL => GPIO5 diff --git a/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs b/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs index f1e5299f17..d725f2a7db 100644 --- a/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs +++ b/examples/src/bin/embassy_i2c_bmp180_calibration_data.rs @@ -3,7 +3,7 @@ //! This example dumps the calibration data from a BMP180 sensor by reading by reading //! with the direct I2C API and the embedded-hal-async I2C API. //! -//! Folowing pins are used: +//! Following pins are used: //! - SDA => GPIO4 //! - SCL => GPIO5 //! diff --git a/examples/src/bin/embassy_multicore.rs b/examples/src/bin/embassy_multicore.rs index 7d871f2b00..8efe9ff3ae 100644 --- a/examples/src/bin/embassy_multicore.rs +++ b/examples/src/bin/embassy_multicore.rs @@ -21,7 +21,7 @@ use esp_backtrace as _; use esp_hal::{ cpu_control::{CpuControl, Stack}, get_core, - gpio::{ErasedPin, Io, Level, Output, Pin}, + gpio::{Io, Level, Output, Pin}, timer::{timg::TimerGroup, ErasedTimer}, }; use esp_hal_embassy::Executor; @@ -34,7 +34,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new(); /// duration of time. #[embassy_executor::task] async fn control_led( - mut led: Output<'static, ErasedPin>, + mut led: Output<'static>, control: &'static Signal, ) { println!("Starting control_led() on core {}", get_core() as usize); diff --git a/examples/src/bin/embassy_multicore_interrupt.rs b/examples/src/bin/embassy_multicore_interrupt.rs index 0c69a468f3..7b99a85fe8 100644 --- a/examples/src/bin/embassy_multicore_interrupt.rs +++ b/examples/src/bin/embassy_multicore_interrupt.rs @@ -20,7 +20,7 @@ use esp_backtrace as _; use esp_hal::{ cpu_control::{CpuControl, Stack}, get_core, - gpio::{ErasedPin, Io, Level, Output, Pin}, + gpio::{Io, Level, Output, Pin}, interrupt::{software::SoftwareInterruptControl, Priority}, prelude::*, timer::{timg::TimerGroup, ErasedTimer}, @@ -35,7 +35,7 @@ static mut APP_CORE_STACK: Stack<8192> = Stack::new(); /// duration of time. #[embassy_executor::task] async fn control_led( - mut led: Output<'static, ErasedPin>, + mut led: Output<'static>, control: &'static Signal, ) { println!("Starting control_led() on core {}", get_core() as usize); diff --git a/examples/src/bin/pcnt_encoder.rs b/examples/src/bin/pcnt_encoder.rs index f02c0ddbdd..07f10b5a26 100644 --- a/examples/src/bin/pcnt_encoder.rs +++ b/examples/src/bin/pcnt_encoder.rs @@ -53,15 +53,15 @@ fn main() -> ! { println!("setup channel 0"); let ch0 = &u0.channel0; - let mut pin_a = io.pins.gpio4; - let mut pin_b = io.pins.gpio5; + let pin_a = io.pins.gpio4; + let pin_b = io.pins.gpio5; - ch0.set_ctrl_signal(PcntSource::from_pin( - &mut pin_a, + ch0.set_ctrl_signal(PcntSource::from( + pin_a.peripheral_input(), PcntInputConfig { pull: Pull::Up }, )); - ch0.set_edge_signal(PcntSource::from_pin( - &mut pin_b, + ch0.set_edge_signal(PcntSource::from( + pin_b.peripheral_input(), PcntInputConfig { pull: Pull::Up }, )); ch0.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep); @@ -69,12 +69,12 @@ fn main() -> ! { println!("setup channel 1"); let ch1 = &u0.channel1; - ch1.set_ctrl_signal(PcntSource::from_pin( - &mut pin_b, + ch1.set_ctrl_signal(PcntSource::from( + pin_b.peripheral_input(), PcntInputConfig { pull: Pull::Up }, )); - ch1.set_edge_signal(PcntSource::from_pin( - &mut pin_a, + ch1.set_edge_signal(PcntSource::from( + pin_a.peripheral_input(), PcntInputConfig { pull: Pull::Up }, )); ch1.set_ctrl_mode(channel::CtrlMode::Reverse, channel::CtrlMode::Keep); diff --git a/examples/src/bin/spi_loopback.rs b/examples/src/bin/spi_loopback.rs index fca0d8b2f9..c24dd894e2 100644 --- a/examples/src/bin/spi_loopback.rs +++ b/examples/src/bin/spi_loopback.rs @@ -2,16 +2,13 @@ //! //! The following wiring is assumed: //! - SCLK => GPIO0 -//! - MISO => GPIO2 -//! - MOSI => GPIO4 +//! - MISO/MOSI => GPIO2 //! - CS => GPIO5 //! //! Depending on your target and the board you are using you have to change the //! pins. //! //! This example transfers data via SPI. -//! Connect MISO and MOSI pins to see the outgoing data is read as incoming -//! data. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 @@ -21,7 +18,7 @@ use esp_backtrace as _; use esp_hal::{ delay::Delay, - gpio::{AnyPin, Io}, + gpio::Io, prelude::*, spi::{master::Spi, SpiMode}, }; @@ -33,12 +30,11 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio0; - let miso = io.pins.gpio2; - let mosi = io.pins.gpio4; + let miso_mosi = io.pins.gpio2; let cs = io.pins.gpio5; - let miso = AnyPin::new(miso); - let mosi = AnyPin::new(mosi); + let miso = miso_mosi.peripheral_input(); + let mosi = miso_mosi.into_peripheral_output(); let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0).with_pins( Some(sclk), diff --git a/hil-test/tests/gpio.rs b/hil-test/tests/gpio.rs index 9db23d2c71..6c23d33118 100644 --- a/hil-test/tests/gpio.rs +++ b/hil-test/tests/gpio.rs @@ -11,7 +11,7 @@ use core::cell::RefCell; use critical_section::Mutex; use esp_hal::{ delay::Delay, - gpio::{AnyPin, ErasedPin, Input, Io, Level, Output, Pin, Pull}, + gpio::{AnyPin, Input, Io, Level, Output, Pin, Pull}, macros::handler, timer::timg::TimerGroup, InterruptConfigurable, @@ -22,8 +22,8 @@ static COUNTER: Mutex> = Mutex::new(RefCell::new(0)); static INPUT_PIN: Mutex>> = Mutex::new(RefCell::new(None)); struct Context { - test_gpio1: ErasedPin, - test_gpio2: ErasedPin, + test_gpio1: AnyPin, + test_gpio2: AnyPin, delay: Delay, } @@ -267,8 +267,8 @@ mod tests { // https://github.com/esp-rs/esp-hal/issues/1943 #[test] fn test_gpio_touch_anypin_output(ctx: Context) { - let any_pin2 = AnyPin::new(ctx.test_gpio1); - let any_pin3 = AnyPin::new(ctx.test_gpio2); + let any_pin2 = ctx.test_gpio1; + let any_pin3 = ctx.test_gpio2; let out_pin = Output::new(any_pin2, Level::High); let in_pin = Input::new(any_pin3, Pull::Down); @@ -281,8 +281,8 @@ mod tests { // https://github.com/esp-rs/esp-hal/issues/1943 #[test] fn test_gpio_touch_anypin_input(ctx: Context) { - let any_pin2 = AnyPin::new(ctx.test_gpio1); - let any_pin3 = AnyPin::new(ctx.test_gpio2); + let any_pin2 = ctx.test_gpio1; + let any_pin3 = ctx.test_gpio2; let out_pin = Output::new(any_pin3, Level::Low); let in_pin = Input::new(any_pin2, Pull::Down); diff --git a/hil-test/tests/pcnt.rs b/hil-test/tests/pcnt.rs index 638c12817d..fbf35341fd 100644 --- a/hil-test/tests/pcnt.rs +++ b/hil-test/tests/pcnt.rs @@ -7,7 +7,7 @@ use esp_hal::{ delay::Delay, - gpio::{AnyPin, Io, Level, Output, Pull}, + gpio::{AnyPin, Io, Level, Output, Pin, Pull}, pcnt::{ channel::{EdgeMode, PcntInputConfig, PcntSource}, Pcnt, @@ -17,8 +17,8 @@ use hil_test as _; struct Context<'d> { pcnt: Pcnt<'d>, - input: AnyPin<'d>, - output: AnyPin<'d>, + input: AnyPin, + output: AnyPin, delay: Delay, } @@ -35,8 +35,8 @@ mod tests { let (din, dout) = hil_test::common_test_pins!(io); - let din = AnyPin::new(din); - let dout = AnyPin::new(dout); + let din = din.degrade(); + let dout = dout.degrade(); Context { pcnt: Pcnt::new(peripherals.PCNT), @@ -51,7 +51,7 @@ mod tests { let unit = ctx.pcnt.unit0; // Setup channel 0 to increment the count when gpio2 does LOW -> HIGH - unit.channel0.set_edge_signal(PcntSource::from_pin( + unit.channel0.set_edge_signal(PcntSource::from( ctx.input, PcntInputConfig { pull: Pull::Down }, )); @@ -90,7 +90,7 @@ mod tests { let unit = ctx.pcnt.unit1; // Setup channel 0 to increment the count when gpio2 does LOW -> HIGH - unit.channel0.set_edge_signal(PcntSource::from_pin( + unit.channel0.set_edge_signal(PcntSource::from( ctx.input, PcntInputConfig { pull: Pull::Up }, )); @@ -131,7 +131,7 @@ mod tests { unit.set_high_limit(Some(3)).unwrap(); // Setup channel 0 to increment the count when gpio2 does LOW -> HIGH - unit.channel0.set_edge_signal(PcntSource::from_pin( + unit.channel0.set_edge_signal(PcntSource::from( ctx.input, PcntInputConfig { pull: Pull::Up }, )); @@ -194,7 +194,7 @@ mod tests { unit.clear(); // Setup channel 0 to increment the count when gpio2 does LOW -> HIGH - unit.channel0.set_edge_signal(PcntSource::from_pin( + unit.channel0.set_edge_signal(PcntSource::from( ctx.input, PcntInputConfig { pull: Pull::Up }, )); @@ -261,7 +261,7 @@ mod tests { unit.clear(); // Setup channel 0 to decrement the count when gpio2 does LOW -> HIGH - unit.channel0.set_edge_signal(PcntSource::from_pin( + unit.channel0.set_edge_signal(PcntSource::from( ctx.input, PcntInputConfig { pull: Pull::Up }, )); @@ -319,7 +319,7 @@ mod tests { let unit = ctx.pcnt.unit2; // Setup channel 1 to increment the count when gpio2 does LOW -> HIGH - unit.channel1.set_edge_signal(PcntSource::from_pin( + unit.channel1.set_edge_signal(PcntSource::from( ctx.input, PcntInputConfig { pull: Pull::Up }, )); diff --git a/hil-test/tests/qspi_read.rs b/hil-test/tests/qspi_read.rs index 6328465fce..e910e2653a 100644 --- a/hil-test/tests/qspi_read.rs +++ b/hil-test/tests/qspi_read.rs @@ -8,7 +8,7 @@ use esp_hal::{ dma::{Channel, Dma, DmaPriority, DmaRxBuf}, dma_buffers, - gpio::{ErasedPin, Io, Level, Output}, + gpio::{AnyPin, Io, Level, Output}, prelude::*, spi::{ master::{Address, Command, Spi, SpiDma}, @@ -34,7 +34,7 @@ cfg_if::cfg_if! { struct Context { spi: esp_hal::peripherals::SPI2, dma_channel: Channel<'static, DmaChannel0, Blocking>, - miso: ErasedPin, + miso: AnyPin, miso_mirror: Output<'static>, } diff --git a/hil-test/tests/qspi_write.rs b/hil-test/tests/qspi_write.rs index 2b035a3456..e362e773b3 100644 --- a/hil-test/tests/qspi_write.rs +++ b/hil-test/tests/qspi_write.rs @@ -38,10 +38,10 @@ cfg_if::cfg_if! { struct Context { spi: esp_hal::peripherals::SPI2, + pcnt_source: PcntSource, pcnt: esp_hal::peripherals::PCNT, dma_channel: Channel<'static, DmaChannel0, Blocking>, - mosi: AnyPin<'static>, - mosi_mirror: AnyPin<'static>, + mosi: AnyPin, } fn execute( @@ -103,10 +103,9 @@ mod tests { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let (mosi, mosi_mirror) = hil_test::common_test_pins!(io); + let (mosi, _) = hil_test::common_test_pins!(io); - let mosi = AnyPin::new(mosi); - let mosi_mirror = AnyPin::new(mosi_mirror); + let mosi = mosi.degrade(); let dma = Dma::new(peripherals.DMA); @@ -122,10 +121,13 @@ mod tests { Context { spi: peripherals.SPI2, + pcnt_source: PcntSource::from( + mosi.peripheral_input(), + PcntInputConfig { pull: Pull::None }, + ), pcnt: peripherals.PCNT, dma_channel, mosi, - mosi_mirror, } } @@ -146,10 +148,7 @@ mod tests { let pcnt = Pcnt::new(ctx.pcnt); let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::None }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); @@ -173,10 +172,7 @@ mod tests { let pcnt = Pcnt::new(ctx.pcnt); let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::None }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); @@ -200,10 +196,7 @@ mod tests { let pcnt = Pcnt::new(ctx.pcnt); let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::None }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); @@ -227,10 +220,7 @@ mod tests { let pcnt = Pcnt::new(ctx.pcnt); let unit = pcnt.unit0; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::None }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); diff --git a/hil-test/tests/qspi_write_read.rs b/hil-test/tests/qspi_write_read.rs index 65bb660e58..5d4d19d765 100644 --- a/hil-test/tests/qspi_write_read.rs +++ b/hil-test/tests/qspi_write_read.rs @@ -10,7 +10,7 @@ use esp_hal::{ dma::{Channel, Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, - gpio::{ErasedPin, Io, Level, Output}, + gpio::{AnyPin, Io, Level, Output}, prelude::*, spi::{ master::{Address, Command, Spi, SpiDma}, @@ -36,7 +36,7 @@ cfg_if::cfg_if! { struct Context { spi: esp_hal::peripherals::SPI2, dma_channel: Channel<'static, DmaChannel0, Blocking>, - mosi: ErasedPin, + mosi: AnyPin, mosi_mirror: Output<'static>, } diff --git a/hil-test/tests/spi_full_duplex.rs b/hil-test/tests/spi_full_duplex.rs index 5578a89125..ce77f8b8a8 100644 --- a/hil-test/tests/spi_full_duplex.rs +++ b/hil-test/tests/spi_full_duplex.rs @@ -31,12 +31,13 @@ mod tests { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio0; - let (miso, mosi) = hil_test::common_test_pins!(io); + let (_, mosi) = hil_test::common_test_pins!(io); - let spi = Spi::new(peripherals.SPI2, 1000u32.kHz(), SpiMode::Mode0) + let mosi_loopback = mosi.peripheral_input(); + let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) - .with_miso(miso); + .with_miso(mosi_loopback); Context { spi } } diff --git a/hil-test/tests/spi_full_duplex_dma.rs b/hil-test/tests/spi_full_duplex_dma.rs index 6781261e02..34c53bb50d 100644 --- a/hil-test/tests/spi_full_duplex_dma.rs +++ b/hil-test/tests/spi_full_duplex_dma.rs @@ -48,7 +48,7 @@ mod tests { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio0; - let (miso, mosi) = hil_test::common_test_pins!(io); + let (_, mosi) = hil_test::common_test_pins!(io); let dma = Dma::new(peripherals.DMA); @@ -60,10 +60,11 @@ mod tests { } } + let mosi_loopback = mosi.peripheral_input(); let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) - .with_miso(miso) + .with_miso(mosi_loopback) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); Context { spi } diff --git a/hil-test/tests/spi_full_duplex_dma_async.rs b/hil-test/tests/spi_full_duplex_dma_async.rs index 1758751891..593ccce953 100644 --- a/hil-test/tests/spi_full_duplex_dma_async.rs +++ b/hil-test/tests/spi_full_duplex_dma_async.rs @@ -10,7 +10,7 @@ use embedded_hal_async::spi::SpiBus; use esp_hal::{ dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, - gpio::{ErasedPin, Io, Level, Output, Pull}, + gpio::{Io, Pull}, pcnt::{ channel::{EdgeMode, PcntInputConfig, PcntSource}, unit::Unit, @@ -42,9 +42,8 @@ const DMA_BUFFER_SIZE: usize = 5; struct Context { spi: SpiDmaBus<'static, SPI2, DmaChannel0, FullDuplexMode, Async>, + pcnt_source: PcntSource, pcnt_unit: Unit<'static, 0>, - out_pin: Output<'static>, - mosi_mirror: ErasedPin, } #[cfg(test)] @@ -62,13 +61,7 @@ mod tests { let pcnt = Pcnt::new(peripherals.PCNT); let sclk = io.pins.gpio0; - let (mosi_mirror, mosi) = hil_test::common_test_pins!(io); - let miso = io.pins.gpio4; - let mosi_mirror = mosi_mirror.degrade(); - - let mut out_pin = Output::new(io.pins.gpio5, Level::Low); - out_pin.set_low(); - assert_eq!(out_pin.is_set_low(), true); + let (_, mosi) = hil_test::common_test_pins!(io); let dma = Dma::new(peripherals.DMA); @@ -84,28 +77,26 @@ mod tests { let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap(); let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap(); + let mosi_loopback = mosi.peripheral_input(); + let mosi_loopback_pcnt = mosi.peripheral_input(); let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) - .with_miso(miso) + .with_miso(mosi_loopback) .with_dma(dma_channel.configure_for_async(false, DmaPriority::Priority0)) .with_buffers(dma_rx_buf, dma_tx_buf); Context { spi, + pcnt_source: PcntSource::from(mosi_loopback_pcnt, PcntInputConfig { pull: Pull::Down }), pcnt_unit: pcnt.unit0, - out_pin, - mosi_mirror, } } #[test] #[timeout(3)] async fn test_async_dma_read_dma_write_pcnt(mut ctx: Context) { - ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); + ctx.pcnt_unit.channel0.set_edge_signal(ctx.pcnt_source); ctx.pcnt_unit .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); @@ -115,8 +106,6 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. let transmit = [0b0110_1010; DMA_BUFFER_SIZE]; - assert_eq!(ctx.out_pin.is_set_low(), true); - for i in 1..4 { receive.copy_from_slice(&[5, 5, 5, 5, 5]); SpiBus::read(&mut ctx.spi, &mut receive).await.unwrap(); @@ -130,10 +119,7 @@ mod tests { #[test] #[timeout(3)] async fn test_async_dma_read_dma_transfer_pcnt(mut ctx: Context) { - ctx.pcnt_unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); + ctx.pcnt_unit.channel0.set_edge_signal(ctx.pcnt_source); ctx.pcnt_unit .channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); @@ -143,8 +129,6 @@ mod tests { // Fill the buffer where each byte has 3 pos edges. let transmit = [0b0110_1010; DMA_BUFFER_SIZE]; - assert_eq!(ctx.out_pin.is_set_low(), true); - for i in 1..4 { receive.copy_from_slice(&[5, 5, 5, 5, 5]); SpiBus::read(&mut ctx.spi, &mut receive).await.unwrap(); diff --git a/hil-test/tests/spi_full_duplex_dma_pcnt.rs b/hil-test/tests/spi_full_duplex_dma_pcnt.rs index 403f3a75cd..59fbc30260 100644 --- a/hil-test/tests/spi_full_duplex_dma_pcnt.rs +++ b/hil-test/tests/spi_full_duplex_dma_pcnt.rs @@ -8,7 +8,7 @@ use esp_hal::{ dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, - gpio::{ErasedPin, Io, Level, Output, Pull}, + gpio::{Io, Pull}, pcnt::{ channel::{EdgeMode, PcntInputConfig, PcntSource}, unit::Unit, @@ -38,9 +38,8 @@ cfg_if::cfg_if! { struct Context { spi: SpiDma<'static, SPI2, DmaChannel0, FullDuplexMode, Blocking>, + pcnt_source: PcntSource, pcnt_unit: Unit<'static, 0>, - out_pin: Output<'static>, - mosi_mirror: ErasedPin, } #[cfg(test)] @@ -56,8 +55,7 @@ mod tests { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio0; - let (mosi_mirror, mosi) = hil_test::common_test_pins!(io); - let miso = io.pins.gpio4; + let (_, mosi) = hil_test::common_test_pins!(io); let dma = Dma::new(peripherals.DMA); @@ -69,24 +67,20 @@ mod tests { } } + let mosi_loopback = mosi.peripheral_input(); + let mosi_loopback_pcnt = mosi.peripheral_input(); let spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) - .with_miso(miso) + .with_miso(mosi_loopback) .with_dma(dma_channel.configure(false, DmaPriority::Priority0)); let pcnt = Pcnt::new(peripherals.PCNT); - let mut out_pin = Output::new(io.pins.gpio5, Level::Low); - out_pin.set_low(); - assert_eq!(out_pin.is_set_low(), true); - let mosi_mirror = mosi_mirror.degrade(); - Context { spi, + pcnt_source: PcntSource::from(mosi_loopback_pcnt, PcntInputConfig { pull: Pull::Down }), pcnt_unit: pcnt.unit0, - out_pin, - mosi_mirror, } } @@ -101,18 +95,13 @@ mod tests { let unit = ctx.pcnt_unit; let mut spi = ctx.spi; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); // Fill the buffer where each byte has 3 pos edges. dma_tx_buf.as_mut_slice().fill(0b0110_1010); - assert_eq!(ctx.out_pin.is_set_low(), true); - for i in 1..4 { dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap(); @@ -136,18 +125,13 @@ mod tests { let unit = ctx.pcnt_unit; let mut spi = ctx.spi; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); // Fill the buffer where each byte has 3 pos edges. dma_tx_buf.as_mut_slice().fill(0b0110_1010); - assert_eq!(ctx.out_pin.is_set_low(), true); - for i in 1..4 { dma_rx_buf.as_mut_slice().copy_from_slice(&[5, 5, 5, 5, 5]); let transfer = spi.dma_read(dma_rx_buf).map_err(|e| e.0).unwrap(); diff --git a/hil-test/tests/spi_half_duplex_write.rs b/hil-test/tests/spi_half_duplex_write.rs index af77205261..787ce803af 100644 --- a/hil-test/tests/spi_half_duplex_write.rs +++ b/hil-test/tests/spi_half_duplex_write.rs @@ -8,7 +8,7 @@ use esp_hal::{ dma::{Dma, DmaPriority, DmaRxBuf, DmaTxBuf}, dma_buffers, - gpio::{AnyPin, Io, Pull}, + gpio::{Io, Pull}, pcnt::{ channel::{EdgeMode, PcntInputConfig, PcntSource}, unit::Unit, @@ -40,7 +40,7 @@ cfg_if::cfg_if! { struct Context { spi: SpiDma<'static, SPI2, DmaChannel0, HalfDuplexMode, Blocking>, pcnt_unit: Unit<'static, 0>, - mosi_mirror: AnyPin<'static>, + pcnt_source: PcntSource, } #[cfg(test)] @@ -59,9 +59,7 @@ mod tests { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio0; - let (mosi, mosi_mirror) = hil_test::common_test_pins!(io); - - let mosi_mirror = AnyPin::new(mosi_mirror); + let (mosi, _) = hil_test::common_test_pins!(io); let pcnt = Pcnt::new(peripherals.PCNT); let dma = Dma::new(peripherals.DMA); @@ -74,6 +72,8 @@ mod tests { } } + let mosi_loopback = mosi.peripheral_input(); + let spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0) .with_sck(sclk) .with_mosi(mosi) @@ -81,7 +81,7 @@ mod tests { Context { spi, - mosi_mirror, + pcnt_source: PcntSource::from(mosi_loopback, PcntInputConfig { pull: Pull::Down }), pcnt_unit: pcnt.unit0, } } @@ -97,10 +97,7 @@ mod tests { let unit = ctx.pcnt_unit; let mut spi = ctx.spi; - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment); @@ -148,10 +145,7 @@ mod tests { let unit = ctx.pcnt_unit; let mut spi = ctx.spi.with_buffers(dma_rx_buf, dma_tx_buf); - unit.channel0.set_edge_signal(PcntSource::from_pin( - ctx.mosi_mirror, - PcntInputConfig { pull: Pull::Down }, - )); + unit.channel0.set_edge_signal(ctx.pcnt_source); unit.channel0 .set_input_mode(EdgeMode::Hold, EdgeMode::Increment);