aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/gpio.rs104
1 files changed, 103 insertions, 1 deletions
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index dd334c633..d48ad3d0e 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -1,6 +1,7 @@
1use core::convert::Infallible; 1use core::convert::Infallible;
2use core::hint::unreachable_unchecked; 2use core::hint::unreachable_unchecked;
3 3
4use embassy::util::PeripheralBorrow;
4use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; 5use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
5use gpio::pin_cnf::DRIVE_A; 6use gpio::pin_cnf::DRIVE_A;
6 7
@@ -205,6 +206,7 @@ pub(crate) mod sealed {
205 } 206 }
206 } 207 }
207 208
209 #[inline]
208 fn block(&self) -> &gpio::RegisterBlock { 210 fn block(&self) -> &gpio::RegisterBlock {
209 unsafe { 211 unsafe {
210 match self.pin_port() / 32 { 212 match self.pin_port() / 32 {
@@ -216,11 +218,13 @@ pub(crate) mod sealed {
216 } 218 }
217 } 219 }
218 220
221 #[inline]
219 fn conf(&self) -> &gpio::PIN_CNF { 222 fn conf(&self) -> &gpio::PIN_CNF {
220 &self.block().pin_cnf[self._pin() as usize] 223 &self.block().pin_cnf[self._pin() as usize]
221 } 224 }
222 225
223 /// Set the output as high. 226 /// Set the output as high.
227 #[inline]
224 fn set_high(&self) { 228 fn set_high(&self) {
225 unsafe { 229 unsafe {
226 self.block().outset.write(|w| w.bits(1u32 << self._pin())); 230 self.block().outset.write(|w| w.bits(1u32 << self._pin()));
@@ -228,12 +232,15 @@ pub(crate) mod sealed {
228 } 232 }
229 233
230 /// Set the output as low. 234 /// Set the output as low.
235 #[inline]
231 fn set_low(&self) { 236 fn set_low(&self) {
232 unsafe { 237 unsafe {
233 self.block().outclr.write(|w| w.bits(1u32 << self._pin())); 238 self.block().outclr.write(|w| w.bits(1u32 << self._pin()));
234 } 239 }
235 } 240 }
236 } 241 }
242
243 pub trait OptionalPin {}
237} 244}
238 245
239pub trait Pin: sealed::Pin + Sized { 246pub trait Pin: sealed::Pin + Sized {
@@ -247,7 +254,7 @@ pub trait Pin: sealed::Pin + Sized {
247 #[inline] 254 #[inline]
248 fn port(&self) -> Port { 255 fn port(&self) -> Port {
249 match self.pin_port() / 32 { 256 match self.pin_port() / 32 {
250 1 => Port::Port0, 257 0 => Port::Port0,
251 #[cfg(any(feature = "52833", feature = "52840"))] 258 #[cfg(any(feature = "52833", feature = "52840"))]
252 1 => Port::Port1, 259 1 => Port::Port1,
253 _ => unsafe { unreachable_unchecked() }, 260 _ => unsafe { unreachable_unchecked() },
@@ -260,6 +267,7 @@ pub trait Pin: sealed::Pin + Sized {
260 } 267 }
261 268
262 /// Convert from concrete pin type PX_XX to type erased `AnyPin`. 269 /// Convert from concrete pin type PX_XX to type erased `AnyPin`.
270 #[inline]
263 fn degrade(self) -> AnyPin { 271 fn degrade(self) -> AnyPin {
264 AnyPin { 272 AnyPin {
265 pin_port: self.pin_port(), 273 pin_port: self.pin_port(),
@@ -273,6 +281,7 @@ pub struct AnyPin {
273} 281}
274 282
275impl AnyPin { 283impl AnyPin {
284 #[inline]
276 pub unsafe fn steal(pin_port: u8) -> Self { 285 pub unsafe fn steal(pin_port: u8) -> Self {
277 Self { pin_port } 286 Self { pin_port }
278 } 287 }
@@ -280,15 +289,108 @@ impl AnyPin {
280 289
281impl Pin for AnyPin {} 290impl Pin for AnyPin {}
282impl sealed::Pin for AnyPin { 291impl sealed::Pin for AnyPin {
292 #[inline]
283 fn pin_port(&self) -> u8 { 293 fn pin_port(&self) -> u8 {
284 self.pin_port 294 self.pin_port
285 } 295 }
286} 296}
287 297
298impl PeripheralBorrow for AnyPin {
299 type Target = AnyPin;
300 #[inline]
301 unsafe fn unborrow(self) -> Self::Target {
302 self
303 }
304}
305
306impl<'a> PeripheralBorrow for &'a mut AnyPin {
307 type Target = AnyPin;
308 #[inline]
309 unsafe fn unborrow(self) -> Self::Target {
310 AnyPin {
311 pin_port: self.pin_port,
312 }
313 }
314}
315
316// ====================
317
318pub trait OptionalPin: sealed::OptionalPin + Sized {
319 type Pin: Pin;
320 fn pin(&self) -> Option<&Self::Pin>;
321 fn pin_mut(&mut self) -> Option<&mut Self::Pin>;
322
323 #[inline]
324 fn psel_bits(&self) -> u32 {
325 self.pin().map_or(1u32 << 31, |pin| Pin::psel_bits(pin))
326 }
327
328 /// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`.
329 #[inline]
330 fn degrade_optional(mut self) -> Option<AnyPin> {
331 self.pin_mut()
332 .map(|pin| unsafe { core::ptr::read(pin) }.degrade())
333 }
334}
335
336impl<T: Pin> sealed::OptionalPin for T {}
337impl<T: Pin> OptionalPin for T {
338 type Pin = T;
339
340 #[inline]
341 fn pin(&self) -> Option<&T> {
342 Some(self)
343 }
344
345 #[inline]
346 fn pin_mut(&mut self) -> Option<&mut T> {
347 Some(self)
348 }
349}
350
351// Uninhabited enum, so it's actually impossible to create a DummyPin value.
352#[doc(hidden)]
353pub enum DummyPin {}
354impl Pin for DummyPin {}
355impl sealed::Pin for DummyPin {
356 #[inline]
357 fn pin_port(&self) -> u8 {
358 unreachable!()
359 }
360}
361
362#[derive(Clone, Copy, Debug)]
363pub struct NoPin;
364impl sealed::OptionalPin for NoPin {}
365impl OptionalPin for NoPin {
366 type Pin = DummyPin;
367
368 #[inline]
369 fn pin(&self) -> Option<&DummyPin> {
370 None
371 }
372
373 #[inline]
374 fn pin_mut(&mut self) -> Option<&mut DummyPin> {
375 None
376 }
377}
378
379impl PeripheralBorrow for NoPin {
380 type Target = NoPin;
381 #[inline]
382 unsafe fn unborrow(self) -> Self::Target {
383 self
384 }
385}
386
387// ====================
388
288macro_rules! make_impl { 389macro_rules! make_impl {
289 ($type:ident, $port_num:expr, $pin_num:expr) => { 390 ($type:ident, $port_num:expr, $pin_num:expr) => {
290 impl Pin for peripherals::$type {} 391 impl Pin for peripherals::$type {}
291 impl sealed::Pin for peripherals::$type { 392 impl sealed::Pin for peripherals::$type {
393 #[inline]
292 fn pin_port(&self) -> u8 { 394 fn pin_port(&self) -> u8 {
293 $port_num * 32 + $pin_num 395 $port_num * 32 + $pin_num
294 } 396 }