nrf/gpio: add infallible inherent methods, remove some duplication.
This implements Input and Output using FlexPin, to avoid some code duplication.
This commit is contained in:
parent
fcb43caa36
commit
22bc1e4ae1
@ -14,14 +14,13 @@ use embassy_nrf::{
|
|||||||
peripherals::P0_13,
|
peripherals::P0_13,
|
||||||
Peripherals,
|
Peripherals,
|
||||||
};
|
};
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
|
||||||
|
|
||||||
#[embassy::task]
|
#[embassy::task]
|
||||||
async fn blinker(mut led: Output<'static, P0_13>, interval: Duration) {
|
async fn blinker(mut led: Output<'static, P0_13>, interval: Duration) {
|
||||||
loop {
|
loop {
|
||||||
unwrap!(led.set_high());
|
led.set_high();
|
||||||
Timer::after(interval).await;
|
Timer::after(interval).await;
|
||||||
unwrap!(led.set_low());
|
led.set_low();
|
||||||
Timer::after(interval).await;
|
Timer::after(interval).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::future::Future;
|
|
||||||
use core::hint::unreachable_unchecked;
|
use core::hint::unreachable_unchecked;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
@ -38,26 +37,23 @@ pub enum Pull {
|
|||||||
|
|
||||||
/// GPIO input driver.
|
/// GPIO input driver.
|
||||||
pub struct Input<'d, T: Pin> {
|
pub struct Input<'d, T: Pin> {
|
||||||
pub(crate) pin: T,
|
pub(crate) pin: FlexPin<'d, T>,
|
||||||
phantom: PhantomData<&'d mut T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Input<'d, T> {
|
impl<'d, T: Pin> Input<'d, T> {
|
||||||
pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self {
|
pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self {
|
||||||
unborrow!(pin);
|
let mut pin = FlexPin::new(pin);
|
||||||
|
pin.set_as_input(pull);
|
||||||
|
|
||||||
init_input(&pin, pull);
|
Self { pin }
|
||||||
|
|
||||||
Self {
|
|
||||||
pin,
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Pin> Drop for Input<'d, T> {
|
fn is_high(&self) -> bool {
|
||||||
fn drop(&mut self) {
|
self.pin.is_high()
|
||||||
self.pin.conf().reset();
|
}
|
||||||
|
|
||||||
|
fn is_low(&self) -> bool {
|
||||||
|
self.pin.is_low()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,65 +61,11 @@ impl<'d, T: Pin> InputPin for Input<'d, T> {
|
|||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
self.is_low().map(|v| !v)
|
Ok(self.is_high())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
Ok(self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0)
|
Ok(self.is_low())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpiote")]
|
|
||||||
impl<'d, T: Pin> embassy::traits::gpio::WaitForHigh for Input<'d, T> {
|
|
||||||
type Future<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = ()> + Unpin + 'a;
|
|
||||||
|
|
||||||
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().high());
|
|
||||||
|
|
||||||
crate::gpiote::PortInputFuture {
|
|
||||||
pin_port: self.pin.pin_port(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpiote")]
|
|
||||||
impl<'d, T: Pin> embassy::traits::gpio::WaitForLow for Input<'d, T> {
|
|
||||||
type Future<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = ()> + Unpin + 'a;
|
|
||||||
|
|
||||||
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().low());
|
|
||||||
|
|
||||||
crate::gpiote::PortInputFuture {
|
|
||||||
pin_port: self.pin.pin_port(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpiote")]
|
|
||||||
impl<'d, T: Pin> embassy::traits::gpio::WaitForAnyEdge for Input<'d, T> {
|
|
||||||
type Future<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = ()> + Unpin + 'a;
|
|
||||||
|
|
||||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
|
|
||||||
if self.is_high().ok().unwrap() {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().low());
|
|
||||||
} else {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().high());
|
|
||||||
}
|
|
||||||
crate::gpiote::PortInputFuture {
|
|
||||||
pin_port: self.pin.pin_port(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,8 +102,7 @@ pub enum OutputDrive {
|
|||||||
|
|
||||||
/// GPIO output driver.
|
/// GPIO output driver.
|
||||||
pub struct Output<'d, T: Pin> {
|
pub struct Output<'d, T: Pin> {
|
||||||
pub(crate) pin: T,
|
pub(crate) pin: FlexPin<'d, T>,
|
||||||
phantom: PhantomData<&'d mut T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Output<'d, T> {
|
impl<'d, T: Pin> Output<'d, T> {
|
||||||
@ -170,63 +111,56 @@ impl<'d, T: Pin> Output<'d, T> {
|
|||||||
initial_output: Level,
|
initial_output: Level,
|
||||||
drive: OutputDrive,
|
drive: OutputDrive,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(pin);
|
let mut pin = FlexPin::new(pin);
|
||||||
|
|
||||||
match initial_output {
|
match initial_output {
|
||||||
Level::High => pin.set_high(),
|
Level::High => pin.set_high(),
|
||||||
Level::Low => pin.set_low(),
|
Level::Low => pin.set_low(),
|
||||||
}
|
}
|
||||||
|
pin.set_as_output(drive);
|
||||||
|
|
||||||
init_output(&pin, drive);
|
Self { pin }
|
||||||
|
|
||||||
Self {
|
|
||||||
pin,
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d, T: Pin> Drop for Output<'d, T> {
|
/// Set the output as high.
|
||||||
fn drop(&mut self) {
|
pub fn set_high(&mut self) {
|
||||||
self.pin.conf().reset();
|
self.pin.set_high()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the output as low.
|
||||||
|
pub fn set_low(&mut self) {
|
||||||
|
self.pin.set_low()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is the output pin set as high?
|
||||||
|
pub fn is_set_high(&self) -> bool {
|
||||||
|
self.pin.is_set_high()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is the output pin set as low?
|
||||||
|
pub fn is_set_low(&self) -> bool {
|
||||||
|
self.pin.is_set_low()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> OutputPin for Output<'d, T> {
|
impl<'d, T: Pin> OutputPin for Output<'d, T> {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
/// Set the output as high.
|
|
||||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||||
unsafe {
|
Ok(self.set_high())
|
||||||
self.pin
|
|
||||||
.block()
|
|
||||||
.outset
|
|
||||||
.write(|w| w.bits(1u32 << self.pin.pin()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output as low.
|
|
||||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||||
unsafe {
|
Ok(self.set_low())
|
||||||
self.pin
|
|
||||||
.block()
|
|
||||||
.outclr
|
|
||||||
.write(|w| w.bits(1u32 << self.pin.pin()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
|
impl<'d, T: Pin> StatefulOutputPin for Output<'d, T> {
|
||||||
/// Is the output pin set as high?
|
|
||||||
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||||
self.is_set_low().map(|v| !v)
|
Ok(self.is_set_high())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the output pin set as low?
|
|
||||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
Ok(self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0)
|
Ok(self.is_set_low())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +190,24 @@ impl<'d, T: Pin> FlexPin<'d, T> {
|
|||||||
|
|
||||||
/// Put the pin into input mode.
|
/// Put the pin into input mode.
|
||||||
pub fn set_as_input(&mut self, pull: Pull) {
|
pub fn set_as_input(&mut self, pull: Pull) {
|
||||||
init_input(&self.pin, pull);
|
self.pin.conf().write(|w| {
|
||||||
|
w.dir().input();
|
||||||
|
w.input().connect();
|
||||||
|
match pull {
|
||||||
|
Pull::None => {
|
||||||
|
w.pull().disabled();
|
||||||
|
}
|
||||||
|
Pull::Up => {
|
||||||
|
w.pull().pullup();
|
||||||
|
}
|
||||||
|
Pull::Down => {
|
||||||
|
w.pull().pulldown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.drive().s0s1();
|
||||||
|
w.sense().disabled();
|
||||||
|
w
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put the pin into output mode.
|
/// Put the pin into output mode.
|
||||||
@ -264,13 +215,59 @@ impl<'d, T: Pin> FlexPin<'d, T> {
|
|||||||
/// The pin level will be whatever was set before (or low by default). If you want it to begin
|
/// The pin level will be whatever was set before (or low by default). If you want it to begin
|
||||||
/// at a specific level, call `set_high`/`set_low` on the pin first.
|
/// at a specific level, call `set_high`/`set_low` on the pin first.
|
||||||
pub fn set_as_output(&mut self, drive: OutputDrive) {
|
pub fn set_as_output(&mut self, drive: OutputDrive) {
|
||||||
init_output(&self.pin, drive);
|
let drive = match drive {
|
||||||
|
OutputDrive::Standard => DRIVE_A::S0S1,
|
||||||
|
OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1,
|
||||||
|
OutputDrive::Standard0HighDrive1 => DRIVE_A::S0H1,
|
||||||
|
OutputDrive::HighDrive => DRIVE_A::H0H1,
|
||||||
|
OutputDrive::Disconnect0Standard1 => DRIVE_A::D0S1,
|
||||||
|
OutputDrive::Disconnect0HighDrive1 => DRIVE_A::D0H1,
|
||||||
|
OutputDrive::Standard0Disconnect1 => DRIVE_A::S0D1,
|
||||||
|
OutputDrive::HighDrive0Disconnect1 => DRIVE_A::H0D1,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.pin.conf().write(|w| {
|
||||||
|
w.dir().output();
|
||||||
|
w.input().disconnect();
|
||||||
|
w.pull().disabled();
|
||||||
|
w.drive().variant(drive);
|
||||||
|
w.sense().disabled();
|
||||||
|
w
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put the pin into disconnected mode.
|
/// Put the pin into disconnected mode.
|
||||||
pub fn set_as_disconnected(&mut self) {
|
pub fn set_as_disconnected(&mut self) {
|
||||||
self.pin.conf().reset();
|
self.pin.conf().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_high(&self) -> bool {
|
||||||
|
!self.is_low()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_low(&self) -> bool {
|
||||||
|
self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the output as high.
|
||||||
|
pub fn set_high(&mut self) {
|
||||||
|
self.pin.set_high()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the output as low.
|
||||||
|
pub fn set_low(&mut self) {
|
||||||
|
self.pin.set_low()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is the output pin set as high?
|
||||||
|
pub fn is_set_high(&self) -> bool {
|
||||||
|
!self.is_set_low()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Is the output pin set as low?
|
||||||
|
pub fn is_set_low(&self) -> bool {
|
||||||
|
self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> Drop for FlexPin<'d, T> {
|
impl<'d, T: Pin> Drop for FlexPin<'d, T> {
|
||||||
@ -286,103 +283,33 @@ impl<'d, T: Pin> InputPin for FlexPin<'d, T> {
|
|||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
fn is_high(&self) -> Result<bool, Self::Error> {
|
fn is_high(&self) -> Result<bool, Self::Error> {
|
||||||
self.is_low().map(|v| !v)
|
Ok(self.is_high())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_low(&self) -> Result<bool, Self::Error> {
|
fn is_low(&self) -> Result<bool, Self::Error> {
|
||||||
Ok(self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0)
|
Ok(self.is_low())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> OutputPin for FlexPin<'d, T> {
|
impl<'d, T: Pin> OutputPin for FlexPin<'d, T> {
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
|
|
||||||
/// Set the output as high.
|
|
||||||
fn set_high(&mut self) -> Result<(), Self::Error> {
|
fn set_high(&mut self) -> Result<(), Self::Error> {
|
||||||
unsafe {
|
Ok(self.set_high())
|
||||||
self.pin
|
|
||||||
.block()
|
|
||||||
.outset
|
|
||||||
.write(|w| w.bits(1u32 << self.pin.pin()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the output as low.
|
|
||||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||||
unsafe {
|
Ok(self.set_low())
|
||||||
self.pin
|
|
||||||
.block()
|
|
||||||
.outclr
|
|
||||||
.write(|w| w.bits(1u32 << self.pin.pin()));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Pin> StatefulOutputPin for FlexPin<'d, T> {
|
impl<'d, T: Pin> StatefulOutputPin for FlexPin<'d, T> {
|
||||||
/// Is the output pin set as high?
|
|
||||||
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
fn is_set_high(&self) -> Result<bool, Self::Error> {
|
||||||
self.is_set_low().map(|v| !v)
|
Ok(self.is_set_high())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the output pin set as low?
|
|
||||||
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
fn is_set_low(&self) -> Result<bool, Self::Error> {
|
||||||
Ok(self.pin.block().out.read().bits() & (1 << self.pin.pin()) == 0)
|
Ok(self.is_set_low())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpiote")]
|
|
||||||
impl<'d, T: Pin> embassy::traits::gpio::WaitForHigh for FlexPin<'d, T> {
|
|
||||||
type Future<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = ()> + Unpin + 'a;
|
|
||||||
|
|
||||||
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().high());
|
|
||||||
|
|
||||||
crate::gpiote::PortInputFuture {
|
|
||||||
pin_port: self.pin.pin_port(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpiote")]
|
|
||||||
impl<'d, T: Pin> embassy::traits::gpio::WaitForLow for FlexPin<'d, T> {
|
|
||||||
type Future<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = ()> + Unpin + 'a;
|
|
||||||
|
|
||||||
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().low());
|
|
||||||
|
|
||||||
crate::gpiote::PortInputFuture {
|
|
||||||
pin_port: self.pin.pin_port(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gpiote")]
|
|
||||||
impl<'d, T: Pin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> {
|
|
||||||
type Future<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = ()> + Unpin + 'a;
|
|
||||||
|
|
||||||
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
|
|
||||||
if self.is_high().ok().unwrap() {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().low());
|
|
||||||
} else {
|
|
||||||
self.pin.conf().modify(|_, w| w.sense().high());
|
|
||||||
}
|
|
||||||
crate::gpiote::PortInputFuture {
|
|
||||||
pin_port: self.pin.pin_port(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,55 +420,6 @@ impl sealed::Pin for AnyPin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====================
|
|
||||||
|
|
||||||
/// Set up a pin for input
|
|
||||||
#[inline]
|
|
||||||
fn init_input<T: Pin>(pin: &T, pull: Pull) {
|
|
||||||
pin.conf().write(|w| {
|
|
||||||
w.dir().input();
|
|
||||||
w.input().connect();
|
|
||||||
match pull {
|
|
||||||
Pull::None => {
|
|
||||||
w.pull().disabled();
|
|
||||||
}
|
|
||||||
Pull::Up => {
|
|
||||||
w.pull().pullup();
|
|
||||||
}
|
|
||||||
Pull::Down => {
|
|
||||||
w.pull().pulldown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.drive().s0s1();
|
|
||||||
w.sense().disabled();
|
|
||||||
w
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set up a pin for output
|
|
||||||
#[inline]
|
|
||||||
fn init_output<T: Pin>(pin: &T, drive: OutputDrive) {
|
|
||||||
let drive = match drive {
|
|
||||||
OutputDrive::Standard => DRIVE_A::S0S1,
|
|
||||||
OutputDrive::HighDrive0Standard1 => DRIVE_A::H0S1,
|
|
||||||
OutputDrive::Standard0HighDrive1 => DRIVE_A::S0H1,
|
|
||||||
OutputDrive::HighDrive => DRIVE_A::H0H1,
|
|
||||||
OutputDrive::Disconnect0Standard1 => DRIVE_A::D0S1,
|
|
||||||
OutputDrive::Disconnect0HighDrive1 => DRIVE_A::D0H1,
|
|
||||||
OutputDrive::Standard0Disconnect1 => DRIVE_A::S0D1,
|
|
||||||
OutputDrive::HighDrive0Disconnect1 => DRIVE_A::H0D1,
|
|
||||||
};
|
|
||||||
|
|
||||||
pin.conf().write(|w| {
|
|
||||||
w.dir().output();
|
|
||||||
w.input().disconnect();
|
|
||||||
w.pull().disabled();
|
|
||||||
w.drive().variant(drive);
|
|
||||||
w.sense().disabled();
|
|
||||||
w
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
|
|
||||||
pub trait OptionalPin: Unborrow<Target = Self> + sealed::OptionalPin + Sized {
|
pub trait OptionalPin: Unborrow<Target = Self> + sealed::OptionalPin + Sized {
|
||||||
@ -601,9 +479,7 @@ pub(crate) fn deconfigure_pin(psel_bits: u32) {
|
|||||||
if psel_bits & 0x8000_0000 != 0 {
|
if psel_bits & 0x8000_0000 != 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe { AnyPin::steal(psel_bits as _).conf().reset() }
|
||||||
AnyPin::steal(psel_bits as _).conf().reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================
|
// ====================
|
||||||
|
@ -5,11 +5,11 @@ use core::task::{Context, Poll};
|
|||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy::waitqueue::AtomicWaker;
|
use embassy::waitqueue::AtomicWaker;
|
||||||
use embassy_hal_common::unsafe_impl_unborrow;
|
use embassy_hal_common::unsafe_impl_unborrow;
|
||||||
use embedded_hal::digital::v2::{InputPin, StatefulOutputPin};
|
use embedded_hal::digital::v2::InputPin;
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
use crate::gpio::sealed::Pin as _;
|
use crate::gpio::sealed::Pin as _;
|
||||||
use crate::gpio::{AnyPin, Input, Output, Pin as GpioPin};
|
use crate::gpio::{AnyPin, FlexPin, Input, Output, Pin as GpioPin};
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::ppi::{Event, Task};
|
use crate::ppi::{Event, Task};
|
||||||
use crate::{interrupt, peripherals};
|
use crate::{interrupt, peripherals};
|
||||||
@ -177,11 +177,11 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
|
|||||||
InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
|
InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(),
|
||||||
};
|
};
|
||||||
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
|
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
|
||||||
w.port().bit(match pin.pin.port() {
|
w.port().bit(match pin.pin.pin.port() {
|
||||||
crate::gpio::Port::Port0 => false,
|
crate::gpio::Port::Port0 => false,
|
||||||
crate::gpio::Port::Port1 => true,
|
crate::gpio::Port::Port1 => true,
|
||||||
});
|
});
|
||||||
unsafe { w.psel().bits(pin.pin.pin()) }
|
unsafe { w.psel().bits(pin.pin.pin.pin()) }
|
||||||
});
|
});
|
||||||
|
|
||||||
g.events_in[num].reset();
|
g.events_in[num].reset();
|
||||||
@ -250,7 +250,7 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
|
|||||||
|
|
||||||
g.config[num].write(|w| {
|
g.config[num].write(|w| {
|
||||||
w.mode().task();
|
w.mode().task();
|
||||||
match pin.is_set_high().unwrap() {
|
match pin.is_set_high() {
|
||||||
true => w.outinit().high(),
|
true => w.outinit().high(),
|
||||||
false => w.outinit().low(),
|
false => w.outinit().low(),
|
||||||
};
|
};
|
||||||
@ -260,11 +260,11 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
|
|||||||
OutputChannelPolarity::Toggle => w.polarity().toggle(),
|
OutputChannelPolarity::Toggle => w.polarity().toggle(),
|
||||||
};
|
};
|
||||||
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
|
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
|
||||||
w.port().bit(match pin.pin.port() {
|
w.port().bit(match pin.pin.pin.port() {
|
||||||
crate::gpio::Port::Port0 => false,
|
crate::gpio::Port::Port0 => false,
|
||||||
crate::gpio::Port::Port1 => true,
|
crate::gpio::Port::Port1 => true,
|
||||||
});
|
});
|
||||||
unsafe { w.psel().bits(pin.pin.pin()) }
|
unsafe { w.psel().bits(pin.pin.pin.pin()) }
|
||||||
});
|
});
|
||||||
|
|
||||||
OutputChannel { ch, _pin: pin }
|
OutputChannel { ch, _pin: pin }
|
||||||
@ -311,9 +311,11 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =======================
|
||||||
|
|
||||||
pub(crate) struct PortInputFuture<'a> {
|
pub(crate) struct PortInputFuture<'a> {
|
||||||
pub(crate) pin_port: u8,
|
pin_port: u8,
|
||||||
pub(crate) phantom: PhantomData<&'a mut AnyPin>,
|
phantom: PhantomData<&'a mut AnyPin>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Unpin for PortInputFuture<'a> {}
|
impl<'a> Unpin for PortInputFuture<'a> {}
|
||||||
@ -340,6 +342,92 @@ impl<'a> Future for PortInputFuture<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GpioPin> embassy::traits::gpio::WaitForHigh for Input<'d, T> {
|
||||||
|
type Future<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = ()> + Unpin + 'a;
|
||||||
|
|
||||||
|
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
|
||||||
|
self.pin.wait_for_high()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GpioPin> embassy::traits::gpio::WaitForLow for Input<'d, T> {
|
||||||
|
type Future<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = ()> + Unpin + 'a;
|
||||||
|
|
||||||
|
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
|
||||||
|
self.pin.wait_for_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for Input<'d, T> {
|
||||||
|
type Future<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = ()> + Unpin + 'a;
|
||||||
|
|
||||||
|
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
|
||||||
|
self.pin.wait_for_any_edge()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GpioPin> embassy::traits::gpio::WaitForHigh for FlexPin<'d, T> {
|
||||||
|
type Future<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = ()> + Unpin + 'a;
|
||||||
|
|
||||||
|
fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> {
|
||||||
|
self.pin.conf().modify(|_, w| w.sense().high());
|
||||||
|
|
||||||
|
PortInputFuture {
|
||||||
|
pin_port: self.pin.pin_port(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GpioPin> embassy::traits::gpio::WaitForLow for FlexPin<'d, T> {
|
||||||
|
type Future<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = ()> + Unpin + 'a;
|
||||||
|
|
||||||
|
fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
|
||||||
|
self.pin.conf().modify(|_, w| w.sense().low());
|
||||||
|
|
||||||
|
PortInputFuture {
|
||||||
|
pin_port: self.pin.pin_port(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: GpioPin> embassy::traits::gpio::WaitForAnyEdge for FlexPin<'d, T> {
|
||||||
|
type Future<'a>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
= impl Future<Output = ()> + Unpin + 'a;
|
||||||
|
|
||||||
|
fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
|
||||||
|
if self.is_high() {
|
||||||
|
self.pin.conf().modify(|_, w| w.sense().low());
|
||||||
|
} else {
|
||||||
|
self.pin.conf().modify(|_, w| w.sense().high());
|
||||||
|
}
|
||||||
|
PortInputFuture {
|
||||||
|
pin_port: self.pin.pin_port(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================
|
||||||
|
|
||||||
mod sealed {
|
mod sealed {
|
||||||
pub trait Channel {}
|
pub trait Channel {}
|
||||||
}
|
}
|
||||||
|
@ -5,21 +5,19 @@
|
|||||||
#[path = "../example_common.rs"]
|
#[path = "../example_common.rs"]
|
||||||
mod example_common;
|
mod example_common;
|
||||||
|
|
||||||
use defmt::unwrap;
|
|
||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy_nrf::gpio::{Level, Output, OutputDrive};
|
use embassy_nrf::gpio::{Level, Output, OutputDrive};
|
||||||
use embassy_nrf::Peripherals;
|
use embassy_nrf::Peripherals;
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
|
||||||
|
|
||||||
#[embassy::main]
|
#[embassy::main]
|
||||||
async fn main(_spawner: Spawner, p: Peripherals) {
|
async fn main(_spawner: Spawner, p: Peripherals) {
|
||||||
let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
|
let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
unwrap!(led.set_high());
|
led.set_high();
|
||||||
Timer::after(Duration::from_millis(300)).await;
|
Timer::after(Duration::from_millis(300)).await;
|
||||||
unwrap!(led.set_low());
|
led.set_low();
|
||||||
Timer::after(Duration::from_millis(300)).await;
|
Timer::after(Duration::from_millis(300)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ use embassy::time::{Duration, Timer};
|
|||||||
use embassy::util::Forever;
|
use embassy::util::Forever;
|
||||||
use embassy_nrf::gpio::{Level, Output, OutputDrive};
|
use embassy_nrf::gpio::{Level, Output, OutputDrive};
|
||||||
use embassy_nrf::Peripherals;
|
use embassy_nrf::Peripherals;
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
|
||||||
|
|
||||||
enum LedState {
|
enum LedState {
|
||||||
On,
|
On,
|
||||||
@ -53,8 +52,8 @@ async fn main(spawner: Spawner, p: Peripherals) {
|
|||||||
Err(TryRecvError::Closed) => break,
|
Err(TryRecvError::Closed) => break,
|
||||||
};
|
};
|
||||||
match maybe_message {
|
match maybe_message {
|
||||||
Some(LedState::On) => unwrap!(led.set_high()),
|
Some(LedState::On) => led.set_high(),
|
||||||
Some(LedState::Off) => unwrap!(led.set_low()),
|
Some(LedState::Off) => led.set_low(),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ use embassy_nrf::gpio::{Level, Output, OutputDrive};
|
|||||||
use embassy_nrf::Peripherals;
|
use embassy_nrf::Peripherals;
|
||||||
use embassy_nrf::{interrupt, spim};
|
use embassy_nrf::{interrupt, spim};
|
||||||
use embassy_traits::spi::FullDuplex;
|
use embassy_traits::spi::FullDuplex;
|
||||||
use embedded_hal::digital::v2::*;
|
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
#[embassy::main]
|
#[embassy::main]
|
||||||
@ -29,12 +28,12 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
|||||||
|
|
||||||
// softreset
|
// softreset
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
unwrap!(ncs.set_low());
|
ncs.set_low();
|
||||||
cortex_m::asm::delay(5);
|
cortex_m::asm::delay(5);
|
||||||
let tx = [0xFF];
|
let tx = [0xFF];
|
||||||
unwrap!(spim.read_write(&mut [], &tx).await);
|
unwrap!(spim.read_write(&mut [], &tx).await);
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
unwrap!(ncs.set_high());
|
ncs.set_high();
|
||||||
|
|
||||||
cortex_m::asm::delay(100000);
|
cortex_m::asm::delay(100000);
|
||||||
|
|
||||||
@ -42,31 +41,31 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
|||||||
|
|
||||||
// read ESTAT
|
// read ESTAT
|
||||||
cortex_m::asm::delay(5000);
|
cortex_m::asm::delay(5000);
|
||||||
unwrap!(ncs.set_low());
|
ncs.set_low();
|
||||||
cortex_m::asm::delay(5000);
|
cortex_m::asm::delay(5000);
|
||||||
let tx = [0b000_11101, 0];
|
let tx = [0b000_11101, 0];
|
||||||
unwrap!(spim.read_write(&mut rx, &tx).await);
|
unwrap!(spim.read_write(&mut rx, &tx).await);
|
||||||
cortex_m::asm::delay(5000);
|
cortex_m::asm::delay(5000);
|
||||||
unwrap!(ncs.set_high());
|
ncs.set_high();
|
||||||
info!("estat: {=[?]}", rx);
|
info!("estat: {=[?]}", rx);
|
||||||
|
|
||||||
// Switch to bank 3
|
// Switch to bank 3
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
unwrap!(ncs.set_low());
|
ncs.set_low();
|
||||||
cortex_m::asm::delay(5);
|
cortex_m::asm::delay(5);
|
||||||
let tx = [0b100_11111, 0b11];
|
let tx = [0b100_11111, 0b11];
|
||||||
unwrap!(spim.read_write(&mut rx, &tx).await);
|
unwrap!(spim.read_write(&mut rx, &tx).await);
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
unwrap!(ncs.set_high());
|
ncs.set_high();
|
||||||
|
|
||||||
// read EREVID
|
// read EREVID
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
unwrap!(ncs.set_low());
|
ncs.set_low();
|
||||||
cortex_m::asm::delay(5);
|
cortex_m::asm::delay(5);
|
||||||
let tx = [0b000_10010, 0];
|
let tx = [0b000_10010, 0];
|
||||||
unwrap!(spim.read_write(&mut rx, &tx).await);
|
unwrap!(spim.read_write(&mut rx, &tx).await);
|
||||||
cortex_m::asm::delay(10);
|
cortex_m::asm::delay(10);
|
||||||
unwrap!(ncs.set_high());
|
ncs.set_high();
|
||||||
|
|
||||||
info!("erevid: {=[?]}", rx);
|
info!("erevid: {=[?]}", rx);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user