nrf/gpio: add OptionalPin
This commit is contained in:
parent
df42c38492
commit
e7e34cb8c2
@ -1,6 +1,7 @@
|
|||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::hint::unreachable_unchecked;
|
use core::hint::unreachable_unchecked;
|
||||||
|
|
||||||
|
use embassy::util::PeripheralBorrow;
|
||||||
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
|
use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
|
||||||
use gpio::pin_cnf::DRIVE_A;
|
use gpio::pin_cnf::DRIVE_A;
|
||||||
|
|
||||||
@ -205,6 +206,7 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn block(&self) -> &gpio::RegisterBlock {
|
fn block(&self) -> &gpio::RegisterBlock {
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.pin_port() / 32 {
|
match self.pin_port() / 32 {
|
||||||
@ -216,11 +218,13 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn conf(&self) -> &gpio::PIN_CNF {
|
fn conf(&self) -> &gpio::PIN_CNF {
|
||||||
&self.block().pin_cnf[self._pin() as usize]
|
&self.block().pin_cnf[self._pin() as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output as high.
|
/// Set the output as high.
|
||||||
|
#[inline]
|
||||||
fn set_high(&self) {
|
fn set_high(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.block().outset.write(|w| w.bits(1u32 << self._pin()));
|
self.block().outset.write(|w| w.bits(1u32 << self._pin()));
|
||||||
@ -228,12 +232,15 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output as low.
|
/// Set the output as low.
|
||||||
|
#[inline]
|
||||||
fn set_low(&self) {
|
fn set_low(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.block().outclr.write(|w| w.bits(1u32 << self._pin()));
|
self.block().outclr.write(|w| w.bits(1u32 << self._pin()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait OptionalPin {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Pin: sealed::Pin + Sized {
|
pub trait Pin: sealed::Pin + Sized {
|
||||||
@ -247,7 +254,7 @@ pub trait Pin: sealed::Pin + Sized {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn port(&self) -> Port {
|
fn port(&self) -> Port {
|
||||||
match self.pin_port() / 32 {
|
match self.pin_port() / 32 {
|
||||||
1 => Port::Port0,
|
0 => Port::Port0,
|
||||||
#[cfg(any(feature = "52833", feature = "52840"))]
|
#[cfg(any(feature = "52833", feature = "52840"))]
|
||||||
1 => Port::Port1,
|
1 => Port::Port1,
|
||||||
_ => unsafe { unreachable_unchecked() },
|
_ => unsafe { unreachable_unchecked() },
|
||||||
@ -260,6 +267,7 @@ pub trait Pin: sealed::Pin + Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert from concrete pin type PX_XX to type erased `AnyPin`.
|
/// Convert from concrete pin type PX_XX to type erased `AnyPin`.
|
||||||
|
#[inline]
|
||||||
fn degrade(self) -> AnyPin {
|
fn degrade(self) -> AnyPin {
|
||||||
AnyPin {
|
AnyPin {
|
||||||
pin_port: self.pin_port(),
|
pin_port: self.pin_port(),
|
||||||
@ -273,6 +281,7 @@ pub struct AnyPin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AnyPin {
|
impl AnyPin {
|
||||||
|
#[inline]
|
||||||
pub unsafe fn steal(pin_port: u8) -> Self {
|
pub unsafe fn steal(pin_port: u8) -> Self {
|
||||||
Self { pin_port }
|
Self { pin_port }
|
||||||
}
|
}
|
||||||
@ -280,15 +289,108 @@ impl AnyPin {
|
|||||||
|
|
||||||
impl Pin for AnyPin {}
|
impl Pin for AnyPin {}
|
||||||
impl sealed::Pin for AnyPin {
|
impl sealed::Pin for AnyPin {
|
||||||
|
#[inline]
|
||||||
fn pin_port(&self) -> u8 {
|
fn pin_port(&self) -> u8 {
|
||||||
self.pin_port
|
self.pin_port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PeripheralBorrow for AnyPin {
|
||||||
|
type Target = AnyPin;
|
||||||
|
#[inline]
|
||||||
|
unsafe fn unborrow(self) -> Self::Target {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PeripheralBorrow for &'a mut AnyPin {
|
||||||
|
type Target = AnyPin;
|
||||||
|
#[inline]
|
||||||
|
unsafe fn unborrow(self) -> Self::Target {
|
||||||
|
AnyPin {
|
||||||
|
pin_port: self.pin_port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================
|
||||||
|
|
||||||
|
pub trait OptionalPin: sealed::OptionalPin + Sized {
|
||||||
|
type Pin: Pin;
|
||||||
|
fn pin(&self) -> Option<&Self::Pin>;
|
||||||
|
fn pin_mut(&mut self) -> Option<&mut Self::Pin>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn psel_bits(&self) -> u32 {
|
||||||
|
self.pin().map_or(1u32 << 31, |pin| Pin::psel_bits(pin))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`.
|
||||||
|
#[inline]
|
||||||
|
fn degrade_optional(mut self) -> Option<AnyPin> {
|
||||||
|
self.pin_mut()
|
||||||
|
.map(|pin| unsafe { core::ptr::read(pin) }.degrade())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pin> sealed::OptionalPin for T {}
|
||||||
|
impl<T: Pin> OptionalPin for T {
|
||||||
|
type Pin = T;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pin(&self) -> Option<&T> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pin_mut(&mut self) -> Option<&mut T> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uninhabited enum, so it's actually impossible to create a DummyPin value.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub enum DummyPin {}
|
||||||
|
impl Pin for DummyPin {}
|
||||||
|
impl sealed::Pin for DummyPin {
|
||||||
|
#[inline]
|
||||||
|
fn pin_port(&self) -> u8 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct NoPin;
|
||||||
|
impl sealed::OptionalPin for NoPin {}
|
||||||
|
impl OptionalPin for NoPin {
|
||||||
|
type Pin = DummyPin;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pin(&self) -> Option<&DummyPin> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn pin_mut(&mut self) -> Option<&mut DummyPin> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PeripheralBorrow for NoPin {
|
||||||
|
type Target = NoPin;
|
||||||
|
#[inline]
|
||||||
|
unsafe fn unborrow(self) -> Self::Target {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================
|
||||||
|
|
||||||
macro_rules! make_impl {
|
macro_rules! make_impl {
|
||||||
($type:ident, $port_num:expr, $pin_num:expr) => {
|
($type:ident, $port_num:expr, $pin_num:expr) => {
|
||||||
impl Pin for peripherals::$type {}
|
impl Pin for peripherals::$type {}
|
||||||
impl sealed::Pin for peripherals::$type {
|
impl sealed::Pin for peripherals::$type {
|
||||||
|
#[inline]
|
||||||
fn pin_port(&self) -> u8 {
|
fn pin_port(&self) -> u8 {
|
||||||
$port_num * 32 + $pin_num
|
$port_num * 32 + $pin_num
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user