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