Add PeripheralRef::map_into (#2326)
* Add PeripheralRef::map_into * Update clone_unchecked to take shared self * Simplify pin erasure
This commit is contained in:
parent
6e2606b367
commit
472d5f93e0
@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
- Add burst transfer support to DMA buffers (#2236)
|
||||
|
||||
- `AnyPin` now implements `From<GpioPin<N>>`. (#2326)
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -48,7 +48,7 @@ impl Clone for InputSignal {
|
||||
impl Peripheral for InputSignal {
|
||||
type P = Self;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
@ -187,7 +187,7 @@ pub struct OutputSignal {
|
||||
impl Peripheral for OutputSignal {
|
||||
type P = Self;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
Self {
|
||||
pin: self.pin.clone_unchecked(),
|
||||
is_inverted: self.is_inverted,
|
||||
@ -345,7 +345,7 @@ pub struct AnyInputSignal(AnyInputSignalInner);
|
||||
impl Peripheral for AnyInputSignal {
|
||||
type P = Self;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ pub trait PeripheralOutput: PeripheralSignal {
|
||||
}
|
||||
|
||||
/// Trait implemented by pins which can be used as inputs.
|
||||
pub trait InputPin: Pin + PeripheralInput {
|
||||
pub trait InputPin: Pin + PeripheralInput + Into<AnyPin> + 'static {
|
||||
/// Listen for interrupts
|
||||
#[doc(hidden)]
|
||||
fn listen(&mut self, event: Event, _: private::Internal) {
|
||||
@ -519,7 +519,7 @@ pub trait InputPin: Pin + PeripheralInput {
|
||||
}
|
||||
|
||||
/// Trait implemented by pins which can be used as outputs.
|
||||
pub trait OutputPin: Pin + PeripheralOutput {}
|
||||
pub trait OutputPin: Pin + PeripheralOutput + Into<AnyPin> + 'static {}
|
||||
|
||||
/// Trait implemented by pins which can be used as analog pins
|
||||
pub trait AnalogPin: Pin {
|
||||
@ -776,7 +776,7 @@ where
|
||||
{
|
||||
type P = GpioPin<GPIONUM>;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
core::ptr::read(self as *const _)
|
||||
}
|
||||
}
|
||||
@ -1131,6 +1131,13 @@ macro_rules! gpio {
|
||||
input_signals
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GpioPin<$gpionum>> for AnyPin {
|
||||
fn from(pin: GpioPin<$gpionum>) -> Self {
|
||||
use $crate::gpio::Pin;
|
||||
pin.degrade()
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
||||
pub(crate) enum AnyPinInner {
|
||||
@ -1142,8 +1149,9 @@ macro_rules! gpio {
|
||||
/// Type-erased GPIO pin
|
||||
pub struct AnyPin(pub(crate) AnyPinInner);
|
||||
|
||||
impl AnyPin {
|
||||
pub(crate) unsafe fn clone_unchecked(&self) -> Self {
|
||||
impl $crate::peripheral::Peripheral for AnyPin {
|
||||
type P = AnyPin;
|
||||
unsafe fn clone_unchecked(&self) -> Self {
|
||||
match self.0 {
|
||||
$(AnyPinInner::[<Gpio $gpionum >](_) => {
|
||||
Self(AnyPinInner::[< Gpio $gpionum >](unsafe { GpioPin::steal() }))
|
||||
@ -1152,13 +1160,6 @@ macro_rules! gpio {
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::peripheral::Peripheral for AnyPin {
|
||||
type P = AnyPin;
|
||||
unsafe fn clone_unchecked(&mut self) -> Self {
|
||||
AnyPin::clone_unchecked(self)
|
||||
}
|
||||
}
|
||||
|
||||
// These macros call the code block on the actually contained GPIO pin.
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -1598,18 +1599,17 @@ impl<P> private::Sealed for Output<'_, P> {}
|
||||
|
||||
impl<'d, P> Peripheral for Output<'d, P> {
|
||||
type P = P;
|
||||
unsafe fn clone_unchecked(&mut self) -> P {
|
||||
unsafe fn clone_unchecked(&self) -> P {
|
||||
self.pin.clone_unchecked()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Output<'d> {
|
||||
/// Create GPIO output driver for a [GpioPin] with the provided level
|
||||
/// Create GPIO open-drain output driver for a [Pin] with the provided
|
||||
/// initial output-level and [Pull] configuration.
|
||||
#[inline]
|
||||
pub fn new<P: OutputPin>(pin: impl Peripheral<P = P> + 'd, initial_output: Level) -> Self {
|
||||
let pin = Flex::new(pin);
|
||||
|
||||
Self::new_inner(pin, initial_output)
|
||||
pub fn new(pin: impl Peripheral<P = impl OutputPin> + 'd, initial_output: Level) -> Self {
|
||||
Self::new_typed(pin.map_into(), initial_output)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1702,7 +1702,7 @@ impl<P> private::Sealed for Input<'_, P> {}
|
||||
|
||||
impl<'d, P> Peripheral for Input<'d, P> {
|
||||
type P = P;
|
||||
unsafe fn clone_unchecked(&mut self) -> P {
|
||||
unsafe fn clone_unchecked(&self) -> P {
|
||||
self.pin.clone_unchecked()
|
||||
}
|
||||
}
|
||||
@ -1711,10 +1711,8 @@ impl<'d> Input<'d> {
|
||||
/// Create GPIO input driver for a [Pin] with the provided [Pull]
|
||||
/// configuration.
|
||||
#[inline]
|
||||
pub fn new<P: InputPin>(pin: impl Peripheral<P = P> + 'd, pull: Pull) -> Self {
|
||||
let pin = Flex::new(pin);
|
||||
|
||||
Self::new_inner(pin, pull)
|
||||
pub fn new(pin: impl Peripheral<P = impl InputPin> + 'd, pull: Pull) -> Self {
|
||||
Self::new_typed(pin.map_into(), pull)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1726,12 +1724,8 @@ where
|
||||
/// configuration.
|
||||
#[inline]
|
||||
pub fn new_typed(pin: impl Peripheral<P = P> + 'd, pull: Pull) -> Self {
|
||||
let pin = Flex::new_typed(pin);
|
||||
let mut pin = Flex::new_typed(pin);
|
||||
|
||||
Self::new_inner(pin, pull)
|
||||
}
|
||||
|
||||
fn new_inner(mut pin: Flex<'d, P>, pull: Pull) -> Self {
|
||||
pin.set_as_input(pull);
|
||||
|
||||
Self { pin }
|
||||
@ -1806,7 +1800,7 @@ impl<P> private::Sealed for OutputOpenDrain<'_, P> {}
|
||||
|
||||
impl<'d, P> Peripheral for OutputOpenDrain<'d, P> {
|
||||
type P = P;
|
||||
unsafe fn clone_unchecked(&mut self) -> P {
|
||||
unsafe fn clone_unchecked(&self) -> P {
|
||||
self.pin.clone_unchecked()
|
||||
}
|
||||
}
|
||||
@ -1815,14 +1809,12 @@ impl<'d> OutputOpenDrain<'d> {
|
||||
/// Create GPIO open-drain output driver for a [Pin] with the provided
|
||||
/// initial output-level and [Pull] configuration.
|
||||
#[inline]
|
||||
pub fn new<P: InputPin + OutputPin>(
|
||||
pin: impl Peripheral<P = P> + 'd,
|
||||
pub fn new(
|
||||
pin: impl Peripheral<P = impl InputPin + OutputPin> + 'd,
|
||||
initial_output: Level,
|
||||
pull: Pull,
|
||||
) -> Self {
|
||||
let pin = Flex::new(pin);
|
||||
|
||||
Self::new_inner(pin, initial_output, pull)
|
||||
Self::new_typed(pin.map_into(), initial_output, pull)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1834,15 +1826,9 @@ where
|
||||
/// initial output-level and [Pull] configuration.
|
||||
#[inline]
|
||||
pub fn new_typed(pin: impl Peripheral<P = P> + 'd, initial_output: Level, pull: Pull) -> Self {
|
||||
let pin = Flex::new_typed(pin);
|
||||
|
||||
Self::new_inner(pin, initial_output, pull)
|
||||
}
|
||||
|
||||
fn new_inner(mut pin: Flex<'d, P>, initial_output: Level, pull: Pull) -> Self {
|
||||
pin.pin
|
||||
.set_output_high(initial_output.into(), private::Internal);
|
||||
let mut pin = Flex::new_typed(pin);
|
||||
|
||||
pin.set_level(initial_output);
|
||||
pin.set_as_open_drain(pull);
|
||||
|
||||
Self { pin }
|
||||
@ -1945,7 +1931,7 @@ impl<P> private::Sealed for Flex<'_, P> {}
|
||||
|
||||
impl<'d, P> Peripheral for Flex<'d, P> {
|
||||
type P = P;
|
||||
unsafe fn clone_unchecked(&mut self) -> P {
|
||||
unsafe fn clone_unchecked(&self) -> P {
|
||||
core::ptr::read(&*self.pin as *const _)
|
||||
}
|
||||
}
|
||||
@ -1954,10 +1940,8 @@ impl<'d> Flex<'d> {
|
||||
/// Create flexible pin driver for a [Pin].
|
||||
/// No mode change happens.
|
||||
#[inline]
|
||||
pub fn new<P: Pin>(pin: impl Peripheral<P = P> + 'd) -> Self {
|
||||
crate::into_ref!(pin);
|
||||
let pin = pin.degrade_pin(private::Internal);
|
||||
Self::new_typed(pin)
|
||||
pub fn new(pin: impl Peripheral<P = impl Into<AnyPin>> + 'd) -> Self {
|
||||
Self::new_typed(pin.map_into())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ use super::*;
|
||||
impl crate::peripheral::Peripheral for Level {
|
||||
type P = Self;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
*self
|
||||
}
|
||||
}
|
||||
@ -96,7 +96,7 @@ pub struct NoPin;
|
||||
impl crate::peripheral::Peripheral for NoPin {
|
||||
type P = Self;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ impl<const NUM: u8> crate::peripheral::Peripheral for SoftwareInterrupt<NUM> {
|
||||
type P = SoftwareInterrupt<NUM>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
Self::steal()
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ impl<'a, T> PeripheralRef<'a, T> {
|
||||
/// You should strongly prefer using `reborrow()` instead. It returns a
|
||||
/// `PeripheralRef` that borrows `self`, which allows the borrow checker
|
||||
/// to enforce this at compile time.
|
||||
pub unsafe fn clone_unchecked(&mut self) -> PeripheralRef<'a, T>
|
||||
pub unsafe fn clone_unchecked(&self) -> PeripheralRef<'a, T>
|
||||
where
|
||||
T: Peripheral<P = T>,
|
||||
{
|
||||
@ -62,6 +62,24 @@ impl<'a, T> PeripheralRef<'a, T> {
|
||||
// self, so user code can't use both at the same time.
|
||||
PeripheralRef::new(unsafe { self.inner.clone_unchecked() })
|
||||
}
|
||||
|
||||
/// Map the inner peripheral using `Into`.
|
||||
///
|
||||
/// This converts from `PeripheralRef<'a, T>` to `PeripheralRef<'a, U>`,
|
||||
/// using an `Into` impl to convert from `T` to `U`.
|
||||
///
|
||||
/// For example, this can be useful to degrade GPIO pins: converting from
|
||||
/// PeripheralRef<'a, GpioPin<11>>` to `PeripheralRef<'a, AnyPin>`.
|
||||
#[inline]
|
||||
pub fn map_into<U>(self) -> PeripheralRef<'a, U>
|
||||
where
|
||||
T: Into<U>,
|
||||
{
|
||||
PeripheralRef {
|
||||
inner: self.inner.into(),
|
||||
_lifetime: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for PeripheralRef<'a, T> {
|
||||
@ -137,19 +155,32 @@ pub trait Peripheral: Sized + crate::private::Sealed {
|
||||
/// You should strongly prefer using `into_ref()` instead. It returns a
|
||||
/// `PeripheralRef`, which allows the borrow checker to enforce this at
|
||||
/// compile time.
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P;
|
||||
unsafe fn clone_unchecked(&self) -> Self::P;
|
||||
|
||||
/// Convert a value into a `PeripheralRef`.
|
||||
///
|
||||
/// When called on an owned `T`, yields a `PeripheralRef<'static, T>`.
|
||||
/// When called on an `&'a mut T`, yields a `PeripheralRef<'a, T>`.
|
||||
#[inline]
|
||||
fn into_ref<'a>(mut self) -> PeripheralRef<'a, Self::P>
|
||||
fn into_ref<'a>(self) -> PeripheralRef<'a, Self::P>
|
||||
where
|
||||
Self: 'a,
|
||||
{
|
||||
PeripheralRef::new(unsafe { self.clone_unchecked() })
|
||||
}
|
||||
|
||||
/// Map the peripheral using `Into`.
|
||||
///
|
||||
/// This converts from `Peripheral<P = T>` to `Peripheral<P = U>`,
|
||||
/// using an `Into` impl to convert from `T` to `U`.
|
||||
#[inline]
|
||||
fn map_into<U>(self) -> U
|
||||
where
|
||||
Self::P: Into<U>,
|
||||
U: Peripheral<P = U>,
|
||||
{
|
||||
unsafe { self.clone_unchecked().into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P> Peripheral for &mut T
|
||||
@ -158,12 +189,22 @@ where
|
||||
{
|
||||
type P = P;
|
||||
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
T::clone_unchecked(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> crate::private::Sealed for &mut T where T: crate::private::Sealed {}
|
||||
impl<T> crate::private::Sealed for PeripheralRef<'_, T> where T: crate::private::Sealed {}
|
||||
|
||||
impl<T: Peripheral> Peripheral for PeripheralRef<'_, T> {
|
||||
type P = T::P;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
T::clone_unchecked(self)
|
||||
}
|
||||
}
|
||||
|
||||
mod peripheral_macros {
|
||||
#[doc(hidden)]
|
||||
@ -257,6 +298,17 @@ mod peripheral_macros {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! into_mapped_ref {
|
||||
($($name:ident),*) => {
|
||||
$(
|
||||
#[allow(unused_mut)]
|
||||
let mut $name = $name.map_into().into_ref();
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
/// Macro to create a peripheral structure.
|
||||
@ -288,7 +340,7 @@ mod peripheral_macros {
|
||||
type P = $name;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
Self::steal()
|
||||
}
|
||||
}
|
||||
@ -346,7 +398,7 @@ mod peripheral_macros {
|
||||
type P = $name;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
Self::steal()
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +461,7 @@ impl Peripheral for AnyTimer {
|
||||
type P = Self;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
core::ptr::read(self as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1003,7 +1003,7 @@ where
|
||||
type P = Self;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
core::ptr::read(self as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,7 +591,7 @@ where
|
||||
type P = Self;
|
||||
|
||||
#[inline]
|
||||
unsafe fn clone_unchecked(&mut self) -> Self::P {
|
||||
unsafe fn clone_unchecked(&self) -> Self::P {
|
||||
core::ptr::read(self as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user