Don't require interconnect signals to be Peripheral impls (#3302)

* Fix unsoundness around DerefMut

* Don't require interconnect signals to be Peripheral impls

* Remove Peripheral impl from pin drivers

* Changelog

* Yeet Level and NoPin impls

* Re-add missing Sealed impl for mutable references

* Relax
This commit is contained in:
Dániel Buga 2025-03-28 15:52:05 +01:00 committed by GitHub
parent 873f033089
commit f6b467402a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 925 additions and 850 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for `rand_core` 0.9 (#3211) - Support for `rand_core` 0.9 (#3211)
- `ESP_HAL_CONFIG_STACK_GUARD_OFFSET` and `ESP_HAL_CONFIG_STACK_GUARD_VALUE` to configure Rust's [Stack smashing protection](https://doc.rust-lang.org/rustc/exploit-mitigations.html#stack-smashing-protection) (#3203) - `ESP_HAL_CONFIG_STACK_GUARD_OFFSET` and `ESP_HAL_CONFIG_STACK_GUARD_VALUE` to configure Rust's [Stack smashing protection](https://doc.rust-lang.org/rustc/exploit-mitigations.html#stack-smashing-protection) (#3203)
- Experimental metadata in the output `.elf` (#3276) - Experimental metadata in the output `.elf` (#3276)
- `PeripheralInput::connect_input_to_peripheral` and `PeripheralOuptut::{connect_peripheral_to_output, disconnect_from_peripheral_output}` (#3302)
### Changed ### Changed
@ -20,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `esp_hal::i2c::master::AnyI2c` has been moved to `esp_hal::i2c::AnyI2c` (#3226) - `esp_hal::i2c::master::AnyI2c` has been moved to `esp_hal::i2c::AnyI2c` (#3226)
- `SpiDmaBus` no longer adjusts the DMA buffer length for each transfer (#3263) - `SpiDmaBus` no longer adjusts the DMA buffer length for each transfer (#3263)
- `gpio::interconnect` types now have a lifetime associated with them (#3302)
### Fixed ### Fixed
- RMT now uses correct max filter threshold of 255 instead of 127 (#3192) - RMT now uses correct max filter threshold of 255 instead of 127 (#3192)
@ -37,6 +40,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed ### Removed
- `gpio::{Level, NoPin, Input, Output, Flex}` no longer implement `Peripheral` (#3302)
## v1.0.0-beta.0 ## v1.0.0-beta.0
### Added ### Added

View File

@ -0,0 +1,23 @@
# Migration Guide from v1.0.0-beta.0 to ?
## GPIO changes
### Interconnect types now have a lifetime
The GPIO interconnect types now have a lifetime. This lifetime prevents them to be live for longer
than the GPIO that was used to create them.
The affected types in the `gpio::interconnect` module are:
- `InputSignal`
- `OutputSignal`
- `InputConnection`
- `OutputConnection`
### Pin drivers no longer implement `Peripheral`
Peripheral drivers now take `impl PeripheralInput` and `impl PeripheralOutput` directly. These
traits are now implemented for GPIO pins (stably) and driver structs (unstably) alike.
This change means it's no longer possible to pass a reference to a GPIO driver to a peripheral
driver. For example, it's no longer possible to pass an `&mut Input` to `Spi::with_miso`.

View File

@ -29,7 +29,7 @@ use crate::{
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AnyGdmaChannel(u8); pub struct AnyGdmaChannel(u8);
impl Peripheral for AnyGdmaChannel { unsafe impl Peripheral for AnyGdmaChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -52,7 +52,7 @@ impl DmaChannel for AnyGdmaChannel {
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AnyGdmaRxChannel(u8); pub struct AnyGdmaRxChannel(u8);
impl Peripheral for AnyGdmaRxChannel { unsafe impl Peripheral for AnyGdmaRxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -71,7 +71,7 @@ impl DmaChannelConvert<AnyGdmaRxChannel> for AnyGdmaRxChannel {
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct AnyGdmaTxChannel(u8); pub struct AnyGdmaTxChannel(u8);
impl Peripheral for AnyGdmaTxChannel { unsafe impl Peripheral for AnyGdmaTxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -602,7 +602,7 @@ macro_rules! impl_channel {
impl $crate::private::Sealed for [<DmaChannel $num>] {} impl $crate::private::Sealed for [<DmaChannel $num>] {}
impl Peripheral for [<DmaChannel $num>] { unsafe impl Peripheral for [<DmaChannel $num>] {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {

View File

@ -23,7 +23,7 @@ impl CryptoDmaRxChannel {
impl crate::private::Sealed for CryptoDmaRxChannel {} impl crate::private::Sealed for CryptoDmaRxChannel {}
impl DmaRxChannel for CryptoDmaRxChannel {} impl DmaRxChannel for CryptoDmaRxChannel {}
impl Peripheral for CryptoDmaRxChannel { unsafe impl Peripheral for CryptoDmaRxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -44,7 +44,7 @@ impl CryptoDmaTxChannel {
impl crate::private::Sealed for CryptoDmaTxChannel {} impl crate::private::Sealed for CryptoDmaTxChannel {}
impl DmaTxChannel for CryptoDmaTxChannel {} impl DmaTxChannel for CryptoDmaTxChannel {}
impl Peripheral for CryptoDmaTxChannel { unsafe impl Peripheral for CryptoDmaTxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -438,7 +438,7 @@ pub struct CryptoDmaChannel {}
impl crate::private::Sealed for CryptoDmaChannel {} impl crate::private::Sealed for CryptoDmaChannel {}
impl Peripheral for CryptoDmaChannel { unsafe impl Peripheral for CryptoDmaChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
Self::steal() Self::steal()

View File

@ -17,7 +17,7 @@ impl AnyI2sDmaRxChannel {
impl crate::private::Sealed for AnyI2sDmaRxChannel {} impl crate::private::Sealed for AnyI2sDmaRxChannel {}
impl DmaRxChannel for AnyI2sDmaRxChannel {} impl DmaRxChannel for AnyI2sDmaRxChannel {}
impl Peripheral for AnyI2sDmaRxChannel { unsafe impl Peripheral for AnyI2sDmaRxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -38,7 +38,7 @@ impl AnyI2sDmaTxChannel {
impl crate::private::Sealed for AnyI2sDmaTxChannel {} impl crate::private::Sealed for AnyI2sDmaTxChannel {}
impl DmaTxChannel for AnyI2sDmaTxChannel {} impl DmaTxChannel for AnyI2sDmaTxChannel {}
impl Peripheral for AnyI2sDmaTxChannel { unsafe impl Peripheral for AnyI2sDmaTxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {

View File

@ -59,7 +59,7 @@ macro_rules! impl_pdma_channel {
impl $crate::private::Sealed for [<$instance DmaChannel>] {} impl $crate::private::Sealed for [<$instance DmaChannel>] {}
impl Peripheral for [<$instance DmaChannel>] { unsafe impl Peripheral for [<$instance DmaChannel>] {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {

View File

@ -17,7 +17,7 @@ impl AnySpiDmaRxChannel {
impl crate::private::Sealed for AnySpiDmaRxChannel {} impl crate::private::Sealed for AnySpiDmaRxChannel {}
impl DmaRxChannel for AnySpiDmaRxChannel {} impl DmaRxChannel for AnySpiDmaRxChannel {}
impl Peripheral for AnySpiDmaRxChannel { unsafe impl Peripheral for AnySpiDmaRxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
@ -38,7 +38,7 @@ impl AnySpiDmaTxChannel {
impl crate::private::Sealed for AnySpiDmaTxChannel {} impl crate::private::Sealed for AnySpiDmaTxChannel {}
impl DmaTxChannel for AnySpiDmaTxChannel {} impl DmaTxChannel for AnySpiDmaTxChannel {}
impl Peripheral for AnySpiDmaTxChannel { unsafe impl Peripheral for AnySpiDmaTxChannel {
type P = Self; type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {

View File

@ -150,7 +150,7 @@ impl<const C: u8> EventChannel<C> {
/// Trigger at rising edge /// Trigger at rising edge
pub fn rising_edge<'d>( pub fn rising_edge<'d>(
self, self,
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd, pin: impl Into<InputSignal<'d>>,
pin_config: InputConfig, pin_config: InputConfig,
) -> Event<'d> { ) -> Event<'d> {
self.into_event(pin, pin_config, EventKind::Rising) self.into_event(pin, pin_config, EventKind::Rising)
@ -159,7 +159,7 @@ impl<const C: u8> EventChannel<C> {
/// Trigger at falling edge /// Trigger at falling edge
pub fn falling_edge<'d>( pub fn falling_edge<'d>(
self, self,
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd, pin: impl Into<InputSignal<'d>>,
pin_config: InputConfig, pin_config: InputConfig,
) -> Event<'d> { ) -> Event<'d> {
self.into_event(pin, pin_config, EventKind::Falling) self.into_event(pin, pin_config, EventKind::Falling)
@ -168,7 +168,7 @@ impl<const C: u8> EventChannel<C> {
/// Trigger at any edge /// Trigger at any edge
pub fn any_edge<'d>( pub fn any_edge<'d>(
self, self,
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd, pin: impl Into<InputSignal<'d>>,
pin_config: InputConfig, pin_config: InputConfig,
) -> Event<'d> { ) -> Event<'d> {
self.into_event(pin, pin_config, EventKind::Any) self.into_event(pin, pin_config, EventKind::Any)
@ -176,11 +176,11 @@ impl<const C: u8> EventChannel<C> {
fn into_event<'d>( fn into_event<'d>(
self, self,
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd, pin: impl Into<InputSignal<'d>>,
pin_config: InputConfig, pin_config: InputConfig,
kind: EventKind, kind: EventKind,
) -> Event<'d> { ) -> Event<'d> {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.init_input(pin_config.pull); pin.init_input(pin_config.pull);
@ -256,27 +256,19 @@ impl<const C: u8> TaskChannel<C> {
// number is the pin-count // number is the pin-count
/// Task to set a high level /// Task to set a high level
pub fn set<'d>( pub fn set<'d>(self, pin: impl Into<OutputSignal<'d>>, pin_config: OutputConfig) -> Task<'d> {
self,
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
pin_config: OutputConfig,
) -> Task<'d> {
self.into_task(pin, pin_config, TaskKind::Set) self.into_task(pin, pin_config, TaskKind::Set)
} }
/// Task to set a low level /// Task to set a low level
pub fn clear<'d>( pub fn clear<'d>(self, pin: impl Into<OutputSignal<'d>>, pin_config: OutputConfig) -> Task<'d> {
self,
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
pin_config: OutputConfig,
) -> Task<'d> {
self.into_task(pin, pin_config, TaskKind::Clear) self.into_task(pin, pin_config, TaskKind::Clear)
} }
/// Task to toggle the level /// Task to toggle the level
pub fn toggle<'d>( pub fn toggle<'d>(
self, self,
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd, pin: impl Into<OutputSignal<'d>>,
pin_config: OutputConfig, pin_config: OutputConfig,
) -> Task<'d> { ) -> Task<'d> {
self.into_task(pin, pin_config, TaskKind::Toggle) self.into_task(pin, pin_config, TaskKind::Toggle)
@ -284,11 +276,11 @@ impl<const C: u8> TaskChannel<C> {
fn into_task<'d>( fn into_task<'d>(
self, self,
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd, pin: impl Into<OutputSignal<'d>>,
pin_config: OutputConfig, pin_config: OutputConfig,
kind: TaskKind, kind: TaskKind,
) -> Task<'d> { ) -> Task<'d> {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_output_high(pin_config.initial_state.into()); pin.set_output_high(pin_config.initial_state.into());
if pin_config.open_drain { if pin_config.open_drain {

View File

@ -7,6 +7,10 @@
// interconnect module we allow multiple handles, which means possible RMW // interconnect module we allow multiple handles, which means possible RMW
// operations on the pin registers cause data races. // operations on the pin registers cause data races.
use core::marker::PhantomData;
#[cfg(feature = "unstable")]
use crate::gpio::{Input, Output};
use crate::{ use crate::{
gpio::{ gpio::{
self, self,
@ -27,7 +31,7 @@ use crate::{
INPUT_SIGNAL_MAX, INPUT_SIGNAL_MAX,
OUTPUT_SIGNAL_MAX, OUTPUT_SIGNAL_MAX,
}, },
peripheral::Peripheral, peripheral::{Peripheral, PeripheralRef},
peripherals::GPIO, peripherals::GPIO,
private::{self, Sealed}, private::{self, Sealed},
}; };
@ -40,7 +44,10 @@ use crate::{
private_bounds, private_bounds,
reason = "InputConnection is unstable, but the trait needs to be public" reason = "InputConnection is unstable, but the trait needs to be public"
)] )]
pub trait PeripheralInput: Into<InputConnection> + 'static + crate::private::Sealed {} pub trait PeripheralInput<'d>: Into<InputConnection<'d>> + crate::private::Sealed {
/// Connects the peripheral input to an input signal source.
fn connect_input_to_peripheral(&self, signal: gpio::InputSignal);
}
/// A signal that can be connected to a peripheral input and/or output. /// A signal that can be connected to a peripheral input and/or output.
/// ///
@ -50,32 +57,186 @@ pub trait PeripheralInput: Into<InputConnection> + 'static + crate::private::Sea
private_bounds, private_bounds,
reason = "OutputConnection is unstable, but the trait needs to be public" reason = "OutputConnection is unstable, but the trait needs to be public"
)] )]
pub trait PeripheralOutput: Into<OutputConnection> + 'static + crate::private::Sealed {} pub trait PeripheralOutput<'d>: Into<OutputConnection<'d>> + crate::private::Sealed {
/// Connects the peripheral output to an output signal target.
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal);
/// Disconnects the peripheral output from an output signal target.
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal);
}
// Pins // Pins
impl<P: InputPin> PeripheralInput for P {} impl<P, IP> PeripheralInput<'_> for P
impl<P: OutputPin> PeripheralOutput for P {} where
P: Peripheral<P = IP> + crate::private::Sealed,
IP: InputPin,
{
fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
let this = PeripheralRef::new(unsafe { self.clone_unchecked() });
let pin = unsafe { AnyPin::steal(this.number()) };
DirectInputSignal::new(pin).connect_input_to_peripheral(signal);
}
}
impl<P, OP> PeripheralOutput<'_> for P
where
P: Peripheral<P = OP> + crate::private::Sealed,
OP: OutputPin,
{
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
let this = PeripheralRef::new(unsafe { self.clone_unchecked() });
let pin = unsafe { AnyPin::steal(this.number()) };
DirectOutputSignal::new(pin).connect_peripheral_to_output(signal);
}
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal) {
let this = PeripheralRef::new(unsafe { self.clone_unchecked() });
let pin = unsafe { AnyPin::steal(this.number()) };
DirectOutputSignal::new(pin).disconnect_from_peripheral_output(signal);
}
}
// Pin drivers // Pin drivers
impl PeripheralInput for Flex<'static> {} impl<'d> PeripheralInput<'d> for Flex<'d> {
impl PeripheralOutput for Flex<'static> {} fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
let pin = unsafe { AnyPin::steal(self.pin.number()) };
InputSignal::new(pin).connect_input_to_peripheral(signal);
}
}
#[instability::unstable]
impl<'d> PeripheralInput<'d> for Input<'d> {
fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
// Delegate to Flex
self.pin.connect_input_to_peripheral(signal);
}
}
impl<'d> PeripheralOutput<'d> for Flex<'d> {
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
let pin = unsafe { AnyPin::steal(self.pin.number()) };
OutputSignal::new(pin).connect_peripheral_to_output(signal);
}
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal) {
let pin = unsafe { AnyPin::steal(self.pin.number()) };
OutputSignal::new(pin).disconnect_from_peripheral_output(signal);
}
}
#[instability::unstable]
impl<'d> PeripheralOutput<'d> for Output<'d> {
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
// Delegate to Flex
self.pin.connect_peripheral_to_output(signal);
}
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal) {
// Delegate to Flex
self.pin.disconnect_from_peripheral_output(signal);
}
}
// Placeholders // Placeholders
impl PeripheralInput for NoPin {} impl PeripheralInput<'_> for NoPin {
impl PeripheralOutput for NoPin {} fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
// Arbitrary choice but we need to overwrite a previous signal input
// association.
Level::Low.connect_input_to_peripheral(signal);
}
}
impl PeripheralOutput<'_> for NoPin {
fn connect_peripheral_to_output(&self, _: gpio::OutputSignal) {
// A peripheral's outputs may be connected to any number of GPIOs.
// Connecting to, and disconnecting from a NoPin is therefore a
// no-op, as we are adding and removing nothing from that list of
// connections.
}
fn disconnect_from_peripheral_output(&self, _: gpio::OutputSignal) {
// A peripheral's outputs may be connected to any number of GPIOs.
// Connecting to, and disconnecting from a NoPin is therefore a
// no-op, as we are adding and removing nothing from that list of
// connections.
}
}
impl PeripheralInput for Level {} impl PeripheralInput<'_> for Level {
impl PeripheralOutput for Level {} fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
let value = match self {
Level::High => gpio::ONE_INPUT,
Level::Low => gpio::ZERO_INPUT,
};
connect_input_signal(signal, value, false, true);
}
}
impl PeripheralOutput<'_> for Level {
fn connect_peripheral_to_output(&self, _: gpio::OutputSignal) {
// There is no such thing as a constant-high level peripheral output,
// the implementation just exists for convenience.
}
fn disconnect_from_peripheral_output(&self, _: gpio::OutputSignal) {
// There is no such thing as a constant-high level peripheral output,
// the implementation just exists for convenience.
}
}
// Split signals // Split signals
impl PeripheralInput for InputSignal {} impl<'d> PeripheralInput<'d> for InputSignal<'d> {
impl PeripheralInput for OutputSignal {} fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
impl PeripheralOutput for OutputSignal {} // Since there can only be one input signal connected to a peripheral
// at a time, this function will disconnect any previously
// connected input signals.
connect_pin_to_input_signal(&self.pin, signal, self.is_inverted, true);
}
}
impl<'d> PeripheralInput<'d> for OutputSignal<'d> {
fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
connect_pin_to_input_signal(&self.pin, signal, self.is_inverted, true);
}
}
impl<'d> PeripheralOutput<'d> for OutputSignal<'d> {
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
connect_peripheral_to_output(&self.pin, signal, self.is_inverted, true, true, false);
}
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal) {
// Clears the entry in the GPIO matrix / Io mux that associates this output
// pin with a previously connected [signal](`gpio::OutputSignal`). Any
// other outputs connected to the peripheral remain intact.
disconnect_peripheral_output_from_pin(&self.pin, signal);
}
}
// Type-erased signals // Type-erased signals
impl PeripheralInput for InputConnection {} impl<'d> PeripheralInput<'d> for InputConnection<'d> {
impl PeripheralInput for OutputConnection {} fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
impl PeripheralOutput for OutputConnection {} self.connect_input_to_peripheral(signal);
}
}
impl<'d> PeripheralInput<'d> for OutputConnection<'d> {
fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
match &self.0 {
OutputConnectionInner::Output(pin) => pin.connect_input_to_peripheral(signal),
OutputConnectionInner::DirectOutput(pin) => pin.connect_input_to_peripheral(signal),
OutputConnectionInner::Constant(level) => level.connect_input_to_peripheral(signal),
}
}
}
impl<'d> PeripheralOutput<'d> for OutputConnection<'d> {
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
match &self.0 {
OutputConnectionInner::Output(pin) => pin.connect_peripheral_to_output(signal),
OutputConnectionInner::DirectOutput(pin) => pin.connect_peripheral_to_output(signal),
OutputConnectionInner::Constant(level) => level.connect_peripheral_to_output(signal),
}
}
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal) {
match &self.0 {
OutputConnectionInner::Output(pin) => pin.disconnect_from_peripheral_output(signal),
OutputConnectionInner::DirectOutput(pin) => {
pin.disconnect_from_peripheral_output(signal)
}
OutputConnectionInner::Constant(level) => {
level.disconnect_from_peripheral_output(signal)
}
}
}
}
impl gpio::InputSignal { impl gpio::InputSignal {
fn can_use_gpio_matrix(self) -> bool { fn can_use_gpio_matrix(self) -> bool {
@ -91,9 +252,7 @@ impl gpio::InputSignal {
/// so if you want to disconnect it from GPIOs, you should connect it to a /// so if you want to disconnect it from GPIOs, you should connect it to a
/// constant level. /// constant level.
#[inline] #[inline]
pub fn connect_to(self, pin: impl Peripheral<P = impl PeripheralInput>) { pub fn connect_to<'d>(self, pin: &impl PeripheralInput<'d>) {
crate::into_mapped_ref!(pin);
pin.connect_input_to_peripheral(self); pin.connect_input_to_peripheral(self);
} }
} }
@ -111,17 +270,13 @@ impl gpio::OutputSignal {
/// Also note that it is possible to connect a peripheral output signal to /// Also note that it is possible to connect a peripheral output signal to
/// multiple GPIOs, and old connections will not be cleared automatically. /// multiple GPIOs, and old connections will not be cleared automatically.
#[inline] #[inline]
pub fn connect_to(self, pin: impl Peripheral<P = impl PeripheralOutput>) { pub fn connect_to<'d>(self, pin: &impl PeripheralOutput<'d>) {
crate::into_mapped_ref!(pin);
pin.connect_peripheral_to_output(self); pin.connect_peripheral_to_output(self);
} }
/// Disconnects a peripheral output signal from a GPIO. /// Disconnects a peripheral output signal from a GPIO.
#[inline] #[inline]
pub fn disconnect_from(self, pin: impl Peripheral<P = impl PeripheralOutput>) { pub fn disconnect_from<'d>(self, pin: &impl PeripheralOutput<'d>) {
crate::into_mapped_ref!(pin);
pin.disconnect_from_peripheral_output(self); pin.disconnect_from_peripheral_output(self);
} }
} }
@ -229,53 +384,66 @@ fn disconnect_peripheral_output_from_pin(pin: &AnyPin, signal: gpio::OutputSigna
/// ///
/// Multiple input signals can be connected to one pin. /// Multiple input signals can be connected to one pin.
#[instability::unstable] #[instability::unstable]
pub struct InputSignal { pub struct InputSignal<'d> {
pin: AnyPin, pin: AnyPin,
is_inverted: bool, is_inverted: bool,
_lifetime: PhantomData<&'d mut ()>,
} }
impl<P> From<P> for InputSignal impl Sealed for InputSignal<'_> {}
where
P: InputPin,
{
fn from(input: P) -> Self {
Self::new(input.degrade())
}
}
impl From<Flex<'static>> for InputSignal { impl Clone for InputSignal<'_> {
fn from(input: Flex<'static>) -> Self {
Self::new(unsafe { AnyPin::steal(input.pin.number()) })
}
}
impl Clone for InputSignal {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
pin: unsafe { self.pin.clone_unchecked() }, pin: unsafe { self.pin.clone_unchecked() },
is_inverted: self.is_inverted, is_inverted: self.is_inverted,
_lifetime: PhantomData,
} }
} }
} }
impl Peripheral for InputSignal { impl<'d, P, OP> From<P> for InputSignal<'d>
type P = Self; where
P: Peripheral<P = OP> + 'd,
unsafe fn clone_unchecked(&self) -> Self::P { OP: InputPin,
self.clone() {
fn from(output: P) -> Self {
crate::into_ref!(output);
InputSignal::new(unsafe { AnyPin::steal(output.number()) })
} }
} }
impl Sealed for InputSignal {} impl<'d> From<Flex<'d>> for InputSignal<'d> {
fn from(input: Flex<'d>) -> Self {
InputSignal::new(unsafe { AnyPin::steal(input.pin.number()) })
}
}
impl InputSignal { #[instability::unstable]
impl<'d> From<Input<'d>> for InputSignal<'d> {
fn from(input: Input<'d>) -> Self {
input.pin.into()
}
}
#[instability::unstable]
impl<'d> From<Output<'d>> for InputSignal<'d> {
fn from(output: Output<'d>) -> Self {
output.pin.into()
}
}
impl InputSignal<'static> {
pub(crate) fn new(pin: AnyPin) -> Self { pub(crate) fn new(pin: AnyPin) -> Self {
Self { Self {
pin, pin,
is_inverted: false, is_inverted: false,
_lifetime: PhantomData,
} }
} }
}
impl InputSignal<'_> {
/// Returns the GPIO number of the underlying pin. /// Returns the GPIO number of the underlying pin.
pub fn number(&self) -> u8 { pub fn number(&self) -> u8 {
self.pin.number() self.pin.number()
@ -302,15 +470,6 @@ impl InputSignal {
self self
} }
/// 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(&self, signal: gpio::InputSignal) {
connect_pin_to_input_signal(&self.pin, signal, self.is_inverted, true);
}
delegate::delegate! { delegate::delegate! {
#[doc(hidden)] #[doc(hidden)]
to self.pin { to self.pin {
@ -365,47 +524,49 @@ impl DirectInputSignal {
/// ///
/// Multiple pins can be connected to one output signal. /// Multiple pins can be connected to one output signal.
#[instability::unstable] #[instability::unstable]
pub struct OutputSignal { pub struct OutputSignal<'d> {
pin: AnyPin, pin: AnyPin,
is_inverted: bool, is_inverted: bool,
_lifetime: PhantomData<&'d mut ()>,
} }
impl<P> From<P> for OutputSignal impl Sealed for OutputSignal<'_> {}
impl<'d, P, OP> From<P> for OutputSignal<'d>
where where
P: OutputPin, P: Peripheral<P = OP> + 'd,
OP: OutputPin,
{ {
fn from(output: P) -> Self { fn from(output: P) -> Self {
Self::new(output.degrade()) crate::into_ref!(output);
OutputSignal::new(unsafe { AnyPin::steal(output.number()) })
} }
} }
impl From<Flex<'static>> for OutputSignal { impl<'d> From<Flex<'d>> for OutputSignal<'d> {
fn from(output: Flex<'static>) -> Self { fn from(output: Flex<'d>) -> Self {
Self::new(unsafe { AnyPin::steal(output.pin.number()) }) OutputSignal::new(unsafe { AnyPin::steal(output.pin.number()) })
} }
} }
impl Peripheral for OutputSignal { #[instability::unstable]
type P = Self; impl<'d> From<Output<'d>> for OutputSignal<'d> {
fn from(output: Output<'d>) -> Self {
unsafe fn clone_unchecked(&self) -> Self::P { output.pin.into()
Self {
pin: self.pin.clone_unchecked(),
is_inverted: self.is_inverted,
}
} }
} }
impl Sealed for OutputSignal {} impl OutputSignal<'static> {
impl OutputSignal {
pub(crate) fn new(pin: AnyPin) -> Self { pub(crate) fn new(pin: AnyPin) -> Self {
Self { Self {
pin, pin,
is_inverted: false, is_inverted: false,
_lifetime: PhantomData,
} }
} }
}
impl OutputSignal<'_> {
/// Returns the GPIO number of the underlying pin. /// Returns the GPIO number of the underlying pin.
pub fn number(&self) -> u8 { pub fn number(&self) -> u8 {
self.pin.number() self.pin.number()
@ -427,20 +588,6 @@ impl OutputSignal {
self self
} }
/// Connect the pin to a peripheral output signal.
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
connect_peripheral_to_output(&self.pin, signal, self.is_inverted, true, true, false);
}
/// Remove this output pin from a connected [signal](`gpio::OutputSignal`).
///
/// Clears the entry in the GPIO matrix / Io mux that associates this output
/// pin with a previously connected [signal](`gpio::OutputSignal`). Any
/// other outputs connected to the peripheral remain intact.
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal) {
disconnect_peripheral_output_from_pin(&self.pin, signal);
}
delegate::delegate! { delegate::delegate! {
#[instability::unstable] #[instability::unstable]
to self.pin { to self.pin {
@ -474,6 +621,11 @@ impl DirectOutputSignal {
Self { pin } Self { pin }
} }
/// Connect the pin to a peripheral input signal.
fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
connect_pin_to_input_signal(&self.pin, signal, false, false);
}
/// Connect the pin to a peripheral output signal. /// Connect the pin to a peripheral output signal.
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) { fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
connect_peripheral_to_output(&self.pin, signal, false, false, true, false); connect_peripheral_to_output(&self.pin, signal, false, false, true, false);
@ -509,8 +661,8 @@ impl DirectOutputSignal {
} }
#[derive(Clone)] #[derive(Clone)]
enum InputConnectionInner { enum InputConnectionInner<'d> {
Input(InputSignal), Input(InputSignal<'d>),
DirectInput(DirectInputSignal), DirectInput(DirectInputSignal),
Constant(Level), Constant(Level),
} }
@ -521,62 +673,64 @@ enum InputConnectionInner {
/// peripherals within the MCU without external hardware. /// peripherals within the MCU without external hardware.
#[derive(Clone)] #[derive(Clone)]
#[instability::unstable] #[instability::unstable]
pub struct InputConnection(InputConnectionInner); pub struct InputConnection<'d>(InputConnectionInner<'d>);
impl Sealed for InputConnection<'_> {}
impl Peripheral for InputConnection { impl<'d> From<InputSignal<'d>> for InputConnection<'d> {
type P = Self; fn from(input: InputSignal<'d>) -> Self {
unsafe fn clone_unchecked(&self) -> Self::P {
self.clone()
}
}
impl From<InputSignal> for InputConnection {
fn from(input: InputSignal) -> Self {
Self(InputConnectionInner::Input(input)) Self(InputConnectionInner::Input(input))
} }
} }
impl From<Level> for InputConnection { impl From<Level> for InputConnection<'_> {
fn from(level: Level) -> Self { fn from(level: Level) -> Self {
Self(InputConnectionInner::Constant(level)) Self(InputConnectionInner::Constant(level))
} }
} }
impl From<NoPin> for InputConnection { impl From<NoPin> for InputConnection<'_> {
fn from(_pin: NoPin) -> Self { fn from(_pin: NoPin) -> Self {
Self(InputConnectionInner::Constant(Level::Low)) Self(InputConnectionInner::Constant(Level::Low))
} }
} }
impl<P> From<P> for InputConnection impl<P, GPIO> From<P> for InputConnection<'_>
where where
P: InputPin, P: Peripheral<P = GPIO> + crate::private::Sealed,
GPIO: Pin,
{ {
fn from(input: P) -> Self { fn from(input: P) -> Self {
Self(InputConnectionInner::Input(InputSignal::from(input))) crate::into_ref!(input);
} InputConnection::from(DirectInputSignal::new(unsafe {
} AnyPin::steal(input.number())
impl From<OutputSignal> for InputConnection {
fn from(output_signal: OutputSignal) -> Self {
Self(InputConnectionInner::Input(InputSignal {
pin: output_signal.pin,
is_inverted: output_signal.is_inverted,
})) }))
} }
} }
impl From<DirectOutputSignal> for InputConnection { impl<'d> From<OutputSignal<'d>> for InputConnection<'d> {
fn from(output_signal: DirectOutputSignal) -> Self { fn from(output_signal: OutputSignal<'d>) -> Self {
Self(InputConnectionInner::DirectInput(DirectInputSignal::new( InputConnection::from(InputSignal {
output_signal.pin, pin: output_signal.pin,
))) is_inverted: output_signal.is_inverted,
_lifetime: PhantomData,
})
} }
} }
impl From<OutputConnection> for InputConnection { impl From<DirectInputSignal> for InputConnection<'static> {
fn from(conn: OutputConnection) -> Self { fn from(input_signal: DirectInputSignal) -> Self {
InputConnection(InputConnectionInner::DirectInput(input_signal))
}
}
impl From<DirectOutputSignal> for InputConnection<'static> {
fn from(output_signal: DirectOutputSignal) -> Self {
InputConnection::from(DirectInputSignal::new(output_signal.pin))
}
}
impl<'d> From<OutputConnection<'d>> for InputConnection<'d> {
fn from(conn: OutputConnection<'d>) -> Self {
match conn.0 { match conn.0 {
OutputConnectionInner::Output(inner) => inner.into(), OutputConnectionInner::Output(inner) => inner.into(),
OutputConnectionInner::DirectOutput(inner) => inner.into(), OutputConnectionInner::DirectOutput(inner) => inner.into(),
@ -585,15 +739,27 @@ impl From<OutputConnection> for InputConnection {
} }
} }
impl From<Flex<'static>> for InputConnection { impl<'d> From<Flex<'d>> for InputConnection<'d> {
fn from(pin: Flex<'static>) -> Self { fn from(pin: Flex<'d>) -> Self {
pin.peripheral_input().into() pin.peripheral_input().into()
} }
} }
impl Sealed for InputConnection {} #[instability::unstable]
impl<'d> From<Input<'d>> for InputConnection<'d> {
fn from(pin: Input<'d>) -> Self {
pin.pin.into()
}
}
impl InputConnection { #[instability::unstable]
impl<'d> From<Output<'d>> for InputConnection<'d> {
fn from(pin: Output<'d>) -> Self {
pin.pin.into()
}
}
impl InputConnection<'_> {
delegate::delegate! { delegate::delegate! {
#[instability::unstable] #[instability::unstable]
to match &self.0 { to match &self.0 {
@ -613,8 +779,8 @@ impl InputConnection {
} }
} }
enum OutputConnectionInner { enum OutputConnectionInner<'d> {
Output(OutputSignal), Output(OutputSignal<'d>),
DirectOutput(DirectOutputSignal), DirectOutput(DirectOutputSignal),
Constant(Level), Constant(Level),
} }
@ -624,64 +790,60 @@ enum OutputConnectionInner {
/// This is mainly intended for internal use, but it can be used to connect /// This is mainly intended for internal use, but it can be used to connect
/// peripherals within the MCU without external hardware. /// peripherals within the MCU without external hardware.
#[instability::unstable] #[instability::unstable]
pub struct OutputConnection(OutputConnectionInner); pub struct OutputConnection<'d>(OutputConnectionInner<'d>);
impl Sealed for OutputConnection<'_> {}
impl Sealed for OutputConnection {} impl<'d> From<OutputSignal<'d>> for OutputConnection<'d> {
fn from(signal: OutputSignal<'d>) -> Self {
impl Peripheral for OutputConnection { Self(OutputConnectionInner::Output(signal))
type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P {
match self {
Self(OutputConnectionInner::Output(signal)) => Self::from(signal.clone_unchecked()),
Self(OutputConnectionInner::DirectOutput(signal)) => {
Self::from(DirectOutputSignal::new(signal.pin.clone_unchecked()))
}
Self(OutputConnectionInner::Constant(level)) => Self::from(*level),
}
} }
} }
impl From<NoPin> for OutputConnection { impl From<NoPin> for OutputConnection<'_> {
fn from(_pin: NoPin) -> Self { fn from(_pin: NoPin) -> Self {
Self(OutputConnectionInner::Constant(Level::Low)) Self(OutputConnectionInner::Constant(Level::Low))
} }
} }
impl From<Level> for OutputConnection { impl From<Level> for OutputConnection<'_> {
fn from(level: Level) -> Self { fn from(level: Level) -> Self {
Self(OutputConnectionInner::Constant(level)) Self(OutputConnectionInner::Constant(level))
} }
} }
impl<P> From<P> for OutputConnection impl<P, OP> From<P> for OutputConnection<'_>
where where
P: OutputPin, P: Peripheral<P = OP> + crate::private::Sealed,
OP: OutputPin,
{ {
fn from(input: P) -> Self { fn from(output: P) -> Self {
Self(OutputConnectionInner::Output(OutputSignal::from(input))) crate::into_ref!(output);
OutputConnection::from(DirectOutputSignal::new(unsafe {
AnyPin::steal(output.number())
}))
} }
} }
impl From<OutputSignal> for OutputConnection { impl<'d> From<Flex<'d>> for OutputConnection<'d> {
fn from(signal: OutputSignal) -> Self { fn from(pin: Flex<'d>) -> Self {
Self(OutputConnectionInner::Output(signal))
}
}
impl From<Flex<'static>> for OutputConnection {
fn from(pin: Flex<'static>) -> Self {
pin.into_peripheral_output().into() pin.into_peripheral_output().into()
} }
} }
impl From<DirectOutputSignal> for OutputConnection { #[instability::unstable]
impl<'d> From<Output<'d>> for OutputConnection<'d> {
fn from(pin: Output<'d>) -> Self {
pin.pin.into()
}
}
impl From<DirectOutputSignal> for OutputConnection<'static> {
fn from(signal: DirectOutputSignal) -> Self { fn from(signal: DirectOutputSignal) -> Self {
Self(OutputConnectionInner::DirectOutput(signal)) Self(OutputConnectionInner::DirectOutput(signal))
} }
} }
impl OutputConnection { impl OutputConnection<'_> {
delegate::delegate! { delegate::delegate! {
#[instability::unstable] #[instability::unstable]
to match &self.0 { to match &self.0 {
@ -704,25 +866,13 @@ impl OutputConnection {
pub fn set_output_high(&self, on: bool); pub fn set_output_high(&self, on: bool);
pub fn set_drive_strength(&self, strength: gpio::DriveStrength); pub fn set_drive_strength(&self, strength: gpio::DriveStrength);
pub fn enable_open_drain(&self, on: bool); pub fn enable_open_drain(&self, on: bool);
// These don't need to be public, the intended way is `connect_to` and `disconnect_from`
fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal);
fn disconnect_from_peripheral_output(&self, signal: gpio::OutputSignal);
} }
} }
pub(crate) fn connect_with_guard( pub(crate) fn connect_with_guard(self, signal: crate::gpio::OutputSignal) -> PinGuard {
this: impl Peripheral<P = impl PeripheralOutput>, match self.0 {
signal: crate::gpio::OutputSignal, OutputConnectionInner::Output(pin) => PinGuard::new(pin.pin, signal),
) -> PinGuard { OutputConnectionInner::DirectOutput(pin) => PinGuard::new(pin.pin, signal),
crate::into_mapped_ref!(this);
match &this.0 {
OutputConnectionInner::Output(pin) => {
PinGuard::new(unsafe { pin.pin.clone_unchecked() }, signal)
}
OutputConnectionInner::DirectOutput(pin) => {
PinGuard::new(unsafe { pin.pin.clone_unchecked() }, signal)
}
OutputConnectionInner::Constant(_) => PinGuard::new_unconnected(signal), OutputConnectionInner::Constant(_) => PinGuard::new_unconnected(signal),
} }
} }

View File

@ -132,22 +132,13 @@ pub(crate) struct PinGuard {
} }
impl crate::private::Sealed for PinGuard {} impl crate::private::Sealed for PinGuard {}
impl Peripheral for PinGuard {
type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P {
Self {
pin: self.pin,
signal: self.signal,
}
}
}
impl PinGuard { impl PinGuard {
pub(crate) fn new(mut pin: AnyPin, signal: OutputSignal) -> Self { pub(crate) fn new(pin: AnyPin, signal: OutputSignal) -> Self {
signal.connect_to(&mut pin); let number = pin.number();
signal.connect_to(&pin.into_ref());
Self { Self {
pin: pin.number(), pin: number,
signal, signal,
} }
} }
@ -163,8 +154,8 @@ impl PinGuard {
impl Drop for PinGuard { impl Drop for PinGuard {
fn drop(&mut self) { fn drop(&mut self) {
if self.pin != u8::MAX { if self.pin != u8::MAX {
let mut pin = unsafe { AnyPin::steal(self.pin) }; let pin = unsafe { AnyPin::steal(self.pin) };
self.signal.disconnect_from(&mut pin); self.signal.disconnect_from(&pin.into_ref());
} }
} }
} }
@ -650,7 +641,12 @@ where
/// # } /// # }
/// ``` /// ```
#[instability::unstable] #[instability::unstable]
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) { pub fn split(
self,
) -> (
interconnect::InputSignal<'static>,
interconnect::OutputSignal<'static>,
) {
// FIXME: we should implement this in the gpio macro for output pins, but we // FIXME: we should implement this in the gpio macro for output pins, but we
// should also have an input-only alternative for pins that can't be used as // should also have an input-only alternative for pins that can't be used as
// outputs. // outputs.
@ -689,7 +685,7 @@ fn disable_usb_pads(gpionum: u8) {
} }
} }
impl<const GPIONUM: u8> Peripheral for GpioPin<GPIONUM> unsafe impl<const GPIONUM: u8> Peripheral for GpioPin<GPIONUM>
where where
Self: Pin, Self: Pin,
{ {
@ -963,7 +959,7 @@ macro_rules! gpio {
} }
)+ )+
impl $crate::peripheral::Peripheral for $crate::gpio::AnyPin { unsafe impl $crate::peripheral::Peripheral for $crate::gpio::AnyPin {
type P = $crate::gpio::AnyPin; type P = $crate::gpio::AnyPin;
unsafe fn clone_unchecked(&self) -> Self { unsafe fn clone_unchecked(&self) -> Self {
Self(self.0) Self(self.0)
@ -1150,13 +1146,6 @@ pub struct Output<'d> {
impl private::Sealed for Output<'_> {} impl private::Sealed for Output<'_> {}
impl<'d> Peripheral for Output<'d> {
type P = Flex<'d>;
unsafe fn clone_unchecked(&self) -> Self::P {
self.pin.clone_unchecked()
}
}
impl<'d> Output<'d> { impl<'d> Output<'d> {
/// Creates a new GPIO output driver. /// Creates a new GPIO output driver.
/// ///
@ -1222,7 +1211,12 @@ impl<'d> Output<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) { pub fn split(
self,
) -> (
interconnect::InputSignal<'d>,
interconnect::OutputSignal<'d>,
) {
self.pin.split() self.pin.split()
} }
@ -1242,7 +1236,7 @@ impl<'d> Output<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn peripheral_input(&self) -> interconnect::InputSignal { pub fn peripheral_input(&self) -> interconnect::InputSignal<'d> {
self.pin.peripheral_input() self.pin.peripheral_input()
} }
@ -1262,7 +1256,7 @@ impl<'d> Output<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal { pub fn into_peripheral_output(self) -> interconnect::OutputSignal<'d> {
self.pin.into_peripheral_output() self.pin.into_peripheral_output()
} }
@ -1361,13 +1355,6 @@ pub struct Input<'d> {
impl private::Sealed for Input<'_> {} impl private::Sealed for Input<'_> {}
impl<'d> Peripheral for Input<'d> {
type P = Flex<'d>;
unsafe fn clone_unchecked(&self) -> Self::P {
self.pin.clone_unchecked()
}
}
impl<'d> Input<'d> { impl<'d> Input<'d> {
/// Creates a new GPIO input. /// Creates a new GPIO input.
/// ///
@ -1432,7 +1419,7 @@ impl<'d> Input<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn peripheral_input(&self) -> interconnect::InputSignal { pub fn peripheral_input(&self) -> interconnect::InputSignal<'d> {
self.pin.peripheral_input() self.pin.peripheral_input()
} }
@ -1586,7 +1573,12 @@ impl<'d> Input<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) { pub fn split(
self,
) -> (
interconnect::InputSignal<'d>,
interconnect::OutputSignal<'d>,
) {
self.pin.split() self.pin.split()
} }
@ -1607,7 +1599,7 @@ impl<'d> Input<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal { pub fn into_peripheral_output(self) -> interconnect::OutputSignal<'d> {
self.pin.into_peripheral_output() self.pin.into_peripheral_output()
} }
@ -1630,15 +1622,6 @@ pub struct Flex<'d> {
impl private::Sealed for Flex<'_> {} impl private::Sealed for Flex<'_> {}
impl Peripheral for Flex<'_> {
type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P {
Self {
pin: PeripheralRef::new(AnyPin(self.pin.number())),
}
}
}
impl<'d> Flex<'d> { impl<'d> Flex<'d> {
/// Create flexible pin driver for a [Pin]. /// Create flexible pin driver for a [Pin].
/// No mode change happens. /// No mode change happens.
@ -1683,7 +1666,7 @@ impl<'d> Flex<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn peripheral_input(&self) -> interconnect::InputSignal { pub fn peripheral_input(&self) -> interconnect::InputSignal<'d> {
unsafe { AnyPin::steal(self.number()) }.split().0 unsafe { AnyPin::steal(self.number()) }.split().0
} }
@ -1919,7 +1902,12 @@ impl<'d> Flex<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) { pub fn split(
self,
) -> (
interconnect::InputSignal<'d>,
interconnect::OutputSignal<'d>,
) {
assert!(self.pin.is_output()); assert!(self.pin.is_output());
unsafe { AnyPin::steal(self.number()) }.split() unsafe { AnyPin::steal(self.number()) }.split()
} }
@ -1940,7 +1928,7 @@ impl<'d> Flex<'d> {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn into_peripheral_output(self) -> interconnect::OutputSignal { pub fn into_peripheral_output(self) -> interconnect::OutputSignal<'d> {
self.split().1 self.split().1
} }
} }
@ -1986,7 +1974,12 @@ impl AnyPin {
/// ``` /// ```
#[inline] #[inline]
#[instability::unstable] #[instability::unstable]
pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) { pub fn split(
self,
) -> (
interconnect::InputSignal<'static>,
interconnect::OutputSignal<'static>,
) {
assert!(self.is_output()); assert!(self.is_output());
( (
interconnect::InputSignal::new(Self(self.0)), interconnect::InputSignal::new(Self(self.0)),

View File

@ -6,15 +6,6 @@
// polluting the main module. // polluting the main module.
use super::*; use super::*;
use crate::gpio::interconnect::connect_input_signal;
impl crate::peripheral::Peripheral for Level {
type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P {
*self
}
}
impl Level { impl Level {
pub(crate) fn pull_direction(&self, _pull: Pull) {} pub(crate) fn pull_direction(&self, _pull: Pull) {}
@ -34,15 +25,6 @@ impl Level {
*self == Level::High *self == Level::High
} }
pub(crate) fn connect_input_to_peripheral(&self, signal: InputSignal) {
let value = match self {
Level::High => ONE_INPUT,
Level::Low => ZERO_INPUT,
};
connect_input_signal(signal, value, false, true);
}
pub(crate) fn set_to_open_drain_output(&self) {} pub(crate) fn set_to_open_drain_output(&self) {}
pub(crate) fn set_to_push_pull_output(&self) {} pub(crate) fn set_to_push_pull_output(&self) {}
pub(crate) fn enable_output(&self, _on: bool) {} pub(crate) fn enable_output(&self, _on: bool) {}
@ -60,10 +42,6 @@ impl Level {
) -> &'static [(AlternateFunction, OutputSignal)] { ) -> &'static [(AlternateFunction, OutputSignal)] {
&[] &[]
} }
pub(crate) fn connect_peripheral_to_output(&self, _signal: OutputSignal) {}
pub(crate) fn disconnect_from_peripheral_output(&self, _signal: OutputSignal) {}
} }
/// Placeholder pin, used when no pin is required when using a peripheral. /// Placeholder pin, used when no pin is required when using a peripheral.
@ -72,14 +50,6 @@ impl Level {
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
pub struct NoPin; pub struct NoPin;
impl crate::peripheral::Peripheral for NoPin {
type P = Self;
unsafe fn clone_unchecked(&self) -> Self::P {
Self
}
}
impl private::Sealed for NoPin {} impl private::Sealed for NoPin {}
impl embedded_hal::digital::ErrorType for NoPin { impl embedded_hal::digital::ErrorType for NoPin {

View File

@ -917,7 +917,7 @@ where
/// Connect a pin to the I2C SDA signal. /// Connect a pin to the I2C SDA signal.
/// ///
/// This will replace previous pin assignments for this signal. /// This will replace previous pin assignments for this signal.
pub fn with_sda(mut self, sda: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_sda(mut self, sda: impl PeripheralOutput<'d>) -> Self {
let info = self.driver().info; let info = self.driver().info;
let input = info.sda_input; let input = info.sda_input;
let output = info.sda_output; let output = info.sda_output;
@ -929,7 +929,7 @@ where
/// Connect a pin to the I2C SCL signal. /// Connect a pin to the I2C SCL signal.
/// ///
/// This will replace previous pin assignments for this signal. /// This will replace previous pin assignments for this signal.
pub fn with_scl(mut self, scl: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_scl(mut self, scl: impl PeripheralOutput<'d>) -> Self {
let info = self.driver().info; let info = self.driver().info;
let input = info.scl_input; let input = info.scl_input;
let output = info.scl_output; let output = info.scl_output;
@ -939,12 +939,12 @@ where
} }
fn connect_pin( fn connect_pin(
pin: impl Peripheral<P = impl PeripheralOutput> + 'd, pin: impl PeripheralOutput<'d>,
input: InputSignal, input: InputSignal,
output: OutputSignal, output: OutputSignal,
guard: &mut PinGuard, guard: &mut PinGuard,
) { ) {
crate::into_mapped_ref!(pin); let pin = pin.into();
// avoid the pin going low during configuration // avoid the pin going low during configuration
pin.set_output_high(true); pin.set_output_high(true);
@ -952,7 +952,7 @@ where
pin.enable_input(true); pin.enable_input(true);
pin.pull_direction(Pull::Up); pin.pull_direction(Pull::Up);
input.connect_to(pin.reborrow()); input.connect_to(&pin);
*guard = OutputConnection::connect_with_guard(pin, output); *guard = OutputConnection::connect_with_guard(pin, output);
} }

View File

@ -403,10 +403,10 @@ where
Dm: DriverMode, Dm: DriverMode,
{ {
/// Configures the I2S peripheral to use a master clock (MCLK) output pin. /// Configures the I2S peripheral to use a master clock (MCLK) output pin.
pub fn with_mclk<P: PeripheralOutput>(self, pin: impl Peripheral<P = P> + 'd) -> Self { pub fn with_mclk(self, mclk: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let mclk = mclk.into();
pin.set_to_push_pull_output(); mclk.set_to_push_pull_output();
self.i2s_tx.i2s.mclk_signal().connect_to(pin); self.i2s_tx.i2s.mclk_signal().connect_to(&mclk);
self self
} }
@ -729,35 +729,26 @@ mod private {
} }
} }
pub fn with_bclk<P>(self, pin: impl Peripheral<P = P> + 'd) -> Self pub fn with_bclk(self, bclk: impl PeripheralOutput<'d>) -> Self {
where let bclk = bclk.into();
P: PeripheralOutput, bclk.set_to_push_pull_output();
{ self.i2s.bclk_signal().connect_to(&bclk);
crate::into_mapped_ref!(pin);
pin.set_to_push_pull_output();
self.i2s.bclk_signal().connect_to(pin);
self self
} }
pub fn with_ws<P>(self, pin: impl Peripheral<P = P> + 'd) -> Self pub fn with_ws(self, ws: impl PeripheralOutput<'d>) -> Self {
where let ws = ws.into();
P: PeripheralOutput, ws.set_to_push_pull_output();
{ self.i2s.ws_signal().connect_to(&ws);
crate::into_mapped_ref!(pin);
pin.set_to_push_pull_output();
self.i2s.ws_signal().connect_to(pin);
self self
} }
pub fn with_dout<P>(self, pin: impl Peripheral<P = P> + 'd) -> Self pub fn with_dout(self, dout: impl PeripheralOutput<'d>) -> Self {
where let dout = dout.into();
P: PeripheralOutput, dout.set_to_push_pull_output();
{ self.i2s.dout_signal().connect_to(&dout);
crate::into_mapped_ref!(pin);
pin.set_to_push_pull_output();
self.i2s.dout_signal().connect_to(pin);
self self
} }
@ -787,35 +778,26 @@ mod private {
} }
} }
pub fn with_bclk<P>(self, pin: impl Peripheral<P = P> + 'd) -> Self pub fn with_bclk(self, bclk: impl PeripheralOutput<'d>) -> Self {
where let bclk = bclk.into();
P: PeripheralOutput, bclk.set_to_push_pull_output();
{ self.i2s.bclk_rx_signal().connect_to(&bclk);
crate::into_mapped_ref!(pin);
pin.set_to_push_pull_output();
self.i2s.bclk_rx_signal().connect_to(pin);
self self
} }
pub fn with_ws<P>(self, pin: impl Peripheral<P = P> + 'd) -> Self pub fn with_ws(self, ws: impl PeripheralOutput<'d>) -> Self {
where let ws = ws.into();
P: PeripheralOutput, ws.set_to_push_pull_output();
{ self.i2s.ws_rx_signal().connect_to(&ws);
crate::into_mapped_ref!(pin);
pin.set_to_push_pull_output();
self.i2s.ws_rx_signal().connect_to(pin);
self self
} }
pub fn with_din<P>(self, pin: impl Peripheral<P = P> + 'd) -> Self pub fn with_din(self, din: impl PeripheralInput<'d>) -> Self {
where let din = din.into();
P: PeripheralInput, din.init_input(crate::gpio::Pull::None);
{ self.i2s.din_signal().connect_to(&din);
crate::into_mapped_ref!(pin);
pin.init_input(crate::gpio::Pull::None);
self.i2s.din_signal().connect_to(pin);
self self
} }

View File

@ -138,39 +138,48 @@ pub trait TxPins<'d> {
/// Represents a group of 16 output pins configured for 16-bit parallel data /// Represents a group of 16 output pins configured for 16-bit parallel data
/// transmission. /// transmission.
pub struct TxSixteenBits<'d> { pub struct TxSixteenBits<'d> {
pins: [PeripheralRef<'d, OutputConnection>; 16], pins: [OutputConnection<'d>; 16],
} }
impl<'d> TxSixteenBits<'d> { impl<'d> TxSixteenBits<'d> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
/// Creates a new `TxSixteenBits` instance with the provided output pins. /// Creates a new `TxSixteenBits` instance with the provided output pins.
pub fn new( pub fn new(
pin_0: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_0: impl PeripheralOutput<'d>,
pin_1: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_1: impl PeripheralOutput<'d>,
pin_2: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_2: impl PeripheralOutput<'d>,
pin_3: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_3: impl PeripheralOutput<'d>,
pin_4: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_4: impl PeripheralOutput<'d>,
pin_5: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_5: impl PeripheralOutput<'d>,
pin_6: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_6: impl PeripheralOutput<'d>,
pin_7: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_7: impl PeripheralOutput<'d>,
pin_8: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_8: impl PeripheralOutput<'d>,
pin_9: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_9: impl PeripheralOutput<'d>,
pin_10: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_10: impl PeripheralOutput<'d>,
pin_11: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_11: impl PeripheralOutput<'d>,
pin_12: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_12: impl PeripheralOutput<'d>,
pin_13: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_13: impl PeripheralOutput<'d>,
pin_14: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_14: impl PeripheralOutput<'d>,
pin_15: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_15: impl PeripheralOutput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(
pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7, pin_8, pin_9, pin_10, pin_11,
pin_12, pin_13, pin_14, pin_15
);
Self { Self {
pins: [ pins: [
pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7, pin_8, pin_9, pin_10, pin_0.into(),
pin_11, pin_12, pin_13, pin_14, pin_15, pin_1.into(),
pin_2.into(),
pin_3.into(),
pin_4.into(),
pin_5.into(),
pin_6.into(),
pin_7.into(),
pin_8.into(),
pin_9.into(),
pin_10.into(),
pin_11.into(),
pin_12.into(),
pin_13.into(),
pin_14.into(),
pin_15.into(),
], ],
} }
} }
@ -194,26 +203,33 @@ impl<'d> TxPins<'d> for TxSixteenBits<'d> {
/// Represents a group of 8 output pins configured for 8-bit parallel data /// Represents a group of 8 output pins configured for 8-bit parallel data
/// transmission. /// transmission.
pub struct TxEightBits<'d> { pub struct TxEightBits<'d> {
pins: [PeripheralRef<'d, OutputConnection>; 8], pins: [OutputConnection<'d>; 8],
} }
impl<'d> TxEightBits<'d> { impl<'d> TxEightBits<'d> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
/// Creates a new `TxSEightBits` instance with the provided output pins. /// Creates a new `TxSEightBits` instance with the provided output pins.
pub fn new( pub fn new(
pin_0: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_0: impl PeripheralOutput<'d>,
pin_1: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_1: impl PeripheralOutput<'d>,
pin_2: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_2: impl PeripheralOutput<'d>,
pin_3: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_3: impl PeripheralOutput<'d>,
pin_4: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_4: impl PeripheralOutput<'d>,
pin_5: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_5: impl PeripheralOutput<'d>,
pin_6: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_6: impl PeripheralOutput<'d>,
pin_7: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_7: impl PeripheralOutput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7);
Self { Self {
pins: [pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7], pins: [
pin_0.into(),
pin_1.into(),
pin_2.into(),
pin_3.into(),
pin_4.into(),
pin_5.into(),
pin_6.into(),
pin_7.into(),
],
} }
} }
} }
@ -250,13 +266,12 @@ impl<'d> I2sParallel<'d, Blocking> {
channel: impl Peripheral<P = CH> + 'd, channel: impl Peripheral<P = CH> + 'd,
frequency: Rate, frequency: Rate,
mut pins: impl TxPins<'d>, mut pins: impl TxPins<'d>,
clock_pin: impl Peripheral<P = impl PeripheralOutput> + 'd, clock_pin: impl PeripheralOutput<'d>,
) -> Self ) -> Self
where where
CH: DmaChannelFor<AnyI2s>, CH: DmaChannelFor<AnyI2s>,
{ {
crate::into_mapped_ref!(i2s); crate::into_mapped_ref!(i2s);
crate::into_mapped_ref!(clock_pin);
let channel = Channel::new(channel.map(|ch| ch.degrade())); let channel = Channel::new(channel.map(|ch| ch.degrade()));
channel.runtime_ensure_compatible(&i2s); channel.runtime_ensure_compatible(&i2s);
@ -266,8 +281,9 @@ impl<'d> I2sParallel<'d, Blocking> {
// configure the I2S peripheral for parallel mode // configure the I2S peripheral for parallel mode
i2s.setup(frequency, pins.bus_width()); i2s.setup(frequency, pins.bus_width());
// setup the clock pin // setup the clock pin
let clock_pin = clock_pin.into();
clock_pin.set_to_push_pull_output(); clock_pin.set_to_push_pull_output();
i2s.ws_signal().connect_to(clock_pin); i2s.ws_signal().connect_to(&clock_pin);
pins.configure(i2s.reborrow()); pins.configure(i2s.reborrow());
Self { Self {

View File

@ -139,7 +139,7 @@ impl<const NUM: u8> SoftwareInterrupt<NUM> {
} }
} }
impl<const NUM: u8> crate::peripheral::Peripheral for SoftwareInterrupt<NUM> { unsafe impl<const NUM: u8> crate::peripheral::Peripheral for SoftwareInterrupt<NUM> {
type P = SoftwareInterrupt<NUM>; type P = SoftwareInterrupt<NUM>;
#[inline] #[inline]

View File

@ -228,44 +228,38 @@ impl<'d> Camera<'d> {
impl<'d> Camera<'d> { impl<'d> Camera<'d> {
/// Configures the master clock (MCLK) pin for the camera interface. /// Configures the master clock (MCLK) pin for the camera interface.
pub fn with_master_clock<MCLK: PeripheralOutput>( pub fn with_master_clock(self, mclk: impl PeripheralOutput<'d>) -> Self {
self, let mclk = mclk.into();
mclk: impl Peripheral<P = MCLK> + 'd,
) -> Self {
crate::into_mapped_ref!(mclk);
mclk.set_to_push_pull_output(); mclk.set_to_push_pull_output();
OutputSignal::CAM_CLK.connect_to(mclk); OutputSignal::CAM_CLK.connect_to(&mclk);
self self
} }
/// Configures the pixel clock (PCLK) pin for the camera interface. /// Configures the pixel clock (PCLK) pin for the camera interface.
pub fn with_pixel_clock<PCLK: PeripheralInput>( pub fn with_pixel_clock(self, pclk: impl PeripheralInput<'d>) -> Self {
self, let pclk = pclk.into();
pclk: impl Peripheral<P = PCLK> + 'd,
) -> Self {
crate::into_mapped_ref!(pclk);
pclk.init_input(Pull::None); pclk.init_input(Pull::None);
InputSignal::CAM_PCLK.connect_to(pclk); InputSignal::CAM_PCLK.connect_to(&pclk);
self self
} }
/// Configures the control pins for the camera interface (VSYNC and /// Configures the control pins for the camera interface (VSYNC and
/// HENABLE). /// HENABLE).
pub fn with_ctrl_pins<VSYNC: PeripheralInput, HENABLE: PeripheralInput>( pub fn with_ctrl_pins(
self, self,
vsync: impl Peripheral<P = VSYNC> + 'd, vsync: impl PeripheralInput<'d>,
h_enable: impl Peripheral<P = HENABLE> + 'd, h_enable: impl PeripheralInput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(vsync, h_enable); let vsync = vsync.into();
let h_enable = h_enable.into();
vsync.init_input(Pull::None); vsync.init_input(Pull::None);
InputSignal::CAM_V_SYNC.connect_to(vsync); InputSignal::CAM_V_SYNC.connect_to(&vsync);
h_enable.init_input(Pull::None); h_enable.init_input(Pull::None);
InputSignal::CAM_H_ENABLE.connect_to(h_enable); InputSignal::CAM_H_ENABLE.connect_to(&h_enable);
self.regs() self.regs()
.cam_ctrl1() .cam_ctrl1()
@ -276,24 +270,22 @@ impl<'d> Camera<'d> {
/// Configures the control pins for the camera interface (VSYNC, HSYNC, and /// Configures the control pins for the camera interface (VSYNC, HSYNC, and
/// HENABLE) with DE (data enable). /// HENABLE) with DE (data enable).
pub fn with_ctrl_pins_and_de< pub fn with_ctrl_pins_and_de(
VSYNC: PeripheralInput,
HSYNC: PeripheralInput,
HENABLE: PeripheralInput,
>(
self, self,
vsync: impl Peripheral<P = VSYNC> + 'd, vsync: impl PeripheralInput<'d>,
hsync: impl Peripheral<P = HSYNC> + 'd, hsync: impl PeripheralInput<'d>,
h_enable: impl Peripheral<P = HENABLE> + 'd, h_enable: impl PeripheralInput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(vsync, hsync, h_enable); let vsync = vsync.into();
let hsync = hsync.into();
let h_enable = h_enable.into();
vsync.init_input(Pull::None); vsync.init_input(Pull::None);
InputSignal::CAM_V_SYNC.connect_to(vsync); InputSignal::CAM_V_SYNC.connect_to(&vsync);
hsync.init_input(Pull::None); hsync.init_input(Pull::None);
InputSignal::CAM_H_SYNC.connect_to(hsync); InputSignal::CAM_H_SYNC.connect_to(&hsync);
h_enable.init_input(Pull::None); h_enable.init_input(Pull::None);
InputSignal::CAM_H_ENABLE.connect_to(h_enable); InputSignal::CAM_H_ENABLE.connect_to(&h_enable);
self.regs() self.regs()
.cam_ctrl1() .cam_ctrl1()
@ -477,38 +469,29 @@ impl RxEightBits {
/// Creates a new instance of `RxEightBits`, configuring the specified pins /// Creates a new instance of `RxEightBits`, configuring the specified pins
/// as the 8-bit data bus. /// as the 8-bit data bus.
pub fn new<'d>( pub fn new<'d>(
pin_0: impl Peripheral<P = impl PeripheralInput> + 'd, pin_0: impl PeripheralInput<'d>,
pin_1: impl Peripheral<P = impl PeripheralInput> + 'd, pin_1: impl PeripheralInput<'d>,
pin_2: impl Peripheral<P = impl PeripheralInput> + 'd, pin_2: impl PeripheralInput<'d>,
pin_3: impl Peripheral<P = impl PeripheralInput> + 'd, pin_3: impl PeripheralInput<'d>,
pin_4: impl Peripheral<P = impl PeripheralInput> + 'd, pin_4: impl PeripheralInput<'d>,
pin_5: impl Peripheral<P = impl PeripheralInput> + 'd, pin_5: impl PeripheralInput<'d>,
pin_6: impl Peripheral<P = impl PeripheralInput> + 'd, pin_6: impl PeripheralInput<'d>,
pin_7: impl Peripheral<P = impl PeripheralInput> + 'd, pin_7: impl PeripheralInput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(pin_0);
crate::into_mapped_ref!(pin_1);
crate::into_mapped_ref!(pin_2);
crate::into_mapped_ref!(pin_3);
crate::into_mapped_ref!(pin_4);
crate::into_mapped_ref!(pin_5);
crate::into_mapped_ref!(pin_6);
crate::into_mapped_ref!(pin_7);
let pairs = [ let pairs = [
(pin_0, InputSignal::CAM_DATA_0), (pin_0.into(), InputSignal::CAM_DATA_0),
(pin_1, InputSignal::CAM_DATA_1), (pin_1.into(), InputSignal::CAM_DATA_1),
(pin_2, InputSignal::CAM_DATA_2), (pin_2.into(), InputSignal::CAM_DATA_2),
(pin_3, InputSignal::CAM_DATA_3), (pin_3.into(), InputSignal::CAM_DATA_3),
(pin_4, InputSignal::CAM_DATA_4), (pin_4.into(), InputSignal::CAM_DATA_4),
(pin_5, InputSignal::CAM_DATA_5), (pin_5.into(), InputSignal::CAM_DATA_5),
(pin_6, InputSignal::CAM_DATA_6), (pin_6.into(), InputSignal::CAM_DATA_6),
(pin_7, InputSignal::CAM_DATA_7), (pin_7.into(), InputSignal::CAM_DATA_7),
]; ];
for (pin, signal) in pairs.into_iter() { for (pin, signal) in pairs.into_iter() {
pin.init_input(Pull::None); pin.init_input(Pull::None);
signal.connect_to(pin); signal.connect_to(&pin);
} }
Self { _pins: () } Self { _pins: () }
@ -530,62 +513,45 @@ impl RxSixteenBits {
/// Creates a new instance of `RxSixteenBits`, configuring the specified /// Creates a new instance of `RxSixteenBits`, configuring the specified
/// pins as the 16-bit data bus. /// pins as the 16-bit data bus.
pub fn new<'d>( pub fn new<'d>(
pin_0: impl Peripheral<P = impl PeripheralInput> + 'd, pin_0: impl PeripheralInput<'d>,
pin_1: impl Peripheral<P = impl PeripheralInput> + 'd, pin_1: impl PeripheralInput<'d>,
pin_2: impl Peripheral<P = impl PeripheralInput> + 'd, pin_2: impl PeripheralInput<'d>,
pin_3: impl Peripheral<P = impl PeripheralInput> + 'd, pin_3: impl PeripheralInput<'d>,
pin_4: impl Peripheral<P = impl PeripheralInput> + 'd, pin_4: impl PeripheralInput<'d>,
pin_5: impl Peripheral<P = impl PeripheralInput> + 'd, pin_5: impl PeripheralInput<'d>,
pin_6: impl Peripheral<P = impl PeripheralInput> + 'd, pin_6: impl PeripheralInput<'d>,
pin_7: impl Peripheral<P = impl PeripheralInput> + 'd, pin_7: impl PeripheralInput<'d>,
pin_8: impl Peripheral<P = impl PeripheralInput> + 'd, pin_8: impl PeripheralInput<'d>,
pin_9: impl Peripheral<P = impl PeripheralInput> + 'd, pin_9: impl PeripheralInput<'d>,
pin_10: impl Peripheral<P = impl PeripheralInput> + 'd, pin_10: impl PeripheralInput<'d>,
pin_11: impl Peripheral<P = impl PeripheralInput> + 'd, pin_11: impl PeripheralInput<'d>,
pin_12: impl Peripheral<P = impl PeripheralInput> + 'd, pin_12: impl PeripheralInput<'d>,
pin_13: impl Peripheral<P = impl PeripheralInput> + 'd, pin_13: impl PeripheralInput<'d>,
pin_14: impl Peripheral<P = impl PeripheralInput> + 'd, pin_14: impl PeripheralInput<'d>,
pin_15: impl Peripheral<P = impl PeripheralInput> + 'd, pin_15: impl PeripheralInput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(pin_0);
crate::into_mapped_ref!(pin_1);
crate::into_mapped_ref!(pin_2);
crate::into_mapped_ref!(pin_3);
crate::into_mapped_ref!(pin_4);
crate::into_mapped_ref!(pin_5);
crate::into_mapped_ref!(pin_6);
crate::into_mapped_ref!(pin_7);
crate::into_mapped_ref!(pin_8);
crate::into_mapped_ref!(pin_9);
crate::into_mapped_ref!(pin_10);
crate::into_mapped_ref!(pin_11);
crate::into_mapped_ref!(pin_12);
crate::into_mapped_ref!(pin_13);
crate::into_mapped_ref!(pin_14);
crate::into_mapped_ref!(pin_15);
let pairs = [ let pairs = [
(pin_0, InputSignal::CAM_DATA_0), (pin_0.into(), InputSignal::CAM_DATA_0),
(pin_1, InputSignal::CAM_DATA_1), (pin_1.into(), InputSignal::CAM_DATA_1),
(pin_2, InputSignal::CAM_DATA_2), (pin_2.into(), InputSignal::CAM_DATA_2),
(pin_3, InputSignal::CAM_DATA_3), (pin_3.into(), InputSignal::CAM_DATA_3),
(pin_4, InputSignal::CAM_DATA_4), (pin_4.into(), InputSignal::CAM_DATA_4),
(pin_5, InputSignal::CAM_DATA_5), (pin_5.into(), InputSignal::CAM_DATA_5),
(pin_6, InputSignal::CAM_DATA_6), (pin_6.into(), InputSignal::CAM_DATA_6),
(pin_7, InputSignal::CAM_DATA_7), (pin_7.into(), InputSignal::CAM_DATA_7),
(pin_8, InputSignal::CAM_DATA_8), (pin_8.into(), InputSignal::CAM_DATA_8),
(pin_9, InputSignal::CAM_DATA_9), (pin_9.into(), InputSignal::CAM_DATA_9),
(pin_10, InputSignal::CAM_DATA_10), (pin_10.into(), InputSignal::CAM_DATA_10),
(pin_11, InputSignal::CAM_DATA_11), (pin_11.into(), InputSignal::CAM_DATA_11),
(pin_12, InputSignal::CAM_DATA_12), (pin_12.into(), InputSignal::CAM_DATA_12),
(pin_13, InputSignal::CAM_DATA_13), (pin_13.into(), InputSignal::CAM_DATA_13),
(pin_14, InputSignal::CAM_DATA_14), (pin_14.into(), InputSignal::CAM_DATA_14),
(pin_15, InputSignal::CAM_DATA_15), (pin_15.into(), InputSignal::CAM_DATA_15),
]; ];
for (pin, signal) in pairs.into_iter() { for (pin, signal) in pairs.into_iter() {
pin.init_input(Pull::None); pin.init_input(Pull::None);
signal.connect_to(pin); signal.connect_to(&pin);
} }
Self { _pins: () } Self { _pins: () }

View File

@ -317,10 +317,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the VSYNC /// Sets the specified pin to push-pull output and connects it to the VSYNC
/// signal. /// signal.
pub fn with_vsync<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_vsync(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_V_SYNC.connect_to(pin); OutputSignal::LCD_V_SYNC.connect_to(&pin);
self self
} }
@ -329,10 +329,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the HSYNC /// Sets the specified pin to push-pull output and connects it to the HSYNC
/// signal. /// signal.
pub fn with_hsync<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_hsync(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_H_SYNC.connect_to(pin); OutputSignal::LCD_H_SYNC.connect_to(&pin);
self self
} }
@ -341,10 +341,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DE /// Sets the specified pin to push-pull output and connects it to the DE
/// signal. /// signal.
pub fn with_de<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_de(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_H_ENABLE.connect_to(pin); OutputSignal::LCD_H_ENABLE.connect_to(&pin);
self self
} }
@ -353,10 +353,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the PCLK /// Sets the specified pin to push-pull output and connects it to the PCLK
/// signal. /// signal.
pub fn with_pclk<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_pclk(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_PCLK.connect_to(pin); OutputSignal::LCD_PCLK.connect_to(&pin);
self self
} }
@ -365,10 +365,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_0 /// Sets the specified pin to push-pull output and connects it to the DATA_0
/// signal. /// signal.
pub fn with_data0<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data0(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_0.connect_to(pin); OutputSignal::LCD_DATA_0.connect_to(&pin);
self self
} }
@ -377,10 +377,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_1 /// Sets the specified pin to push-pull output and connects it to the DATA_1
/// signal. /// signal.
pub fn with_data1<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data1(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_1.connect_to(pin); OutputSignal::LCD_DATA_1.connect_to(&pin);
self self
} }
@ -389,10 +389,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_2 /// Sets the specified pin to push-pull output and connects it to the DATA_2
/// signal. /// signal.
pub fn with_data2<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data2(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_2.connect_to(pin); OutputSignal::LCD_DATA_2.connect_to(&pin);
self self
} }
@ -401,10 +401,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_3 /// Sets the specified pin to push-pull output and connects it to the DATA_3
/// signal. /// signal.
pub fn with_data3<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data3(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_3.connect_to(pin); OutputSignal::LCD_DATA_3.connect_to(&pin);
self self
} }
@ -413,10 +413,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_4 /// Sets the specified pin to push-pull output and connects it to the DATA_4
/// signal. /// signal.
pub fn with_data4<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data4(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_4.connect_to(pin); OutputSignal::LCD_DATA_4.connect_to(&pin);
self self
} }
@ -425,10 +425,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_5 /// Sets the specified pin to push-pull output and connects it to the DATA_5
/// signal. /// signal.
pub fn with_data5<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data5(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_5.connect_to(pin); OutputSignal::LCD_DATA_5.connect_to(&pin);
self self
} }
@ -437,10 +437,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_6 /// Sets the specified pin to push-pull output and connects it to the DATA_6
/// signal. /// signal.
pub fn with_data6<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data6(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_6.connect_to(pin); OutputSignal::LCD_DATA_6.connect_to(&pin);
self self
} }
@ -449,10 +449,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_7 /// Sets the specified pin to push-pull output and connects it to the DATA_7
/// signal. /// signal.
pub fn with_data7<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data7(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_7.connect_to(pin); OutputSignal::LCD_DATA_7.connect_to(&pin);
self self
} }
@ -461,10 +461,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_8 /// Sets the specified pin to push-pull output and connects it to the DATA_8
/// signal. /// signal.
pub fn with_data8<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data8(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_8.connect_to(pin); OutputSignal::LCD_DATA_8.connect_to(&pin);
self self
} }
@ -473,10 +473,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the DATA_9 /// Sets the specified pin to push-pull output and connects it to the DATA_9
/// signal. /// signal.
pub fn with_data9<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data9(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_9.connect_to(pin); OutputSignal::LCD_DATA_9.connect_to(&pin);
self self
} }
@ -485,10 +485,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the /// Sets the specified pin to push-pull output and connects it to the
/// DATA_10 signal. /// DATA_10 signal.
pub fn with_data10<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data10(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_10.connect_to(pin); OutputSignal::LCD_DATA_10.connect_to(&pin);
self self
} }
@ -497,10 +497,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the /// Sets the specified pin to push-pull output and connects it to the
/// DATA_11 signal. /// DATA_11 signal.
pub fn with_data11<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data11(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_11.connect_to(pin); OutputSignal::LCD_DATA_11.connect_to(&pin);
self self
} }
@ -509,10 +509,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the /// Sets the specified pin to push-pull output and connects it to the
/// DATA_12 signal. /// DATA_12 signal.
pub fn with_data12<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data12(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_12.connect_to(pin); OutputSignal::LCD_DATA_12.connect_to(&pin);
self self
} }
@ -521,10 +521,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the /// Sets the specified pin to push-pull output and connects it to the
/// DATA_13 signal. /// DATA_13 signal.
pub fn with_data13<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data13(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_13.connect_to(pin); OutputSignal::LCD_DATA_13.connect_to(&pin);
self self
} }
@ -533,10 +533,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the /// Sets the specified pin to push-pull output and connects it to the
/// DATA_14 signal. /// DATA_14 signal.
pub fn with_data14<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data14(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_14.connect_to(pin); OutputSignal::LCD_DATA_14.connect_to(&pin);
self self
} }
@ -545,10 +545,10 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the /// Sets the specified pin to push-pull output and connects it to the
/// DATA_15 signal. /// DATA_15 signal.
pub fn with_data15<S: PeripheralOutput>(self, pin: impl Peripheral<P = S> + 'd) -> Self { pub fn with_data15(self, pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
OutputSignal::LCD_DATA_15.connect_to(pin); OutputSignal::LCD_DATA_15.connect_to(&pin);
self self
} }

View File

@ -273,27 +273,28 @@ where
} }
/// Associates a CS pin with the I8080 interface. /// Associates a CS pin with the I8080 interface.
pub fn with_cs<CS: PeripheralOutput>(self, cs: impl Peripheral<P = CS> + 'd) -> Self { pub fn with_cs(self, cs: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(cs); let cs = cs.into();
cs.set_to_push_pull_output(); cs.set_to_push_pull_output();
OutputSignal::LCD_CS.connect_to(cs); OutputSignal::LCD_CS.connect_to(&cs);
self self
} }
/// Configures the control pins for the I8080 interface. /// Configures the control pins for the I8080 interface.
pub fn with_ctrl_pins<DC: PeripheralOutput, WRX: PeripheralOutput>( pub fn with_ctrl_pins(
self, self,
dc: impl Peripheral<P = DC> + 'd, dc: impl PeripheralOutput<'d>,
wrx: impl Peripheral<P = WRX> + 'd, wrx: impl PeripheralOutput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(dc, wrx); let dc = dc.into();
let wrx = wrx.into();
dc.set_to_push_pull_output(); dc.set_to_push_pull_output();
OutputSignal::LCD_DC.connect_to(dc); OutputSignal::LCD_DC.connect_to(&dc);
wrx.set_to_push_pull_output(); wrx.set_to_push_pull_output();
OutputSignal::LCD_PCLK.connect_to(wrx); OutputSignal::LCD_PCLK.connect_to(&wrx);
self self
} }
@ -620,33 +621,33 @@ impl From<u16> for Command<u16> {
/// Represents a group of 8 output pins configured for 8-bit parallel data /// Represents a group of 8 output pins configured for 8-bit parallel data
/// transmission. /// transmission.
pub struct TxEightBits<'d> { pub struct TxEightBits<'d> {
pins: [PeripheralRef<'d, OutputConnection>; 8], pins: [OutputConnection<'d>; 8],
} }
impl<'d> TxEightBits<'d> { impl<'d> TxEightBits<'d> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
/// Creates a new `TxEightBits` instance with the provided output pins. /// Creates a new `TxEightBits` instance with the provided output pins.
pub fn new( pub fn new(
pin_0: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_0: impl PeripheralOutput<'d>,
pin_1: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_1: impl PeripheralOutput<'d>,
pin_2: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_2: impl PeripheralOutput<'d>,
pin_3: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_3: impl PeripheralOutput<'d>,
pin_4: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_4: impl PeripheralOutput<'d>,
pin_5: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_5: impl PeripheralOutput<'d>,
pin_6: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_6: impl PeripheralOutput<'d>,
pin_7: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_7: impl PeripheralOutput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(pin_0);
crate::into_mapped_ref!(pin_1);
crate::into_mapped_ref!(pin_2);
crate::into_mapped_ref!(pin_3);
crate::into_mapped_ref!(pin_4);
crate::into_mapped_ref!(pin_5);
crate::into_mapped_ref!(pin_6);
crate::into_mapped_ref!(pin_7);
Self { Self {
pins: [pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7], pins: [
pin_0.into(),
pin_1.into(),
pin_2.into(),
pin_3.into(),
pin_4.into(),
pin_5.into(),
pin_6.into(),
pin_7.into(),
],
} }
} }
} }
@ -664,7 +665,7 @@ impl TxPins for TxEightBits<'_> {
OutputSignal::LCD_DATA_7, OutputSignal::LCD_DATA_7,
]; ];
for (pin, signal) in self.pins.iter_mut().zip(SIGNALS.into_iter()) { for (pin, signal) in self.pins.iter().zip(SIGNALS.into_iter()) {
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
signal.connect_to(pin); signal.connect_to(pin);
} }
@ -674,39 +675,48 @@ impl TxPins for TxEightBits<'_> {
/// Represents a group of 16 output pins configured for 16-bit parallel data /// Represents a group of 16 output pins configured for 16-bit parallel data
/// transmission. /// transmission.
pub struct TxSixteenBits<'d> { pub struct TxSixteenBits<'d> {
pins: [PeripheralRef<'d, OutputConnection>; 16], pins: [OutputConnection<'d>; 16],
} }
impl<'d> TxSixteenBits<'d> { impl<'d> TxSixteenBits<'d> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
/// Creates a new `TxSixteenBits` instance with the provided output pins. /// Creates a new `TxSixteenBits` instance with the provided output pins.
pub fn new( pub fn new(
pin_0: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_0: impl PeripheralOutput<'d>,
pin_1: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_1: impl PeripheralOutput<'d>,
pin_2: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_2: impl PeripheralOutput<'d>,
pin_3: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_3: impl PeripheralOutput<'d>,
pin_4: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_4: impl PeripheralOutput<'d>,
pin_5: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_5: impl PeripheralOutput<'d>,
pin_6: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_6: impl PeripheralOutput<'d>,
pin_7: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_7: impl PeripheralOutput<'d>,
pin_8: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_8: impl PeripheralOutput<'d>,
pin_9: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_9: impl PeripheralOutput<'d>,
pin_10: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_10: impl PeripheralOutput<'d>,
pin_11: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_11: impl PeripheralOutput<'d>,
pin_12: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_12: impl PeripheralOutput<'d>,
pin_13: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_13: impl PeripheralOutput<'d>,
pin_14: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_14: impl PeripheralOutput<'d>,
pin_15: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_15: impl PeripheralOutput<'d>,
) -> Self { ) -> Self {
crate::into_mapped_ref!(
pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7, pin_8, pin_9, pin_10, pin_11,
pin_12, pin_13, pin_14, pin_15
);
Self { Self {
pins: [ pins: [
pin_0, pin_1, pin_2, pin_3, pin_4, pin_5, pin_6, pin_7, pin_8, pin_9, pin_10, pin_0.into(),
pin_11, pin_12, pin_13, pin_14, pin_15, pin_1.into(),
pin_2.into(),
pin_3.into(),
pin_4.into(),
pin_5.into(),
pin_6.into(),
pin_7.into(),
pin_8.into(),
pin_9.into(),
pin_10.into(),
pin_11.into(),
pin_12.into(),
pin_13.into(),
pin_14.into(),
pin_15.into(),
], ],
} }
} }

View File

@ -16,7 +16,6 @@ use crate::{
OutputSignal, OutputSignal,
}, },
pac::ledc::RegisterBlock, pac::ledc::RegisterBlock,
peripheral::{Peripheral, PeripheralRef},
peripherals::LEDC, peripherals::LEDC,
}; };
@ -152,22 +151,18 @@ pub struct Channel<'a, S: TimerSpeed> {
ledc: &'a RegisterBlock, ledc: &'a RegisterBlock,
timer: Option<&'a dyn TimerIFace<S>>, timer: Option<&'a dyn TimerIFace<S>>,
number: Number, number: Number,
output_pin: PeripheralRef<'a, OutputConnection>, output_pin: OutputConnection<'a>,
} }
impl<'a, S: TimerSpeed> Channel<'a, S> { impl<'a, S: TimerSpeed> Channel<'a, S> {
/// Return a new channel /// Return a new channel
pub fn new( pub fn new(number: Number, output_pin: impl PeripheralOutput<'a>) -> Self {
number: Number,
output_pin: impl Peripheral<P = impl PeripheralOutput> + 'a,
) -> Self {
crate::into_mapped_ref!(output_pin);
let ledc = LEDC::regs(); let ledc = LEDC::regs();
Channel { Channel {
ledc, ledc,
timer: None, timer: None,
number, number,
output_pin, output_pin: output_pin.into(),
} }
} }
} }
@ -614,7 +609,7 @@ where
Number::Channel7 => OutputSignal::LEDC_LS_SIG7, Number::Channel7 => OutputSignal::LEDC_LS_SIG7,
}; };
signal.connect_to(&mut self.output_pin); signal.connect_to(&self.output_pin);
} else { } else {
return Err(Error::Timer); return Err(Error::Timer);
} }

View File

@ -180,7 +180,7 @@ impl<'d> Ledc<'d> {
pub fn channel<S: TimerSpeed>( pub fn channel<S: TimerSpeed>(
&self, &self,
number: channel::Number, number: channel::Number,
output_pin: impl Peripheral<P = impl PeripheralOutput> + 'd, output_pin: impl PeripheralOutput<'d>,
) -> Channel<'d, S> { ) -> Channel<'d, S> {
Channel::new(number, output_pin) Channel::new(number, output_pin)
} }

View File

@ -109,7 +109,7 @@ macro_rules! any_peripheral {
impl $crate::private::Sealed for $name {} impl $crate::private::Sealed for $name {}
impl $crate::peripheral::Peripheral for $name { unsafe impl $crate::peripheral::Peripheral for $name {
type P = $name; type P = $name;
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {

View File

@ -16,7 +16,6 @@ use crate::{
gpio::interconnect::{OutputConnection, PeripheralOutput}, gpio::interconnect::{OutputConnection, PeripheralOutput},
mcpwm::{timer::Timer, PwmPeripheral}, mcpwm::{timer::Timer, PwmPeripheral},
pac, pac,
peripheral::{Peripheral, PeripheralRef},
}; };
/// Input/Output Stream descriptor for each channel /// Input/Output Stream descriptor for each channel
@ -212,7 +211,7 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> {
/// Use the A output with the given pin and configuration /// Use the A output with the given pin and configuration
pub fn with_pin_a( pub fn with_pin_a(
self, self,
pin: impl Peripheral<P = impl PeripheralOutput> + 'd, pin: impl PeripheralOutput<'d>,
config: PwmPinConfig<true>, config: PwmPinConfig<true>,
) -> PwmPin<'d, PWM, OP, true> { ) -> PwmPin<'d, PWM, OP, true> {
PwmPin::new(pin, config) PwmPin::new(pin, config)
@ -221,7 +220,7 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> {
/// Use the B output with the given pin and configuration /// Use the B output with the given pin and configuration
pub fn with_pin_b( pub fn with_pin_b(
self, self,
pin: impl Peripheral<P = impl PeripheralOutput> + 'd, pin: impl PeripheralOutput<'d>,
config: PwmPinConfig<false>, config: PwmPinConfig<false>,
) -> PwmPin<'d, PWM, OP, false> { ) -> PwmPin<'d, PWM, OP, false> {
PwmPin::new(pin, config) PwmPin::new(pin, config)
@ -230,9 +229,9 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> {
/// Use both the A and the B output with the given pins and configurations /// Use both the A and the B output with the given pins and configurations
pub fn with_pins( pub fn with_pins(
self, self,
pin_a: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_a: impl PeripheralOutput<'d>,
config_a: PwmPinConfig<true>, config_a: PwmPinConfig<true>,
pin_b: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_b: impl PeripheralOutput<'d>,
config_b: PwmPinConfig<false>, config_b: PwmPinConfig<false>,
) -> (PwmPin<'d, PWM, OP, true>, PwmPin<'d, PWM, OP, false>) { ) -> (PwmPin<'d, PWM, OP, true>, PwmPin<'d, PWM, OP, false>) {
(PwmPin::new(pin_a, config_a), PwmPin::new(pin_b, config_b)) (PwmPin::new(pin_a, config_a), PwmPin::new(pin_b, config_b))
@ -244,9 +243,9 @@ impl<'d, const OP: u8, PWM: PwmPeripheral> Operator<'d, OP, PWM> {
/// configured deadtime /// configured deadtime
pub fn with_linked_pins( pub fn with_linked_pins(
self, self,
pin_a: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_a: impl PeripheralOutput<'d>,
config_a: PwmPinConfig<true>, config_a: PwmPinConfig<true>,
pin_b: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_b: impl PeripheralOutput<'d>,
config_b: PwmPinConfig<false>, config_b: PwmPinConfig<false>,
config_dt: DeadTimeCfg, config_dt: DeadTimeCfg,
) -> LinkedPins<'d, PWM, OP> { ) -> LinkedPins<'d, PWM, OP> {
@ -287,17 +286,14 @@ impl<const IS_A: bool> PwmPinConfig<IS_A> {
/// A pin driven by an MCPWM operator /// A pin driven by an MCPWM operator
pub struct PwmPin<'d, PWM, const OP: u8, const IS_A: bool> { pub struct PwmPin<'d, PWM, const OP: u8, const IS_A: bool> {
pin: PeripheralRef<'d, OutputConnection>, pin: OutputConnection<'d>,
phantom: PhantomData<PWM>, phantom: PhantomData<PWM>,
_guard: PeripheralGuard, _guard: PeripheralGuard,
} }
impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> { impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP, IS_A> {
fn new( fn new(pin: impl PeripheralOutput<'d>, config: PwmPinConfig<IS_A>) -> Self {
pin: impl Peripheral<P = impl PeripheralOutput> + 'd, let pin = pin.into();
config: PwmPinConfig<IS_A>,
) -> Self {
crate::into_mapped_ref!(pin);
let guard = PeripheralGuard::new(PWM::peripheral()); let guard = PeripheralGuard::new(PWM::peripheral());
@ -309,7 +305,7 @@ impl<'d, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> PwmPin<'d, PWM, OP,
pin.set_actions(config.actions); pin.set_actions(config.actions);
pin.set_update_method(config.update_method); pin.set_update_method(config.update_method);
PWM::output_signal::<OP, IS_A>().connect_to(&mut pin.pin); PWM::output_signal::<OP, IS_A>().connect_to(&pin.pin);
pin.pin.enable_output(true); pin.pin.enable_output(true);
pin pin
@ -497,9 +493,9 @@ pub struct LinkedPins<'d, PWM, const OP: u8> {
impl<'d, PWM: PwmPeripheral, const OP: u8> LinkedPins<'d, PWM, OP> { impl<'d, PWM: PwmPeripheral, const OP: u8> LinkedPins<'d, PWM, OP> {
fn new( fn new(
pin_a: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_a: impl PeripheralOutput<'d>,
config_a: PwmPinConfig<true>, config_a: PwmPinConfig<true>,
pin_b: impl Peripheral<P = impl PeripheralOutput> + 'd, pin_b: impl PeripheralOutput<'d>,
config_b: PwmPinConfig<false>, config_b: PwmPinConfig<false>,
config_dt: DeadTimeCfg, config_dt: DeadTimeCfg,
) -> Self { ) -> Self {

View File

@ -92,10 +92,10 @@ impl<'d> Usb<'d> {
use crate::gpio::Level; use crate::gpio::Level;
InputSignal::USB_OTG_IDDIG.connect_to(Level::High); // connected connector is mini-B side InputSignal::USB_OTG_IDDIG.connect_to(&Level::High); // connected connector is mini-B side
InputSignal::USB_SRP_BVALID.connect_to(Level::High); // HIGH to force USB device mode InputSignal::USB_SRP_BVALID.connect_to(&Level::High); // HIGH to force USB device mode
InputSignal::USB_OTG_VBUSVALID.connect_to(Level::High); // receiving a valid Vbus from device InputSignal::USB_OTG_VBUSVALID.connect_to(&Level::High); // receiving a valid Vbus from device
InputSignal::USB_OTG_AVALID.connect_to(Level::Low); InputSignal::USB_OTG_AVALID.connect_to(&Level::Low);
} }
fn _disable() { fn _disable() {

View File

@ -125,7 +125,6 @@ use core::{
}; };
use enumset::{EnumSet, EnumSetType}; use enumset::{EnumSet, EnumSetType};
use peripheral::PeripheralRef;
use private::*; use private::*;
use crate::{ use crate::{
@ -151,7 +150,7 @@ use crate::{
}, },
interrupt::InterruptHandler, interrupt::InterruptHandler,
parl_io::asynch::interrupt_handler, parl_io::asynch::interrupt_handler,
peripheral::{self, Peripheral}, peripheral::Peripheral,
peripherals::{Interrupt, PARL_IO, PCR}, peripherals::{Interrupt, PARL_IO, PCR},
system::{self, GenericPeripheralGuard}, system::{self, GenericPeripheralGuard},
time::Rate, time::Rate,
@ -364,31 +363,29 @@ impl RxClkPin for NoPin {
/// Wraps a GPIO pin which will be used as the clock output signal /// Wraps a GPIO pin which will be used as the clock output signal
pub struct ClkOutPin<'d> { pub struct ClkOutPin<'d> {
pin: PeripheralRef<'d, OutputConnection>, pin: OutputConnection<'d>,
} }
impl<'d> ClkOutPin<'d> { impl<'d> ClkOutPin<'d> {
/// Create a ClkOutPin /// Create a ClkOutPin
pub fn new(pin: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn new(pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(pin); Self { pin: pin.into() }
Self { pin }
} }
} }
impl TxClkPin for ClkOutPin<'_> { impl TxClkPin for ClkOutPin<'_> {
fn configure(&mut self) { fn configure(&mut self) {
self.pin.set_to_push_pull_output(); self.pin.set_to_push_pull_output();
crate::gpio::OutputSignal::PARL_TX_CLK.connect_to(&mut self.pin); crate::gpio::OutputSignal::PARL_TX_CLK.connect_to(&self.pin);
} }
} }
/// Wraps a GPIO pin which will be used as the TX clock input signal /// Wraps a GPIO pin which will be used as the TX clock input signal
pub struct ClkInPin<'d> { pub struct ClkInPin<'d> {
pin: PeripheralRef<'d, InputConnection>, pin: InputConnection<'d>,
} }
impl<'d> ClkInPin<'d> { impl<'d> ClkInPin<'d> {
/// Create a new ClkInPin /// Create a new ClkInPin
pub fn new(pin: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn new(pin: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(pin); Self { pin: pin.into() }
Self { pin }
} }
} }
impl TxClkPin for ClkInPin<'_> { impl TxClkPin for ClkInPin<'_> {
@ -398,23 +395,22 @@ impl TxClkPin for ClkInPin<'_> {
.modify(|_, w| unsafe { w.parl_clk_tx_sel().bits(3).parl_clk_tx_div_num().bits(0) }); // PAD_CLK_TX, no divider .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(crate::gpio::Pull::None); self.pin.init_input(crate::gpio::Pull::None);
crate::gpio::InputSignal::PARL_TX_CLK.connect_to(&mut self.pin); crate::gpio::InputSignal::PARL_TX_CLK.connect_to(&self.pin);
} }
} }
/// Wraps a GPIO pin which will be used as the RX clock input signal /// Wraps a GPIO pin which will be used as the RX clock input signal
pub struct RxClkInPin<'d> { pub struct RxClkInPin<'d> {
pin: PeripheralRef<'d, InputConnection>, pin: InputConnection<'d>,
sample_edge: SampleEdge, sample_edge: SampleEdge,
} }
impl<'d> RxClkInPin<'d> { impl<'d> RxClkInPin<'d> {
/// Create a new RxClkInPin /// Create a new RxClkInPin
pub fn new( pub fn new(pin: impl PeripheralInput<'d>, sample_edge: SampleEdge) -> Self {
pin: impl Peripheral<P = impl PeripheralInput> + 'd, Self {
sample_edge: SampleEdge, pin: pin.into(),
) -> Self { sample_edge,
crate::into_mapped_ref!(pin); }
Self { pin, sample_edge }
} }
} }
impl RxClkPin for RxClkInPin<'_> { impl RxClkPin for RxClkInPin<'_> {
@ -424,7 +420,7 @@ impl RxClkPin for RxClkInPin<'_> {
.modify(|_, w| unsafe { w.parl_clk_rx_sel().bits(3).parl_clk_rx_div_num().bits(0) }); // PAD_CLK_TX, no divider .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(crate::gpio::Pull::None); self.pin.init_input(crate::gpio::Pull::None);
crate::gpio::InputSignal::PARL_RX_CLK.connect_to(&mut self.pin); crate::gpio::InputSignal::PARL_RX_CLK.connect_to(&self.pin);
Instance::set_rx_clk_edge_sel(self.sample_edge); Instance::set_rx_clk_edge_sel(self.sample_edge);
} }
@ -436,7 +432,7 @@ where
P: NotContainsValidSignalPin + TxPins + ConfigurePins, P: NotContainsValidSignalPin + TxPins + ConfigurePins,
{ {
tx_pins: P, tx_pins: P,
valid_pin: PeripheralRef<'d, OutputConnection>, valid_pin: OutputConnection<'d>,
} }
impl<'d, P> TxPinConfigWithValidPin<'d, P> impl<'d, P> TxPinConfigWithValidPin<'d, P>
@ -444,9 +440,11 @@ where
P: NotContainsValidSignalPin + TxPins + ConfigurePins, P: NotContainsValidSignalPin + TxPins + ConfigurePins,
{ {
/// Create a [TxPinConfigWithValidPin] /// Create a [TxPinConfigWithValidPin]
pub fn new(tx_pins: P, valid_pin: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn new(tx_pins: P, valid_pin: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(valid_pin); Self {
Self { tx_pins, valid_pin } tx_pins,
valid_pin: valid_pin.into(),
}
} }
} }
@ -462,7 +460,7 @@ where
fn configure(&mut self) -> Result<(), Error> { fn configure(&mut self) -> Result<(), Error> {
self.tx_pins.configure()?; self.tx_pins.configure()?;
self.valid_pin.set_to_push_pull_output(); self.valid_pin.set_to_push_pull_output();
Instance::tx_valid_pin_signal().connect_to(&mut self.valid_pin); Instance::tx_valid_pin_signal().connect_to(&self.valid_pin);
Instance::set_tx_hw_valid_en(true); Instance::set_tx_hw_valid_en(true);
Ok(()) Ok(())
} }
@ -510,7 +508,7 @@ macro_rules! tx_pins {
#[doc = "bit output mode"] #[doc = "bit output mode"]
pub struct $name<'d> { pub struct $name<'d> {
$( $(
[< pin_ $pin:lower >] : PeripheralRef<'d, OutputConnection>, [< pin_ $pin:lower >] : OutputConnection<'d >,
)+ )+
} }
@ -520,11 +518,10 @@ macro_rules! tx_pins {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
$( $(
[< pin_ $pin:lower >] : impl Peripheral<P = impl PeripheralOutput > + 'd, [< pin_ $pin:lower >] : impl PeripheralOutput<'d>,
)+ )+
) -> Self { ) -> Self {
crate::into_mapped_ref!($( [< pin_ $pin:lower >] ),+); Self { $( [< pin_ $pin:lower >]: [< pin_ $pin:lower >].into() ),+ }
Self { $( [< pin_ $pin:lower >] ),+ }
} }
} }
@ -615,7 +612,7 @@ where
P: NotContainsValidSignalPin + RxPins + ConfigurePins, P: NotContainsValidSignalPin + RxPins + ConfigurePins,
{ {
rx_pins: P, rx_pins: P,
valid_pin: PeripheralRef<'d, InputConnection>, valid_pin: InputConnection<'d>,
enable_mode: EnableMode, enable_mode: EnableMode,
} }
@ -624,15 +621,10 @@ where
P: NotContainsValidSignalPin + RxPins + ConfigurePins, P: NotContainsValidSignalPin + RxPins + ConfigurePins,
{ {
/// Create a new [RxPinConfigWithValidPin] /// Create a new [RxPinConfigWithValidPin]
pub fn new( pub fn new(rx_pins: P, valid_pin: impl PeripheralInput<'d>, enable_mode: EnableMode) -> Self {
rx_pins: P,
valid_pin: impl Peripheral<P = impl PeripheralInput> + 'd,
enable_mode: EnableMode,
) -> Self {
crate::into_mapped_ref!(valid_pin);
Self { Self {
rx_pins, rx_pins,
valid_pin, valid_pin: valid_pin.into(),
enable_mode, enable_mode,
} }
} }
@ -650,7 +642,7 @@ where
fn configure(&mut self) -> Result<(), Error> { fn configure(&mut self) -> Result<(), Error> {
self.rx_pins.configure()?; self.rx_pins.configure()?;
self.valid_pin.init_input(crate::gpio::Pull::None); self.valid_pin.init_input(crate::gpio::Pull::None);
Instance::rx_valid_pin_signal().connect_to(&mut self.valid_pin); Instance::rx_valid_pin_signal().connect_to(&self.valid_pin);
Instance::set_rx_sw_en(false); Instance::set_rx_sw_en(false);
if let Some(sel) = self.enable_mode.pulse_submode_sel() { if let Some(sel) = self.enable_mode.pulse_submode_sel() {
Instance::set_rx_pulse_submode_sel(sel); Instance::set_rx_pulse_submode_sel(sel);
@ -722,7 +714,7 @@ macro_rules! rx_pins {
#[doc = "bit input mode"] #[doc = "bit input mode"]
pub struct $name<'d> { pub struct $name<'d> {
$( $(
[< pin_ $pin:lower >] : PeripheralRef<'d, InputConnection>, [< pin_ $pin:lower >] : InputConnection<'d>,
)+ )+
} }
@ -732,11 +724,10 @@ macro_rules! rx_pins {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
$( $(
[< pin_ $pin:lower >] : impl Peripheral<P = impl PeripheralInput > + 'd, [< pin_ $pin:lower >] : impl PeripheralInput<'d>,
)+ )+
) -> Self { ) -> Self {
crate::into_mapped_ref!($( [< pin_ $pin:lower >] ),+); Self { $( [< pin_ $pin:lower >]: [< pin_ $pin:lower >].into() ),+ }
Self { $( [< pin_ $pin:lower >] ),+ }
} }
} }
@ -745,7 +736,7 @@ macro_rules! rx_pins {
fn configure(&mut self) -> Result<(), Error> { fn configure(&mut self) -> Result<(), Error> {
$( $(
self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None); self.[< pin_ $pin:lower >].init_input(crate::gpio::Pull::None);
crate::gpio::InputSignal::$signal.connect_to(&mut self.[< pin_ $pin:lower >]); crate::gpio::InputSignal::$signal.connect_to(&self.[< pin_ $pin:lower >]);
)+ )+
private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]); private::Instance::set_rx_bit_width( private::WidSel::[< Bits $width >]);

View File

@ -12,7 +12,6 @@ use core::marker::PhantomData;
pub use crate::pac::pcnt::unit::conf0::{CTRL_MODE as CtrlMode, EDGE_MODE as EdgeMode}; pub use crate::pac::pcnt::unit::conf0::{CTRL_MODE as CtrlMode, EDGE_MODE as EdgeMode};
use crate::{ use crate::{
gpio::{interconnect::PeripheralInput, InputSignal}, gpio::{interconnect::PeripheralInput, InputSignal},
peripheral::Peripheral,
peripherals::PCNT, peripherals::PCNT,
system::GenericPeripheralGuard, system::GenericPeripheralGuard,
}; };
@ -72,7 +71,7 @@ impl<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
} }
/// Set the control signal (pin/high/low) for this channel /// Set the control signal (pin/high/low) for this channel
pub fn set_ctrl_signal<P: PeripheralInput>(&self, source: impl Peripheral<P = P>) -> &Self { pub fn set_ctrl_signal<'d>(&self, source: impl PeripheralInput<'d>) -> &Self {
let signal = match UNIT { let signal = match UNIT {
0 => match NUM { 0 => match NUM {
0 => InputSignal::PCNT0_CTRL_CH0, 0 => InputSignal::PCNT0_CTRL_CH0,
@ -122,15 +121,15 @@ impl<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
}; };
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize { if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
crate::into_mapped_ref!(source); let source = source.into();
source.enable_input(true); source.enable_input(true);
signal.connect_to(source); signal.connect_to(&source);
} }
self self
} }
/// Set the edge signal (pin/high/low) for this channel /// Set the edge signal (pin/high/low) for this channel
pub fn set_edge_signal<P: PeripheralInput>(&self, source: impl Peripheral<P = P>) -> &Self { pub fn set_edge_signal<'d>(&self, source: impl PeripheralInput<'d>) -> &Self {
let signal = match UNIT { let signal = match UNIT {
0 => match NUM { 0 => match NUM {
0 => InputSignal::PCNT0_SIG_CH0, 0 => InputSignal::PCNT0_SIG_CH0,
@ -180,9 +179,9 @@ impl<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
}; };
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize { if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
crate::into_mapped_ref!(source); let source = source.into();
source.enable_input(true); source.enable_input(true);
signal.connect_to(source); signal.connect_to(&source);
} }
self self
} }

View File

@ -1,9 +1,6 @@
//! # Exclusive peripheral access //! # Exclusive peripheral access
use core::{ use core::{marker::PhantomData, ops::Deref};
marker::PhantomData,
ops::{Deref, DerefMut},
};
/// An exclusive reference to a peripheral. /// An exclusive reference to a peripheral.
/// ///
@ -27,6 +24,8 @@ pub struct PeripheralRef<'a, T> {
_lifetime: PhantomData<&'a mut T>, _lifetime: PhantomData<&'a mut T>,
} }
impl<T> crate::private::Sealed for PeripheralRef<'_, T> {}
impl<'a, T> PeripheralRef<'a, T> { impl<'a, T> PeripheralRef<'a, T> {
/// Create a new exclusive reference to a peripheral /// Create a new exclusive reference to a peripheral
#[inline] #[inline]
@ -146,7 +145,16 @@ impl<T> Deref for PeripheralRef<'_, T> {
/// ///
/// `.into_ref()` on an owned `T` yields a `PeripheralRef<'static, T>`. /// `.into_ref()` on an owned `T` yields a `PeripheralRef<'static, T>`.
/// `.into_ref()` on an `&'a mut T` yields a `PeripheralRef<'a, T>`. /// `.into_ref()` on an `&'a mut T` yields a `PeripheralRef<'a, T>`.
pub trait Peripheral: Sized { ///
/// # Safety
///
/// Implementing this trait is unsound on types that can be obtained again even
/// after calling `into_ref`. For example, implementing this trait for
/// `MutexGuard<P>` is unsound, as the guard is dropped to turn it into a
/// `PeripheralRef<'static, P>`, which allows the `Mutex` to be immediately
/// re-acquired, potentially resulting in multiple copies of
/// `PeripheralRef<'static, P>`.
pub unsafe trait Peripheral: Sized {
/// Peripheral singleton type /// Peripheral singleton type
type P; type P;
@ -201,19 +209,17 @@ pub trait Peripheral: Sized {
} }
} }
impl<T: DerefMut> Peripheral for T impl<T: Peripheral> crate::private::Sealed for &mut T {}
where unsafe impl<T: Peripheral> Peripheral for &mut T {
T::Target: Peripheral, type P = <T as Peripheral>::P;
{
type P = <T::Target as Peripheral>::P;
#[inline] #[inline]
unsafe fn clone_unchecked(&self) -> Self::P { unsafe fn clone_unchecked(&self) -> Self::P {
T::Target::clone_unchecked(self) T::clone_unchecked(self)
} }
} }
impl<T: Peripheral> Peripheral for PeripheralRef<'_, T> { unsafe impl<T: Peripheral> Peripheral for PeripheralRef<'_, T> {
type P = T::P; type P = T::P;
#[inline] #[inline]
@ -431,7 +437,7 @@ mod peripheral_macros {
} }
} }
impl $crate::peripheral::Peripheral for $name { unsafe impl $crate::peripheral::Peripheral for $name {
type P = $name; type P = $name;
#[inline] #[inline]

View File

@ -466,8 +466,8 @@ impl crate::interrupt::InterruptConfigurable for Rmt<'_, Blocking> {
} }
} }
fn configure_rx_channel<'d, P: PeripheralInput, T: RxChannelInternal>( fn configure_rx_channel<'d, T: RxChannelInternal>(
pin: impl Peripheral<P = P> + 'd, pin: impl PeripheralInput<'d>,
config: RxChannelConfig, config: RxChannelConfig,
) -> Result<T, Error> { ) -> Result<T, Error> {
cfg_if::cfg_if! { cfg_if::cfg_if! {
@ -482,9 +482,9 @@ fn configure_rx_channel<'d, P: PeripheralInput, T: RxChannelInternal>(
return Err(Error::InvalidArgument); return Err(Error::InvalidArgument);
} }
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.init_input(crate::gpio::Pull::None); pin.init_input(crate::gpio::Pull::None);
T::input_signal().connect_to(pin); T::input_signal().connect_to(&pin);
T::set_divider(config.clk_divider); T::set_divider(config.clk_divider);
T::set_carrier( T::set_carrier(
@ -499,13 +499,13 @@ fn configure_rx_channel<'d, P: PeripheralInput, T: RxChannelInternal>(
Ok(T::new()) Ok(T::new())
} }
fn configure_tx_channel<'d, P: PeripheralOutput, T: TxChannelInternal>( fn configure_tx_channel<'d, T: TxChannelInternal>(
pin: impl Peripheral<P = P> + 'd, pin: impl PeripheralOutput<'d>,
config: TxChannelConfig, config: TxChannelConfig,
) -> Result<T, Error> { ) -> Result<T, Error> {
crate::into_mapped_ref!(pin); let pin = pin.into();
pin.set_to_push_pull_output(); pin.set_to_push_pull_output();
T::output_signal().connect_to(pin); T::output_signal().connect_to(&pin);
T::set_divider(config.clk_divider); T::set_divider(config.clk_divider);
T::set_carrier( T::set_carrier(
@ -520,17 +520,12 @@ fn configure_tx_channel<'d, P: PeripheralOutput, T: TxChannelInternal>(
} }
/// Creates a TX channel /// Creates a TX channel
pub trait TxChannelCreator<'d, T, P> pub trait TxChannelCreator<'d, T>
where where
P: PeripheralOutput,
T: TxChannel, T: TxChannel,
{ {
/// Configure the TX channel /// Configure the TX channel
fn configure( fn configure(self, pin: impl PeripheralOutput<'d>, config: TxChannelConfig) -> Result<T, Error>
self,
pin: impl Peripheral<P = P> + 'd,
config: TxChannelConfig,
) -> Result<T, Error>
where where
Self: Sized, Self: Sized,
{ {
@ -539,17 +534,12 @@ where
} }
/// Creates a TX channel in async mode /// Creates a TX channel in async mode
pub trait TxChannelCreatorAsync<'d, T, P> pub trait TxChannelCreatorAsync<'d, T>
where where
P: PeripheralOutput,
T: TxChannelAsync, T: TxChannelAsync,
{ {
/// Configure the TX channel /// Configure the TX channel
fn configure( fn configure(self, pin: impl PeripheralOutput<'d>, config: TxChannelConfig) -> Result<T, Error>
self,
pin: impl Peripheral<P = P> + 'd,
config: TxChannelConfig,
) -> Result<T, Error>
where where
Self: Sized, Self: Sized,
{ {
@ -558,17 +548,12 @@ where
} }
/// Creates a RX channel /// Creates a RX channel
pub trait RxChannelCreator<'d, T, P> pub trait RxChannelCreator<'d, T>
where where
P: PeripheralInput,
T: RxChannel, T: RxChannel,
{ {
/// Configure the RX channel /// Configure the RX channel
fn configure( fn configure(self, pin: impl PeripheralInput<'d>, config: RxChannelConfig) -> Result<T, Error>
self,
pin: impl Peripheral<P = P> + 'd,
config: RxChannelConfig,
) -> Result<T, Error>
where where
Self: Sized, Self: Sized,
{ {
@ -577,17 +562,12 @@ where
} }
/// Creates a RX channel in async mode /// Creates a RX channel in async mode
pub trait RxChannelCreatorAsync<'d, T, P> pub trait RxChannelCreatorAsync<'d, T>
where where
P: PeripheralInput,
T: RxChannelAsync, T: RxChannelAsync,
{ {
/// Configure the RX channel /// Configure the RX channel
fn configure( fn configure(self, pin: impl PeripheralInput<'d>, config: RxChannelConfig) -> Result<T, Error>
self,
pin: impl Peripheral<P = P> + 'd,
config: RxChannelConfig,
) -> Result<T, Error>
where where
Self: Sized, Self: Sized,
{ {
@ -725,21 +705,16 @@ where
macro_rules! impl_tx_channel_creator { macro_rules! impl_tx_channel_creator {
($channel:literal) => { ($channel:literal) => {
impl<'d, P> impl<'d> $crate::rmt::TxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>>
$crate::rmt::TxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P>
for ChannelCreator<$crate::Blocking, $channel> for ChannelCreator<$crate::Blocking, $channel>
where
P: $crate::gpio::interconnect::PeripheralOutput,
{ {
} }
impl $crate::rmt::TxChannel for $crate::rmt::Channel<$crate::Blocking, $channel> {} impl $crate::rmt::TxChannel for $crate::rmt::Channel<$crate::Blocking, $channel> {}
impl<'d, P> impl<'d>
$crate::rmt::TxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P> $crate::rmt::TxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>>
for ChannelCreator<$crate::Async, $channel> for ChannelCreator<$crate::Async, $channel>
where
P: $crate::gpio::interconnect::PeripheralOutput,
{ {
} }
@ -749,21 +724,16 @@ macro_rules! impl_tx_channel_creator {
macro_rules! impl_rx_channel_creator { macro_rules! impl_rx_channel_creator {
($channel:literal) => { ($channel:literal) => {
impl<'d, P> impl<'d> $crate::rmt::RxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>>
$crate::rmt::RxChannelCreator<'d, $crate::rmt::Channel<$crate::Blocking, $channel>, P>
for ChannelCreator<$crate::Blocking, $channel> for ChannelCreator<$crate::Blocking, $channel>
where
P: $crate::gpio::interconnect::PeripheralInput,
{ {
} }
impl $crate::rmt::RxChannel for $crate::rmt::Channel<$crate::Blocking, $channel> {} impl $crate::rmt::RxChannel for $crate::rmt::Channel<$crate::Blocking, $channel> {}
impl<'d, P> impl<'d>
$crate::rmt::RxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>, P> $crate::rmt::RxChannelCreatorAsync<'d, $crate::rmt::Channel<$crate::Async, $channel>>
for ChannelCreator<$crate::Async, $channel> for ChannelCreator<$crate::Async, $channel>
where
P: $crate::gpio::interconnect::PeripheralInput,
{ {
} }

View File

@ -138,7 +138,7 @@ impl Rng {
impl Sealed for Rng {} impl Sealed for Rng {}
impl Peripheral for Rng { unsafe impl Peripheral for Rng {
type P = Self; type P = Self;
#[inline] #[inline]
@ -287,7 +287,7 @@ impl rand_core09::CryptoRng for Trng<'_> {}
impl Sealed for Trng<'_> {} impl Sealed for Trng<'_> {}
impl Peripheral for Trng<'_> { unsafe impl Peripheral for Trng<'_> {
type P = Self; type P = Self;
#[inline] #[inline]

View File

@ -50,7 +50,7 @@ use crate::{
clock::Clocks, clock::Clocks,
dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx}, dma::{DmaChannelFor, DmaEligible, DmaRxBuffer, DmaTxBuffer, Rx, Tx},
gpio::{ gpio::{
interconnect::{OutputConnection, PeripheralInput, PeripheralOutput}, interconnect::{PeripheralInput, PeripheralOutput},
InputSignal, InputSignal,
NoPin, NoPin,
OutputSignal, OutputSignal,
@ -711,10 +711,10 @@ impl<'d> Spi<'d, Blocking> {
let is_qspi = this.driver().info.sio2_input.is_some(); let is_qspi = this.driver().info.sio2_input.is_some();
if is_qspi { if is_qspi {
unwrap!(this.driver().info.sio2_input).connect_to(NoPin); unwrap!(this.driver().info.sio2_input).connect_to(&NoPin);
unwrap!(this.driver().info.sio2_output).connect_to(NoPin); unwrap!(this.driver().info.sio2_output).connect_to(&NoPin);
unwrap!(this.driver().info.sio3_input).connect_to(NoPin); unwrap!(this.driver().info.sio3_input).connect_to(&NoPin);
unwrap!(this.driver().info.sio3_output).connect_to(NoPin); unwrap!(this.driver().info.sio3_output).connect_to(&NoPin);
} }
Ok(this) Ok(this)
@ -874,10 +874,10 @@ where
/// SPI clock signal. /// SPI clock signal.
/// ///
/// Disconnects the previous pin that was assigned with `with_sck`. /// Disconnects the previous pin that was assigned with `with_sck`.
pub fn with_sck<SCK: PeripheralOutput>(mut self, sclk: impl Peripheral<P = SCK> + 'd) -> Self { pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(sclk); let sclk = sclk.into();
sclk.set_to_push_pull_output(); sclk.set_to_push_pull_output();
self.pins.sclk_pin = OutputConnection::connect_with_guard(sclk, self.driver().info.sclk); self.pins.sclk_pin = sclk.connect_with_guard(self.driver().info.sclk);
self self
} }
@ -890,14 +890,11 @@ where
/// ///
/// Disconnects the previous pin that was assigned with `with_mosi` or /// Disconnects the previous pin that was assigned with `with_mosi` or
/// `with_sio0`. /// `with_sio0`.
pub fn with_mosi<MOSI: PeripheralOutput>( pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
mut self, let mosi = mosi.into();
mosi: impl Peripheral<P = MOSI> + 'd,
) -> Self {
crate::into_mapped_ref!(mosi);
mosi.enable_output(false); mosi.enable_output(false);
self.pins.mosi_pin = OutputConnection::connect_with_guard(mosi, self.driver().info.mosi); self.pins.mosi_pin = mosi.connect_with_guard(self.driver().info.mosi);
self self
} }
@ -909,11 +906,11 @@ where
/// ///
/// You want to use this for full-duplex SPI or /// You want to use this for full-duplex SPI or
/// [DataMode::SingleTwoDataLines] /// [DataMode::SingleTwoDataLines]
pub fn with_miso<MISO: PeripheralInput>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self { pub fn with_miso(self, miso: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(miso); let miso = miso.into();
miso.enable_input(true); miso.enable_input(true);
self.driver().info.miso.connect_to(miso); self.driver().info.miso.connect_to(&miso);
self self
} }
@ -932,16 +929,13 @@ where
/// ///
/// Note: You do not need to call [Self::with_mosi] when this is used. /// Note: You do not need to call [Self::with_mosi] when this is used.
#[instability::unstable] #[instability::unstable]
pub fn with_sio0<MOSI: PeripheralOutput>( pub fn with_sio0(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
mut self, let mosi = mosi.into();
mosi: impl Peripheral<P = MOSI> + 'd,
) -> Self {
crate::into_mapped_ref!(mosi);
mosi.enable_output(true); mosi.enable_output(true);
mosi.enable_input(true); mosi.enable_input(true);
self.driver().info.sio0_input.connect_to(&mut mosi); self.driver().info.sio0_input.connect_to(&mosi);
self.pins.mosi_pin = OutputConnection::connect_with_guard(mosi, self.driver().info.mosi); self.pins.mosi_pin = mosi.connect_with_guard(self.driver().info.mosi);
self self
} }
@ -959,17 +953,13 @@ where
/// ///
/// Note: You do not need to call [Self::with_miso] when this is used. /// Note: You do not need to call [Self::with_miso] when this is used.
#[instability::unstable] #[instability::unstable]
pub fn with_sio1<SIO1: PeripheralOutput>( pub fn with_sio1(mut self, sio1: impl PeripheralOutput<'d>) -> Self {
mut self, let sio1 = sio1.into();
miso: impl Peripheral<P = SIO1> + 'd, sio1.enable_input(true);
) -> Self { sio1.enable_output(true);
crate::into_mapped_ref!(miso);
miso.enable_input(true);
miso.enable_output(true);
self.driver().info.miso.connect_to(&mut miso); self.driver().info.miso.connect_to(&sio1);
self.pins.sio1_pin = self.pins.sio1_pin = sio1.connect_with_guard(self.driver().info.sio1_output);
OutputConnection::connect_with_guard(miso, self.driver().info.sio1_output);
self self
} }
@ -983,21 +973,18 @@ where
/// QSPI operations are unstable, associated pins configuration is /// QSPI operations are unstable, associated pins configuration is
/// inefficient. /// inefficient.
#[instability::unstable] #[instability::unstable]
pub fn with_sio2<SIO2: PeripheralOutput>( pub fn with_sio2(mut self, sio2: impl PeripheralOutput<'d>) -> Self {
mut self,
sio2: impl Peripheral<P = SIO2> + 'd,
) -> Self {
// TODO: panic if not QSPI? // TODO: panic if not QSPI?
crate::into_mapped_ref!(sio2); let sio2 = sio2.into();
sio2.enable_input(true); sio2.enable_input(true);
sio2.enable_output(true); sio2.enable_output(true);
unwrap!(self.driver().info.sio2_input).connect_to(&mut sio2); unwrap!(self.driver().info.sio2_input).connect_to(&sio2);
self.pins.sio2_pin = self self.pins.sio2_pin = self
.driver() .driver()
.info .info
.sio2_output .sio2_output
.map(|signal| OutputConnection::connect_with_guard(sio2, signal)); .map(|signal| sio2.connect_with_guard(signal));
self self
} }
@ -1011,21 +998,18 @@ where
/// QSPI operations are unstable, associated pins configuration is /// QSPI operations are unstable, associated pins configuration is
/// inefficient. /// inefficient.
#[instability::unstable] #[instability::unstable]
pub fn with_sio3<SIO3: PeripheralOutput>( pub fn with_sio3(mut self, sio3: impl PeripheralOutput<'d>) -> Self {
mut self,
sio3: impl Peripheral<P = SIO3> + 'd,
) -> Self {
// TODO: panic if not QSPI? // TODO: panic if not QSPI?
crate::into_mapped_ref!(sio3); let sio3 = sio3.into();
sio3.enable_input(true); sio3.enable_input(true);
sio3.enable_output(true); sio3.enable_output(true);
unwrap!(self.driver().info.sio3_input).connect_to(&mut sio3); unwrap!(self.driver().info.sio3_input).connect_to(&sio3);
self.pins.sio3_pin = self self.pins.sio3_pin = self
.driver() .driver()
.info .info
.sio3_output .sio3_output
.map(|signal| OutputConnection::connect_with_guard(sio3, signal)); .map(|signal| sio3.connect_with_guard(signal));
self self
} }
@ -1042,10 +1026,10 @@ where
/// be set, regardless of the total number available. There is no /// be set, regardless of the total number available. There is no
/// mechanism to select which CS line to use. /// mechanism to select which CS line to use.
#[instability::unstable] #[instability::unstable]
pub fn with_cs<CS: PeripheralOutput>(mut self, cs: impl Peripheral<P = CS> + 'd) -> Self { pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(cs); let cs = cs.into();
cs.set_to_push_pull_output(); cs.set_to_push_pull_output();
self.pins.cs_pin = OutputConnection::connect_with_guard(cs, self.driver().info.cs); self.pins.cs_pin = cs.connect_with_guard(self.driver().info.cs);
self self
} }

View File

@ -127,37 +127,37 @@ impl<'d> Spi<'d, Blocking> {
/// Assign the SCK (Serial Clock) pin for the SPI instance. /// Assign the SCK (Serial Clock) pin for the SPI instance.
#[instability::unstable] #[instability::unstable]
pub fn with_sck(self, sclk: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_sck(self, sclk: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(sclk); let sclk = sclk.into();
sclk.enable_input(true); sclk.enable_input(true);
self.spi.info().sclk.connect_to(sclk); self.spi.info().sclk.connect_to(&sclk);
self self
} }
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance. /// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
#[instability::unstable] #[instability::unstable]
pub fn with_mosi(self, mosi: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_mosi(self, mosi: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(mosi); let mosi = mosi.into();
mosi.enable_input(true); mosi.enable_input(true);
self.spi.info().mosi.connect_to(mosi); self.spi.info().mosi.connect_to(&mosi);
self self
} }
/// Assign the MISO (Master In Slave Out) pin for the SPI instance. /// Assign the MISO (Master In Slave Out) pin for the SPI instance.
#[instability::unstable] #[instability::unstable]
pub fn with_miso(self, miso: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_miso(self, miso: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(miso); let miso = miso.into();
miso.set_to_push_pull_output(); miso.set_to_push_pull_output();
self.spi.info().miso.connect_to(miso); self.spi.info().miso.connect_to(&miso);
self self
} }
/// Assign the CS (Chip Select) pin for the SPI instance. /// Assign the CS (Chip Select) pin for the SPI instance.
#[instability::unstable] #[instability::unstable]
pub fn with_cs(self, cs: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_cs(self, cs: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(cs); let cs = cs.into();
cs.enable_input(true); cs.enable_input(true);
self.spi.info().cs.connect_to(cs); self.spi.info().cs.connect_to(&cs);
self self
} }
} }

View File

@ -589,7 +589,7 @@ impl super::Timer for Alarm {
} }
} }
impl Peripheral for Alarm { unsafe impl Peripheral for Alarm {
type P = Self; type P = Self;
#[inline] #[inline]

View File

@ -356,7 +356,7 @@ impl super::Timer for Timer {
} }
} }
impl Peripheral for Timer { unsafe impl Peripheral for Timer {
type P = Self; type P = Self;
#[inline] #[inline]

View File

@ -667,15 +667,16 @@ impl<'d, Dm> TwaiConfiguration<'d, Dm>
where where
Dm: DriverMode, Dm: DriverMode,
{ {
fn new_internal<TX: PeripheralOutput, RX: PeripheralInput>( fn new_internal(
twai: PeripheralRef<'d, AnyTwai>, twai: PeripheralRef<'d, AnyTwai>,
rx_pin: impl Peripheral<P = RX> + 'd, rx_pin: impl PeripheralInput<'d>,
tx_pin: impl Peripheral<P = TX> + 'd, tx_pin: impl PeripheralOutput<'d>,
baud_rate: BaudRate, baud_rate: BaudRate,
no_transceiver: bool, no_transceiver: bool,
mode: TwaiMode, mode: TwaiMode,
) -> Self { ) -> Self {
crate::into_mapped_ref!(tx_pin, rx_pin); let rx_pin = rx_pin.into();
let tx_pin = tx_pin.into();
let guard = PeripheralGuard::new(twai.peripheral()); let guard = PeripheralGuard::new(twai.peripheral());
@ -710,13 +711,13 @@ where
tx_pin.set_to_push_pull_output(); tx_pin.set_to_push_pull_output();
Pull::None Pull::None
}; };
this.twai.output_signal().connect_to(tx_pin); this.twai.output_signal().connect_to(&tx_pin);
// Setting up RX pin later allows us to use a single pin in tests. // Setting up RX pin later allows us to use a single pin in tests.
// `set_to_push_pull_output` disables input, here we re-enable it if rx_pin // `set_to_push_pull_output` disables input, here we re-enable it if rx_pin
// uses the same GPIO. // uses the same GPIO.
rx_pin.init_input(rx_pull); rx_pin.init_input(rx_pull);
this.twai.input_signal().connect_to(rx_pin); this.twai.input_signal().connect_to(&rx_pin);
// Freeze REC by changing to LOM mode // Freeze REC by changing to LOM mode
this.set_mode(TwaiMode::ListenOnly); this.set_mode(TwaiMode::ListenOnly);
@ -934,10 +935,10 @@ impl<'d> TwaiConfiguration<'d, Blocking> {
/// Create a new instance of [TwaiConfiguration] /// Create a new instance of [TwaiConfiguration]
/// ///
/// You will need to use a transceiver to connect to the TWAI bus /// You will need to use a transceiver to connect to the TWAI bus
pub fn new<RX: PeripheralInput, TX: PeripheralOutput>( pub fn new(
peripheral: impl Peripheral<P = impl Instance> + 'd, peripheral: impl Peripheral<P = impl Instance> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd, rx_pin: impl PeripheralInput<'d>,
tx_pin: impl Peripheral<P = TX> + 'd, tx_pin: impl PeripheralOutput<'d>,
baud_rate: BaudRate, baud_rate: BaudRate,
mode: TwaiMode, mode: TwaiMode,
) -> Self { ) -> Self {
@ -950,10 +951,10 @@ impl<'d> TwaiConfiguration<'d, Blocking> {
/// ///
/// You don't need a transceiver by following the description in the /// You don't need a transceiver by following the description in the
/// `twai.rs` example /// `twai.rs` example
pub fn new_no_transceiver<RX: PeripheralInput, TX: PeripheralOutput>( pub fn new_no_transceiver(
peripheral: impl Peripheral<P = impl Instance> + 'd, peripheral: impl Peripheral<P = impl Instance> + 'd,
rx_pin: impl Peripheral<P = RX> + 'd, rx_pin: impl PeripheralInput<'d>,
tx_pin: impl Peripheral<P = TX> + 'd, tx_pin: impl PeripheralOutput<'d>,
baud_rate: BaudRate, baud_rate: BaudRate,
mode: TwaiMode, mode: TwaiMode,
) -> Self { ) -> Self {

View File

@ -52,7 +52,7 @@ use crate::{
asynch::AtomicWaker, asynch::AtomicWaker,
clock::Clocks, clock::Clocks,
gpio::{ gpio::{
interconnect::{OutputConnection, PeripheralInput, PeripheralOutput}, interconnect::{PeripheralInput, PeripheralOutput},
InputSignal, InputSignal,
OutputSignal, OutputSignal,
PinGuard, PinGuard,
@ -675,10 +675,10 @@ where
{ {
/// Configure RTS pin /// Configure RTS pin
#[instability::unstable] #[instability::unstable]
pub fn with_rts(mut self, rts: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_rts(mut self, rts: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(rts); let rts = rts.into();
rts.set_to_push_pull_output(); rts.set_to_push_pull_output();
self.rts_pin = OutputConnection::connect_with_guard(rts, self.uart.info().rts_signal); self.rts_pin = rts.connect_with_guard(self.uart.info().rts_signal);
self self
} }
@ -690,12 +690,12 @@ where
/// ///
/// Disconnects the previous pin that was assigned with `with_tx`. /// Disconnects the previous pin that was assigned with `with_tx`.
#[instability::unstable] #[instability::unstable]
pub fn with_tx(mut self, tx: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_tx(mut self, tx: impl PeripheralOutput<'d>) -> Self {
crate::into_mapped_ref!(tx); let tx = tx.into();
// Make sure we don't cause an unexpected low pulse on the pin. // Make sure we don't cause an unexpected low pulse on the pin.
tx.set_output_high(true); tx.set_output_high(true);
tx.set_to_push_pull_output(); tx.set_to_push_pull_output();
self.tx_pin = OutputConnection::connect_with_guard(tx, self.uart.info().tx_signal); self.tx_pin = tx.connect_with_guard(self.uart.info().tx_signal);
self self
} }
@ -1035,10 +1035,10 @@ where
/// ///
/// Sets the specified pin to input and connects it to the UART CTS signal. /// Sets the specified pin to input and connects it to the UART CTS signal.
#[instability::unstable] #[instability::unstable]
pub fn with_cts(self, cts: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_cts(self, cts: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(cts); let cts = cts.into();
cts.init_input(Pull::None); cts.init_input(Pull::None);
self.uart.info().cts_signal.connect_to(cts); self.uart.info().cts_signal.connect_to(&cts);
self self
} }
@ -1052,10 +1052,10 @@ where
/// initially high, to avoid receiving a non-data byte caused by an /// initially high, to avoid receiving a non-data byte caused by an
/// initial low signal level. /// initial low signal level.
#[instability::unstable] #[instability::unstable]
pub fn with_rx(self, rx: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_rx(self, rx: impl PeripheralInput<'d>) -> Self {
crate::into_mapped_ref!(rx); let rx = rx.into();
rx.init_input(Pull::Up); rx.init_input(Pull::Up);
self.uart.info().rx_signal.connect_to(rx); self.uart.info().rx_signal.connect_to(&rx);
self self
} }
@ -1470,7 +1470,7 @@ where
/// configure the driver side (i.e. the TX pin), or ensure that the line is /// configure the driver side (i.e. the TX pin), or ensure that the line is
/// initially high, to avoid receiving a non-data byte caused by an /// initially high, to avoid receiving a non-data byte caused by an
/// initial low signal level. /// initial low signal level.
pub fn with_rx(mut self, rx: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_rx(mut self, rx: impl PeripheralInput<'d>) -> Self {
self.rx = self.rx.with_rx(rx); self.rx = self.rx.with_rx(rx);
self self
} }
@ -1479,19 +1479,19 @@ where
/// ///
/// Sets the specified pin to push-pull output and connects it to the UART /// Sets the specified pin to push-pull output and connects it to the UART
/// TX signal. /// TX signal.
pub fn with_tx(mut self, tx: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_tx(mut self, tx: impl PeripheralOutput<'d>) -> Self {
self.tx = self.tx.with_tx(tx); self.tx = self.tx.with_tx(tx);
self self
} }
/// Configure CTS pin /// Configure CTS pin
pub fn with_cts(mut self, cts: impl Peripheral<P = impl PeripheralInput> + 'd) -> Self { pub fn with_cts(mut self, cts: impl PeripheralInput<'d>) -> Self {
self.rx = self.rx.with_cts(cts); self.rx = self.rx.with_cts(cts);
self self
} }
/// Configure RTS pin /// Configure RTS pin
pub fn with_rts(mut self, rts: impl Peripheral<P = impl PeripheralOutput> + 'd) -> Self { pub fn with_rts(mut self, rts: impl PeripheralOutput<'d>) -> Self {
self.tx = self.tx.with_rts(rts); self.tx = self.tx.with_rts(rts);
self self
} }

View File

@ -51,6 +51,27 @@ pub fn interrupt_handler() {
}); });
} }
// Compile-time test to check that GPIOs can be passed by reference.
fn _gpios_can_be_reused() {
let p = esp_hal::init(esp_hal::Config::default());
let mut gpio1 = p.GPIO1;
{
let _driver = Input::new(&mut gpio1, InputConfig::default().with_pull(Pull::Down));
}
{
let _driver = esp_hal::spi::master::Spi::new(p.SPI2, Default::default())
.unwrap()
.with_mosi(&mut gpio1);
}
{
let _driver = Input::new(&mut gpio1, InputConfig::default().with_pull(Pull::Down));
}
}
#[cfg(test)] #[cfg(test)]
#[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())] #[embedded_test::tests(default_timeout = 3, executor = hil_test::Executor::new())]
mod tests { mod tests {

View File

@ -36,10 +36,10 @@ use hil_test as _;
struct Context { struct Context {
parl_io: PARL_IO, parl_io: PARL_IO,
dma_channel: DmaChannel0, dma_channel: DmaChannel0,
clock: OutputSignal, clock: OutputSignal<'static>,
valid: OutputSignal, valid: OutputSignal<'static>,
clock_loopback: InputSignal, clock_loopback: InputSignal<'static>,
valid_loopback: InputSignal, valid_loopback: InputSignal<'static>,
pcnt_unit: Unit<'static, 0>, pcnt_unit: Unit<'static, 0>,
} }

View File

@ -36,10 +36,10 @@ use hil_test as _;
struct Context { struct Context {
parl_io: PARL_IO, parl_io: PARL_IO,
dma_channel: DmaChannel0, dma_channel: DmaChannel0,
clock: OutputSignal, clock: OutputSignal<'static>,
valid: OutputSignal, valid: OutputSignal<'static>,
clock_loopback: InputSignal, clock_loopback: InputSignal<'static>,
valid_loopback: InputSignal, valid_loopback: InputSignal<'static>,
pcnt_unit: Unit<'static, 0>, pcnt_unit: Unit<'static, 0>,
} }

View File

@ -24,7 +24,7 @@ use hil_test as _;
struct Context { struct Context {
spi: SpiDma<'static, Blocking>, spi: SpiDma<'static, Blocking>,
pcnt_unit: Unit<'static, 0>, pcnt_unit: Unit<'static, 0>,
pcnt_source: InputSignal, pcnt_source: InputSignal<'static>,
} }
fn perform_spi_writes_are_correctly_by_pcnt(ctx: Context, mode: DataMode) { fn perform_spi_writes_are_correctly_by_pcnt(ctx: Context, mode: DataMode) {

View File

@ -43,7 +43,7 @@ macro_rules! dma_alloc_buffer {
struct Context { struct Context {
spi: SpiDma<'static, Blocking>, spi: SpiDma<'static, Blocking>,
pcnt_unit: Unit<'static, 0>, pcnt_unit: Unit<'static, 0>,
pcnt_source: InputSignal, pcnt_source: InputSignal<'static>,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -115,6 +115,11 @@ mod tests {
} }
} }
// A bit of test-specific hackery, we need to be able to work with the Input
// driver directly while the SPI is driving the output signal part of
// the GPIO. This is currently not possible to describe in safe code.
let miso_pin_clone = unsafe { miso_pin.clone_unchecked() };
let mosi_gpio = Output::new(mosi_pin, Level::Low, OutputConfig::default()); let mosi_gpio = Output::new(mosi_pin, Level::Low, OutputConfig::default());
let cs_gpio = Output::new(cs_pin, Level::High, OutputConfig::default()); let cs_gpio = Output::new(cs_pin, Level::High, OutputConfig::default());
let sclk_gpio = Output::new(sclk_pin, Level::Low, OutputConfig::default()); let sclk_gpio = Output::new(sclk_pin, Level::Low, OutputConfig::default());
@ -123,7 +128,7 @@ mod tests {
let cs = cs_gpio.peripheral_input(); let cs = cs_gpio.peripheral_input();
let sclk = sclk_gpio.peripheral_input(); let sclk = sclk_gpio.peripheral_input();
let mosi = mosi_gpio.peripheral_input(); let mosi = mosi_gpio.peripheral_input();
let miso = unsafe { miso_gpio.clone_unchecked() }.into_peripheral_output(); let miso = miso_pin_clone.split().1;
Context { Context {
spi: Spi::new(peripherals.SPI2, Mode::_1) spi: Spi::new(peripherals.SPI2, Mode::_1)