diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-20 03:09:42 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-29 00:58:57 +0200 |
| commit | ba7b3974bb0092f0a9d3bf5e02fb5d4c41c53083 (patch) | |
| tree | b9704aae9834c41ed81b4e45b70e317de642d947 | |
| parent | 3d3e770b8dca9adb50b02f14d0087fe40ee1ce35 (diff) | |
nrf/gpiote: update to new gpio
| -rw-r--r-- | embassy-nrf-examples/src/bin/gpiote_port.rs | 19 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 8 | ||||
| -rw-r--r-- | embassy-nrf/src/gpiote.rs | 281 |
3 files changed, 137 insertions, 171 deletions
diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs index 36ee1c8ea..273cd124d 100644 --- a/embassy-nrf-examples/src/bin/gpiote_port.rs +++ b/embassy-nrf-examples/src/bin/gpiote_port.rs | |||
| @@ -6,7 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #[path = "../example_common.rs"] | 7 | #[path = "../example_common.rs"] |
| 8 | mod example_common; | 8 | mod example_common; |
| 9 | use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; | ||
| 9 | use example_common::*; | 10 | use example_common::*; |
| 11 | use gpiote::GpioteInput; | ||
| 10 | 12 | ||
| 11 | use core::pin::Pin; | 13 | use core::pin::Pin; |
| 12 | use cortex_m_rt::entry; | 14 | use cortex_m_rt::entry; |
| @@ -16,10 +18,10 @@ use nrf52840_hal::gpio; | |||
| 16 | use embassy::executor::{task, Executor}; | 18 | use embassy::executor::{task, Executor}; |
| 17 | use embassy::traits::gpio::{WaitForHigh, WaitForLow}; | 19 | use embassy::traits::gpio::{WaitForHigh, WaitForLow}; |
| 18 | use embassy::util::Forever; | 20 | use embassy::util::Forever; |
| 19 | use embassy_nrf::gpiote::{Gpiote, GpiotePin}; | 21 | use embassy_nrf::gpiote; |
| 20 | use embassy_nrf::interrupt; | 22 | use embassy_nrf::interrupt; |
| 21 | 23 | ||
| 22 | async fn button(n: usize, mut pin: GpiotePin<gpio::PullUp>) { | 24 | async fn button(n: usize, mut pin: GpioteInput<AnyPin>) { |
| 23 | loop { | 25 | loop { |
| 24 | Pin::new(&mut pin).wait_for_low().await; | 26 | Pin::new(&mut pin).wait_for_low().await; |
| 25 | info!("Button {:?} pressed!", n); | 27 | info!("Button {:?} pressed!", n); |
| @@ -30,26 +32,25 @@ async fn button(n: usize, mut pin: GpiotePin<gpio::PullUp>) { | |||
| 30 | 32 | ||
| 31 | #[task] | 33 | #[task] |
| 32 | async fn run() { | 34 | async fn run() { |
| 33 | let p = unwrap!(embassy_nrf::pac::Peripherals::take()); | 35 | let p = unsafe { embassy_nrf::peripherals::Peripherals::steal() }; |
| 34 | let port0 = gpio::p0::Parts::new(p.P0); | ||
| 35 | 36 | ||
| 36 | let (g, _) = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE)); | 37 | let g = gpiote::initialize(p.gpiote, interrupt::take!(GPIOTE)); |
| 37 | 38 | ||
| 38 | let button1 = button( | 39 | let button1 = button( |
| 39 | 1, | 40 | 1, |
| 40 | GpiotePin::new(g, port0.p0_11.into_pullup_input().degrade()), | 41 | GpioteInput::new(g, Input::new(p.p0_11.degrade(), Pull::Up)), |
| 41 | ); | 42 | ); |
| 42 | let button2 = button( | 43 | let button2 = button( |
| 43 | 2, | 44 | 2, |
| 44 | GpiotePin::new(g, port0.p0_12.into_pullup_input().degrade()), | 45 | GpioteInput::new(g, Input::new(p.p0_12.degrade(), Pull::Up)), |
| 45 | ); | 46 | ); |
| 46 | let button3 = button( | 47 | let button3 = button( |
| 47 | 3, | 48 | 3, |
| 48 | GpiotePin::new(g, port0.p0_24.into_pullup_input().degrade()), | 49 | GpioteInput::new(g, Input::new(p.p0_24.degrade(), Pull::Up)), |
| 49 | ); | 50 | ); |
| 50 | let button4 = button( | 51 | let button4 = button( |
| 51 | 4, | 52 | 4, |
| 52 | GpiotePin::new(g, port0.p0_25.into_pullup_input().degrade()), | 53 | GpioteInput::new(g, Input::new(p.p0_25.degrade(), Pull::Up)), |
| 53 | ); | 54 | ); |
| 54 | futures::join!(button1, button2, button3, button4); | 55 | futures::join!(button1, button2, button3, button4); |
| 55 | } | 56 | } |
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 52cb57319..dd334c633 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -30,7 +30,7 @@ pub enum Pull { | |||
| 30 | 30 | ||
| 31 | /// GPIO input driver. | 31 | /// GPIO input driver. |
| 32 | pub struct Input<T: Pin> { | 32 | pub struct Input<T: Pin> { |
| 33 | pin: T, | 33 | pub(crate) pin: T, |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | impl<T: Pin> Input<T> { | 36 | impl<T: Pin> Input<T> { |
| @@ -273,10 +273,8 @@ pub struct AnyPin { | |||
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | impl AnyPin { | 275 | impl AnyPin { |
| 276 | pub unsafe fn steal_from_psel_bits(psel_bits: u32) -> Self { | 276 | pub unsafe fn steal(pin_port: u8) -> Self { |
| 277 | Self { | 277 | Self { pin_port } |
| 278 | pin_port: psel_bits as u8, | ||
| 279 | } | ||
| 280 | } | 278 | } |
| 281 | } | 279 | } |
| 282 | 280 | ||
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 5dc80a639..2b603c4c1 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs | |||
| @@ -1,19 +1,24 @@ | |||
| 1 | use core::convert::Infallible; | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 2 | use core::mem::ManuallyDrop; | 3 | use core::intrinsics::transmute; |
| 4 | use core::marker::PhantomData; | ||
| 5 | use core::mem::{self, ManuallyDrop}; | ||
| 3 | use core::ops::Deref; | 6 | use core::ops::Deref; |
| 4 | use core::pin::Pin; | 7 | use core::pin::Pin; |
| 5 | use core::ptr; | 8 | use core::ptr; |
| 6 | use core::task::{Context, Poll}; | 9 | use core::task::{Context, Poll}; |
| 7 | use embassy::interrupt::InterruptExt; | 10 | use embassy::interrupt::InterruptExt; |
| 8 | use embassy::traits::gpio::{WaitForHigh, WaitForLow}; | 11 | use embassy::traits::gpio::{WaitForHigh, WaitForLow}; |
| 9 | use embassy::util::Signal; | 12 | use embassy::util::{AtomicWakerRegistration, Signal}; |
| 13 | use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; | ||
| 10 | 14 | ||
| 11 | use crate::hal::gpio::{Input, Level, Output, Pin as GpioPin, Port}; | 15 | use crate::gpio::sealed::Pin as _; |
| 12 | use crate::interrupt; | 16 | use crate::gpio::{AnyPin, Input, Pin as GpioPin, Pull}; |
| 13 | use crate::pac; | 17 | use crate::pac; |
| 14 | use crate::pac::generic::Reg; | 18 | use crate::pac::generic::Reg; |
| 15 | use crate::pac::gpiote::_TASKS_OUT; | 19 | use crate::pac::gpiote::_TASKS_OUT; |
| 16 | use crate::pac::{p0 as pac_gpio, GPIOTE}; | 20 | use crate::pac::p0 as pac_gpio; |
| 21 | use crate::{interrupt, peripherals}; | ||
| 17 | 22 | ||
| 18 | #[cfg(not(feature = "51"))] | 23 | #[cfg(not(feature = "51"))] |
| 19 | use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET}; | 24 | use crate::pac::gpiote::{_TASKS_CLR, _TASKS_SET}; |
| @@ -63,12 +68,9 @@ impl ChannelID for ChAny { | |||
| 63 | } | 68 | } |
| 64 | } | 69 | } |
| 65 | 70 | ||
| 66 | #[derive(Clone, Copy)] | 71 | const NEW_AWR: AtomicWakerRegistration = AtomicWakerRegistration::new(); |
| 67 | pub struct Gpiote(()); | 72 | static CHANNEL_WAKERS: [AtomicWakerRegistration; CHANNEL_COUNT] = [NEW_AWR; CHANNEL_COUNT]; |
| 68 | 73 | static PORT_WAKERS: [AtomicWakerRegistration; PIN_COUNT] = [NEW_AWR; PIN_COUNT]; | |
| 69 | const NEW_SIGNAL: Signal<()> = Signal::new(); | ||
| 70 | static CHANNEL_SIGNALS: [Signal<()>; CHANNEL_COUNT] = [NEW_SIGNAL; CHANNEL_COUNT]; | ||
| 71 | static PORT_SIGNALS: [Signal<()>; PIN_COUNT] = [NEW_SIGNAL; PIN_COUNT]; | ||
| 72 | 74 | ||
| 73 | pub enum InputChannelPolarity { | 75 | pub enum InputChannelPolarity { |
| 74 | None, | 76 | None, |
| @@ -84,117 +86,84 @@ pub enum OutputChannelPolarity { | |||
| 84 | Toggle, | 86 | Toggle, |
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | 89 | /// Token indicating GPIOTE has been correctly initialized. |
| 88 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 90 | /// |
| 89 | pub enum NewChannelError { | 91 | /// This is not an owned singleton, it is Copy. Drivers that make use of GPIOTE require it. |
| 90 | NoFreeChannels, | 92 | #[derive(Clone, Copy)] |
| 93 | pub struct Initialized { | ||
| 94 | _private: (), | ||
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | pub struct Channels { | 97 | pub fn initialize(gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initialized { |
| 94 | pub ch0: Ch0, | 98 | #[cfg(any(feature = "52833", feature = "52840"))] |
| 95 | pub ch1: Ch1, | 99 | let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] }; |
| 96 | pub ch2: Ch2, | 100 | #[cfg(not(any(feature = "52833", feature = "52840")))] |
| 97 | pub ch3: Ch3, | 101 | let ports = unsafe { &[&*pac::P0::ptr()] }; |
| 98 | pub ch4: Ch4, | 102 | |
| 99 | pub ch5: Ch5, | 103 | for &p in ports { |
| 100 | pub ch6: Ch6, | 104 | // Enable latched detection |
| 101 | pub ch7: Ch7, | 105 | p.detectmode.write(|w| w.detectmode().ldetect()); |
| 106 | // Clear latch | ||
| 107 | p.latch.write(|w| unsafe { w.bits(0xFFFFFFFF) }) | ||
| 108 | } | ||
| 109 | |||
| 110 | // Enable interrupts | ||
| 111 | let g = unsafe { &*pac::GPIOTE::ptr() }; | ||
| 112 | g.events_port.write(|w| w); | ||
| 113 | g.intenset.write(|w| w.port().set()); | ||
| 114 | irq.set_handler(on_irq); | ||
| 115 | irq.unpend(); | ||
| 116 | irq.enable(); | ||
| 117 | |||
| 118 | Initialized { _private: () } | ||
| 102 | } | 119 | } |
| 103 | 120 | ||
| 104 | impl Gpiote { | 121 | unsafe fn on_irq(_ctx: *mut ()) { |
| 105 | pub fn new(gpiote: GPIOTE, irq: interrupt::GPIOTE) -> (Self, Channels) { | 122 | let g = &*pac::GPIOTE::ptr(); |
| 106 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 107 | let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] }; | ||
| 108 | #[cfg(not(any(feature = "52833", feature = "52840")))] | ||
| 109 | let ports = unsafe { &[&*pac::P0::ptr()] }; | ||
| 110 | 123 | ||
| 111 | for &p in ports { | 124 | for i in 0..CHANNEL_COUNT { |
| 112 | // Enable latched detection | 125 | if g.events_in[i].read().bits() != 0 { |
| 113 | p.detectmode.write(|w| w.detectmode().ldetect()); | 126 | g.events_in[i].write(|w| w); |
| 114 | // Clear latch | 127 | CHANNEL_WAKERS[i].wake(); |
| 115 | p.latch.write(|w| unsafe { w.bits(0xFFFFFFFF) }) | ||
| 116 | } | 128 | } |
| 117 | |||
| 118 | // Enable interrupts | ||
| 119 | gpiote.events_port.write(|w| w); | ||
| 120 | gpiote.intenset.write(|w| w.port().set()); | ||
| 121 | irq.set_handler(Self::on_irq); | ||
| 122 | irq.unpend(); | ||
| 123 | irq.enable(); | ||
| 124 | |||
| 125 | ( | ||
| 126 | Self(()), | ||
| 127 | Channels { | ||
| 128 | ch0: Ch0(()), | ||
| 129 | ch1: Ch1(()), | ||
| 130 | ch2: Ch2(()), | ||
| 131 | ch3: Ch3(()), | ||
| 132 | ch4: Ch4(()), | ||
| 133 | ch5: Ch5(()), | ||
| 134 | ch6: Ch6(()), | ||
| 135 | ch7: Ch7(()), | ||
| 136 | }, | ||
| 137 | ) | ||
| 138 | } | 129 | } |
| 139 | 130 | ||
| 140 | unsafe fn on_irq(_ctx: *mut ()) { | 131 | if g.events_port.read().bits() != 0 { |
| 141 | let g = &*GPIOTE::ptr(); | 132 | g.events_port.write(|w| w); |
| 142 | 133 | ||
| 143 | for (event_in, signal) in g.events_in.iter().zip(CHANNEL_SIGNALS.iter()) { | 134 | #[cfg(any(feature = "52833", feature = "52840"))] |
| 144 | if event_in.read().bits() != 0 { | 135 | let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()]; |
| 145 | event_in.write(|w| w); | 136 | #[cfg(not(any(feature = "52833", feature = "52840")))] |
| 146 | signal.signal(()); | 137 | let ports = &[&*pac::P0::ptr()]; |
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | if g.events_port.read().bits() != 0 { | ||
| 151 | g.events_port.write(|w| w); | ||
| 152 | 138 | ||
| 153 | #[cfg(any(feature = "52833", feature = "52840"))] | 139 | for (port, &p) in ports.iter().enumerate() { |
| 154 | let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()]; | 140 | let bits = p.latch.read().bits(); |
| 155 | #[cfg(not(any(feature = "52833", feature = "52840")))] | 141 | for pin in BitIter(bits) { |
| 156 | let ports = &[&*pac::P0::ptr()]; | 142 | p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled()); |
| 157 | 143 | PORT_WAKERS[port * 32 + pin as usize].wake(); | |
| 158 | let mut work = true; | ||
| 159 | while work { | ||
| 160 | work = false; | ||
| 161 | for (port, &p) in ports.iter().enumerate() { | ||
| 162 | for pin in BitIter(p.latch.read().bits()) { | ||
| 163 | work = true; | ||
| 164 | p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled()); | ||
| 165 | p.latch.write(|w| w.bits(1 << pin)); | ||
| 166 | PORT_SIGNALS[port * 32 + pin as usize].signal(()); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | 144 | } |
| 145 | p.latch.write(|w| w.bits(bits)); | ||
| 170 | } | 146 | } |
| 171 | } | 147 | } |
| 172 | } | 148 | } |
| 173 | 149 | ||
| 174 | fn pin_num<T>(pin: &GpioPin<T>) -> usize { | 150 | struct BitIter(u32); |
| 175 | let port = match pin.port() { | ||
| 176 | Port::Port0 => 0, | ||
| 177 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 178 | Port::Port1 => 32, | ||
| 179 | }; | ||
| 180 | |||
| 181 | port + pin.pin() as usize | ||
| 182 | } | ||
| 183 | |||
| 184 | fn pin_block<T>(pin: &GpioPin<T>) -> &pac_gpio::RegisterBlock { | ||
| 185 | let ptr = match pin.port() { | ||
| 186 | Port::Port0 => pac::P0::ptr(), | ||
| 187 | #[cfg(any(feature = "52833", feature = "52840"))] | ||
| 188 | Port::Port1 => pac::P1::ptr(), | ||
| 189 | }; | ||
| 190 | 151 | ||
| 191 | unsafe { &*ptr } | 152 | impl Iterator for BitIter { |
| 192 | } | 153 | type Item = u32; |
| 193 | 154 | ||
| 194 | fn pin_conf<T>(pin: &GpioPin<T>) -> &pac_gpio::PIN_CNF { | 155 | fn next(&mut self) -> Option<Self::Item> { |
| 195 | &pin_block(pin).pin_cnf[pin.pin() as usize] | 156 | match self.0.trailing_zeros() { |
| 157 | 32 => None, | ||
| 158 | b => { | ||
| 159 | self.0 &= !(1 << b); | ||
| 160 | Some(b) | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 196 | } | 164 | } |
| 197 | 165 | ||
| 166 | /* | ||
| 198 | pub struct InputChannel<C: ChannelID, T> { | 167 | pub struct InputChannel<C: ChannelID, T> { |
| 199 | ch: C, | 168 | ch: C, |
| 200 | pin: GpioPin<Input<T>>, | 169 | pin: GpioPin<Input<T>>, |
| @@ -211,7 +180,7 @@ impl<C: ChannelID, T> Drop for InputChannel<C, T> { | |||
| 211 | 180 | ||
| 212 | impl<C: ChannelID, T> InputChannel<C, T> { | 181 | impl<C: ChannelID, T> InputChannel<C, T> { |
| 213 | pub fn new( | 182 | pub fn new( |
| 214 | _gpiote: Gpiote, | 183 | _init: Initialized, |
| 215 | ch: C, | 184 | ch: C, |
| 216 | pin: GpioPin<Input<T>>, | 185 | pin: GpioPin<Input<T>>, |
| 217 | polarity: InputChannelPolarity, | 186 | polarity: InputChannelPolarity, |
| @@ -234,7 +203,7 @@ impl<C: ChannelID, T> InputChannel<C, T> { | |||
| 234 | unsafe { w.psel().bits(pin.pin()) } | 203 | unsafe { w.psel().bits(pin.pin()) } |
| 235 | }); | 204 | }); |
| 236 | 205 | ||
| 237 | CHANNEL_SIGNALS[index].reset(); | 206 | CHANNEL_WAKERS[index].reset(); |
| 238 | 207 | ||
| 239 | // Enable interrupt | 208 | // Enable interrupt |
| 240 | g.intenset.write(|w| unsafe { w.bits(1 << index) }); | 209 | g.intenset.write(|w| unsafe { w.bits(1 << index) }); |
| @@ -251,7 +220,7 @@ impl<C: ChannelID, T> InputChannel<C, T> { | |||
| 251 | 220 | ||
| 252 | pub async fn wait(&self) { | 221 | pub async fn wait(&self) { |
| 253 | let index = self.ch.number(); | 222 | let index = self.ch.number(); |
| 254 | CHANNEL_SIGNALS[index].wait().await; | 223 | CHANNEL_WAKERS[index].wait().await; |
| 255 | } | 224 | } |
| 256 | 225 | ||
| 257 | pub fn pin(&self) -> &GpioPin<Input<T>> { | 226 | pub fn pin(&self) -> &GpioPin<Input<T>> { |
| @@ -366,89 +335,87 @@ impl<C: ChannelID, T> OutputChannel<C, T> { | |||
| 366 | &g.tasks_set[index] | 335 | &g.tasks_set[index] |
| 367 | } | 336 | } |
| 368 | } | 337 | } |
| 338 | */ | ||
| 369 | 339 | ||
| 370 | struct BitIter(u32); | 340 | /// GPIO input driver with support |
| 371 | 341 | pub struct GpioteInput<T: GpioPin> { | |
| 372 | impl Iterator for BitIter { | 342 | pin: Input<T>, |
| 373 | type Item = u32; | 343 | } |
| 344 | impl<T: GpioPin> Unpin for GpioteInput<T> {} | ||
| 374 | 345 | ||
| 375 | fn next(&mut self) -> Option<Self::Item> { | 346 | impl<T: GpioPin> GpioteInput<T> { |
| 376 | match self.0.trailing_zeros() { | 347 | pub fn new(_init: Initialized, pin: Input<T>) -> Self { |
| 377 | 32 => None, | 348 | Self { pin } |
| 378 | b => { | ||
| 379 | self.0 &= !(1 << b); | ||
| 380 | Some(b) | ||
| 381 | } | ||
| 382 | } | ||
| 383 | } | 349 | } |
| 384 | } | 350 | } |
| 385 | 351 | ||
| 386 | pub struct GpiotePin<T> { | 352 | impl<T: GpioPin> InputPin for GpioteInput<T> { |
| 387 | pin: GpioPin<Input<T>>, | 353 | type Error = Infallible; |
| 388 | } | ||
| 389 | 354 | ||
| 390 | impl<T> Unpin for GpiotePin<T> {} | 355 | fn is_high(&self) -> Result<bool, Self::Error> { |
| 356 | self.pin.is_high() | ||
| 357 | } | ||
| 391 | 358 | ||
| 392 | impl<T> GpiotePin<T> { | 359 | fn is_low(&self) -> Result<bool, Self::Error> { |
| 393 | pub fn new(_gpiote: Gpiote, pin: GpioPin<Input<T>>) -> Self { | 360 | self.pin.is_low() |
| 394 | Self { pin } | ||
| 395 | } | 361 | } |
| 396 | } | 362 | } |
| 397 | 363 | ||
| 398 | impl<T: 'static> WaitForHigh for GpiotePin<T> { | 364 | impl<T: GpioPin> WaitForHigh for GpioteInput<T> { |
| 399 | type Future<'a> = PortInputFuture<'a, T>; | 365 | type Future<'a> = PortInputFuture<'a>; |
| 400 | 366 | ||
| 401 | fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { | 367 | fn wait_for_high<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { |
| 368 | self.pin.pin.conf().modify(|_, w| w.sense().high()); | ||
| 369 | |||
| 402 | PortInputFuture { | 370 | PortInputFuture { |
| 403 | pin: &self.get_mut().pin, | 371 | pin_port: self.pin.pin.pin_port(), |
| 404 | polarity: PortInputPolarity::High, | 372 | phantom: PhantomData, |
| 405 | } | 373 | } |
| 406 | } | 374 | } |
| 407 | } | 375 | } |
| 408 | 376 | ||
| 409 | impl<T: 'static> WaitForLow for GpiotePin<T> { | 377 | impl<T: GpioPin> WaitForLow for GpioteInput<T> { |
| 410 | type Future<'a> = PortInputFuture<'a, T>; | 378 | type Future<'a> = PortInputFuture<'a>; |
| 411 | 379 | ||
| 412 | fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { | 380 | fn wait_for_low<'a>(self: Pin<&'a mut Self>) -> Self::Future<'a> { |
| 381 | self.pin.pin.conf().modify(|_, w| w.sense().low()); | ||
| 382 | |||
| 413 | PortInputFuture { | 383 | PortInputFuture { |
| 414 | pin: &self.get_mut().pin, | 384 | pin_port: self.pin.pin.pin_port(), |
| 415 | polarity: PortInputPolarity::Low, | 385 | phantom: PhantomData, |
| 416 | } | 386 | } |
| 417 | } | 387 | } |
| 418 | } | 388 | } |
| 419 | 389 | ||
| 420 | impl<T> Deref for GpiotePin<T> { | 390 | pub struct PortInputFuture<'a> { |
| 421 | type Target = GpioPin<Input<T>>; | 391 | pin_port: u8, |
| 422 | fn deref(&self) -> &Self::Target { | 392 | phantom: PhantomData<&'a mut AnyPin>, |
| 423 | &self.pin | ||
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | enum PortInputPolarity { | ||
| 428 | High, | ||
| 429 | Low, | ||
| 430 | } | ||
| 431 | |||
| 432 | pub struct PortInputFuture<'a, T> { | ||
| 433 | pin: &'a GpioPin<Input<T>>, | ||
| 434 | polarity: PortInputPolarity, | ||
| 435 | } | 393 | } |
| 436 | 394 | ||
| 437 | impl<'a, T> Drop for PortInputFuture<'a, T> { | 395 | impl<'a> Drop for PortInputFuture<'a> { |
| 438 | fn drop(&mut self) { | 396 | fn drop(&mut self) { |
| 439 | pin_conf(&self.pin).modify(|_, w| w.sense().disabled()); | 397 | unsafe { AnyPin::steal(self.pin_port) } |
| 440 | PORT_SIGNALS[pin_num(&self.pin)].reset(); | 398 | .conf() |
| 399 | .modify(|_, w| w.sense().disabled()); | ||
| 441 | } | 400 | } |
| 442 | } | 401 | } |
| 443 | 402 | ||
| 444 | impl<'a, T> Future for PortInputFuture<'a, T> { | 403 | impl<'a> Future for PortInputFuture<'a> { |
| 445 | type Output = (); | 404 | type Output = (); |
| 446 | 405 | ||
| 447 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | 406 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 448 | pin_conf(&self.pin).modify(|_, w| match self.polarity { | 407 | let dis = unsafe { AnyPin::steal(self.pin_port) } |
| 449 | PortInputPolarity::Low => w.sense().low(), | 408 | .conf() |
| 450 | PortInputPolarity::High => w.sense().high(), | 409 | .read() |
| 451 | }); | 410 | .sense() |
| 452 | PORT_SIGNALS[pin_num(&self.pin)].poll_wait(cx) | 411 | .is_disabled(); |
| 412 | |||
| 413 | if dis { | ||
| 414 | return Poll::Ready(()); | ||
| 415 | } | ||
| 416 | |||
| 417 | PORT_WAKERS[self.pin_port as usize].register(cx.waker()); | ||
| 418 | |||
| 419 | Poll::Pending | ||
| 453 | } | 420 | } |
| 454 | } | 421 | } |
