diff options
Diffstat (limited to 'embassy-nrf/src')
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 24 | ||||
| -rw-r--r-- | embassy-nrf/src/gpio.rs | 54 | ||||
| -rw-r--r-- | embassy-nrf/src/pwm.rs | 202 | ||||
| -rw-r--r-- | embassy-nrf/src/spim.rs | 61 | ||||
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 120 |
5 files changed, 317 insertions, 144 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 2880c84f6..b49c12788 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -27,8 +27,7 @@ use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStor | |||
| 27 | use embassy_hal_common::ring_buffer::RingBuffer; | 27 | use embassy_hal_common::ring_buffer::RingBuffer; |
| 28 | use embassy_hal_common::{low_power_wait_until, unborrow}; | 28 | use embassy_hal_common::{low_power_wait_until, unborrow}; |
| 29 | 29 | ||
| 30 | use crate::gpio::sealed::Pin as _; | 30 | use crate::gpio::Pin as GpioPin; |
| 31 | use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; | ||
| 32 | use crate::pac; | 31 | use crate::pac; |
| 33 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 32 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 34 | use crate::timer::Instance as TimerInstance; | 33 | use crate::timer::Instance as TimerInstance; |
| @@ -89,8 +88,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 89 | irq: impl Unborrow<Target = U::Interrupt> + 'd, | 88 | irq: impl Unborrow<Target = U::Interrupt> + 'd, |
| 90 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, | 89 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, |
| 91 | txd: impl Unborrow<Target = impl GpioPin> + 'd, | 90 | txd: impl Unborrow<Target = impl GpioPin> + 'd, |
| 92 | cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 91 | cts: impl Unborrow<Target = impl GpioPin> + 'd, |
| 93 | rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 92 | rts: impl Unborrow<Target = impl GpioPin> + 'd, |
| 94 | config: Config, | 93 | config: Config, |
| 95 | rx_buffer: &'d mut [u8], | 94 | rx_buffer: &'d mut [u8], |
| 96 | tx_buffer: &'d mut [u8], | 95 | tx_buffer: &'d mut [u8], |
| @@ -108,28 +107,19 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 108 | txd.conf().write(|w| w.dir().output().drive().h0h1()); | 107 | txd.conf().write(|w| w.dir().output().drive().h0h1()); |
| 109 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | 108 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); |
| 110 | 109 | ||
| 111 | if let Some(pin) = rts.pin_mut() { | 110 | cts.conf().write(|w| w.input().connect().drive().h0h1()); |
| 112 | pin.set_high(); | ||
| 113 | pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||
| 114 | } | ||
| 115 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | 111 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); |
| 116 | 112 | ||
| 117 | if let Some(pin) = cts.pin_mut() { | 113 | rts.set_high(); |
| 118 | pin.conf().write(|w| w.input().connect().drive().h0h1()); | 114 | rts.conf().write(|w| w.dir().output().drive().h0h1()); |
| 119 | } | ||
| 120 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | 115 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); |
| 121 | 116 | ||
| 122 | r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); | 117 | r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); |
| 123 | r.config.write(|w| w.parity().variant(config.parity)); | 118 | r.config.write(|w| w.parity().variant(config.parity)); |
| 124 | 119 | ||
| 125 | // Configure | 120 | // Configure |
| 126 | let hardware_flow_control = match (rts.pin().is_some(), cts.pin().is_some()) { | ||
| 127 | (false, false) => false, | ||
| 128 | (true, true) => true, | ||
| 129 | _ => panic!("RTS and CTS pins must be either both set or none set."), | ||
| 130 | }; | ||
| 131 | r.config.write(|w| { | 121 | r.config.write(|w| { |
| 132 | w.hwfc().bit(hardware_flow_control); | 122 | w.hwfc().bit(true); |
| 133 | w.parity().variant(config.parity); | 123 | w.parity().variant(config.parity); |
| 134 | w | 124 | w |
| 135 | }); | 125 | }); |
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 3f204d564..09202e2f1 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs | |||
| @@ -287,8 +287,6 @@ pub(crate) mod sealed { | |||
| 287 | unsafe { self.block().outclr.write(|w| w.bits(1u32 << self._pin())) } | 287 | unsafe { self.block().outclr.write(|w| w.bits(1u32 << self._pin())) } |
| 288 | } | 288 | } |
| 289 | } | 289 | } |
| 290 | |||
| 291 | pub trait OptionalPin {} | ||
| 292 | } | 290 | } |
| 293 | 291 | ||
| 294 | pub trait Pin: Unborrow<Target = Self> + sealed::Pin + Sized + 'static { | 292 | pub trait Pin: Unborrow<Target = Self> + sealed::Pin + Sized + 'static { |
| @@ -346,59 +344,17 @@ impl sealed::Pin for AnyPin { | |||
| 346 | 344 | ||
| 347 | // ==================== | 345 | // ==================== |
| 348 | 346 | ||
| 349 | pub trait OptionalPin: Unborrow<Target = Self> + sealed::OptionalPin + Sized { | 347 | pub(crate) trait PselBits { |
| 350 | type Pin: Pin; | 348 | fn psel_bits(&self) -> u32; |
| 351 | fn pin(&self) -> Option<&Self::Pin>; | ||
| 352 | fn pin_mut(&mut self) -> Option<&mut Self::Pin>; | ||
| 353 | |||
| 354 | #[inline] | ||
| 355 | fn psel_bits(&self) -> u32 { | ||
| 356 | self.pin().map_or(1u32 << 31, Pin::psel_bits) | ||
| 357 | } | ||
| 358 | |||
| 359 | /// Convert from concrete pin type PX_XX to type erased `Option<AnyPin>`. | ||
| 360 | #[inline] | ||
| 361 | fn degrade_optional(mut self) -> Option<AnyPin> { | ||
| 362 | self.pin_mut() | ||
| 363 | .map(|pin| unsafe { core::ptr::read(pin) }.degrade()) | ||
| 364 | } | ||
| 365 | } | 349 | } |
| 366 | 350 | ||
| 367 | impl<T: Pin> sealed::OptionalPin for T {} | 351 | impl PselBits for Option<AnyPin> { |
| 368 | impl<T: Pin> OptionalPin for T { | ||
| 369 | type Pin = T; | ||
| 370 | |||
| 371 | #[inline] | ||
| 372 | fn pin(&self) -> Option<&T> { | ||
| 373 | Some(self) | ||
| 374 | } | ||
| 375 | |||
| 376 | #[inline] | 352 | #[inline] |
| 377 | fn pin_mut(&mut self) -> Option<&mut T> { | 353 | fn psel_bits(&self) -> u32 { |
| 378 | Some(self) | 354 | self.as_ref().map_or(1u32 << 31, Pin::psel_bits) |
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | #[derive(Clone, Copy, Debug)] | ||
| 383 | pub struct NoPin; | ||
| 384 | unsafe_impl_unborrow!(NoPin); | ||
| 385 | impl sealed::OptionalPin for NoPin {} | ||
| 386 | impl OptionalPin for NoPin { | ||
| 387 | type Pin = AnyPin; | ||
| 388 | |||
| 389 | #[inline] | ||
| 390 | fn pin(&self) -> Option<&AnyPin> { | ||
| 391 | None | ||
| 392 | } | ||
| 393 | |||
| 394 | #[inline] | ||
| 395 | fn pin_mut(&mut self) -> Option<&mut AnyPin> { | ||
| 396 | None | ||
| 397 | } | 355 | } |
| 398 | } | 356 | } |
| 399 | 357 | ||
| 400 | // ==================== | ||
| 401 | |||
| 402 | pub(crate) fn deconfigure_pin(psel_bits: u32) { | 358 | pub(crate) fn deconfigure_pin(psel_bits: u32) { |
| 403 | if psel_bits & 0x8000_0000 != 0 { | 359 | if psel_bits & 0x8000_0000 != 0 { |
| 404 | return; | 360 | return; |
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 01b1f48d9..5ac52f172 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs | |||
| @@ -6,7 +6,7 @@ use embassy::util::Unborrow; | |||
| 6 | use embassy_hal_common::unborrow; | 6 | use embassy_hal_common::unborrow; |
| 7 | 7 | ||
| 8 | use crate::gpio::sealed::Pin as _; | 8 | use crate::gpio::sealed::Pin as _; |
| 9 | use crate::gpio::{AnyPin, OptionalPin as GpioOptionalPin}; | 9 | use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; |
| 10 | use crate::interrupt::Interrupt; | 10 | use crate::interrupt::Interrupt; |
| 11 | use crate::pac; | 11 | use crate::pac; |
| 12 | use crate::ppi::{Event, Task}; | 12 | use crate::ppi::{Event, Task}; |
| @@ -48,47 +48,104 @@ pub enum Error { | |||
| 48 | const MAX_SEQUENCE_LEN: usize = 32767; | 48 | const MAX_SEQUENCE_LEN: usize = 32767; |
| 49 | 49 | ||
| 50 | impl<'d, T: Instance> SequencePwm<'d, T> { | 50 | impl<'d, T: Instance> SequencePwm<'d, T> { |
| 51 | /// Creates the interface to a `SequencePwm`. | 51 | /// Create a new 1-channel PWM |
| 52 | /// | ||
| 53 | /// Must be started by calling `start` | ||
| 54 | /// | ||
| 55 | /// # Safety | ||
| 56 | /// | ||
| 57 | /// The returned API is safe unless you use `mem::forget` (or similar safe | ||
| 58 | /// mechanisms) on stack allocated buffers which which have been passed to | ||
| 59 | /// [`new()`](SequencePwm::new). | ||
| 60 | #[allow(unused_unsafe)] | 52 | #[allow(unused_unsafe)] |
| 61 | pub fn new( | 53 | pub fn new_1ch( |
| 62 | _pwm: impl Unborrow<Target = T> + 'd, | 54 | pwm: impl Unborrow<Target = T> + 'd, |
| 63 | ch0: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 55 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, |
| 64 | ch1: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 56 | config: Config, |
| 65 | ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 57 | ) -> Result<Self, Error> { |
| 66 | ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 58 | unborrow!(ch0); |
| 59 | Self::new_inner(pwm, Some(ch0.degrade()), None, None, None, config) | ||
| 60 | } | ||
| 61 | |||
| 62 | /// Create a new 2-channel PWM | ||
| 63 | #[allow(unused_unsafe)] | ||
| 64 | pub fn new_2ch( | ||
| 65 | pwm: impl Unborrow<Target = T> + 'd, | ||
| 66 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 67 | ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 68 | config: Config, | ||
| 69 | ) -> Result<Self, Error> { | ||
| 70 | unborrow!(ch0, ch1); | ||
| 71 | Self::new_inner( | ||
| 72 | pwm, | ||
| 73 | Some(ch0.degrade()), | ||
| 74 | Some(ch1.degrade()), | ||
| 75 | None, | ||
| 76 | None, | ||
| 77 | config, | ||
| 78 | ) | ||
| 79 | } | ||
| 80 | |||
| 81 | /// Create a new 3-channel PWM | ||
| 82 | #[allow(unused_unsafe)] | ||
| 83 | pub fn new_3ch( | ||
| 84 | pwm: impl Unborrow<Target = T> + 'd, | ||
| 85 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 86 | ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 87 | ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 88 | config: Config, | ||
| 89 | ) -> Result<Self, Error> { | ||
| 90 | unborrow!(ch0, ch1, ch2); | ||
| 91 | Self::new_inner( | ||
| 92 | pwm, | ||
| 93 | Some(ch0.degrade()), | ||
| 94 | Some(ch1.degrade()), | ||
| 95 | Some(ch2.degrade()), | ||
| 96 | None, | ||
| 97 | config, | ||
| 98 | ) | ||
| 99 | } | ||
| 100 | |||
| 101 | /// Create a new 4-channel PWM | ||
| 102 | #[allow(unused_unsafe)] | ||
| 103 | pub fn new_4ch( | ||
| 104 | pwm: impl Unborrow<Target = T> + 'd, | ||
| 105 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 106 | ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 107 | ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 108 | ch3: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 67 | config: Config, | 109 | config: Config, |
| 68 | ) -> Result<Self, Error> { | 110 | ) -> Result<Self, Error> { |
| 69 | unborrow!(ch0, ch1, ch2, ch3); | 111 | unborrow!(ch0, ch1, ch2, ch3); |
| 112 | Self::new_inner( | ||
| 113 | pwm, | ||
| 114 | Some(ch0.degrade()), | ||
| 115 | Some(ch1.degrade()), | ||
| 116 | Some(ch2.degrade()), | ||
| 117 | Some(ch3.degrade()), | ||
| 118 | config, | ||
| 119 | ) | ||
| 120 | } | ||
| 70 | 121 | ||
| 122 | fn new_inner( | ||
| 123 | _pwm: impl Unborrow<Target = T> + 'd, | ||
| 124 | ch0: Option<AnyPin>, | ||
| 125 | ch1: Option<AnyPin>, | ||
| 126 | ch2: Option<AnyPin>, | ||
| 127 | ch3: Option<AnyPin>, | ||
| 128 | config: Config, | ||
| 129 | ) -> Result<Self, Error> { | ||
| 71 | let r = T::regs(); | 130 | let r = T::regs(); |
| 72 | 131 | ||
| 73 | if let Some(pin) = ch0.pin_mut() { | 132 | if let Some(pin) = &ch0 { |
| 74 | pin.set_low(); | 133 | pin.set_low(); |
| 75 | pin.conf().write(|w| w.dir().output()); | 134 | pin.conf().write(|w| w.dir().output()); |
| 76 | } | 135 | } |
| 77 | if let Some(pin) = ch1.pin_mut() { | 136 | if let Some(pin) = &ch1 { |
| 78 | pin.set_low(); | 137 | pin.set_low(); |
| 79 | pin.conf().write(|w| w.dir().output()); | 138 | pin.conf().write(|w| w.dir().output()); |
| 80 | } | 139 | } |
| 81 | if let Some(pin) = ch2.pin_mut() { | 140 | if let Some(pin) = &ch2 { |
| 82 | pin.set_low(); | 141 | pin.set_low(); |
| 83 | pin.conf().write(|w| w.dir().output()); | 142 | pin.conf().write(|w| w.dir().output()); |
| 84 | } | 143 | } |
| 85 | if let Some(pin) = ch3.pin_mut() { | 144 | if let Some(pin) = &ch3 { |
| 86 | pin.set_low(); | 145 | pin.set_low(); |
| 87 | pin.conf().write(|w| w.dir().output()); | 146 | pin.conf().write(|w| w.dir().output()); |
| 88 | } | 147 | } |
| 89 | 148 | ||
| 90 | // if NoPin provided writes disconnected (top bit 1) 0x80000000 else | ||
| 91 | // writes pin number ex 13 (0x0D) which is connected (top bit 0) | ||
| 92 | r.psel.out[0].write(|w| unsafe { w.bits(ch0.psel_bits()) }); | 149 | r.psel.out[0].write(|w| unsafe { w.bits(ch0.psel_bits()) }); |
| 93 | r.psel.out[1].write(|w| unsafe { w.bits(ch1.psel_bits()) }); | 150 | r.psel.out[1].write(|w| unsafe { w.bits(ch1.psel_bits()) }); |
| 94 | r.psel.out[2].write(|w| unsafe { w.bits(ch2.psel_bits()) }); | 151 | r.psel.out[2].write(|w| unsafe { w.bits(ch2.psel_bits()) }); |
| @@ -121,10 +178,10 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | |||
| 121 | 178 | ||
| 122 | Ok(Self { | 179 | Ok(Self { |
| 123 | phantom: PhantomData, | 180 | phantom: PhantomData, |
| 124 | ch0: ch0.degrade_optional(), | 181 | ch0, |
| 125 | ch1: ch1.degrade_optional(), | 182 | ch1, |
| 126 | ch2: ch2.degrade_optional(), | 183 | ch2, |
| 127 | ch3: ch3.degrade_optional(), | 184 | ch3, |
| 128 | }) | 185 | }) |
| 129 | } | 186 | } |
| 130 | 187 | ||
| @@ -545,41 +602,86 @@ pub enum CounterMode { | |||
| 545 | } | 602 | } |
| 546 | 603 | ||
| 547 | impl<'d, T: Instance> SimplePwm<'d, T> { | 604 | impl<'d, T: Instance> SimplePwm<'d, T> { |
| 548 | /// Creates the interface to a `SimplePwm` | 605 | /// Create a new 1-channel PWM |
| 549 | /// | ||
| 550 | /// Enables the peripheral, defaults the freq to 1Mhz, max_duty 1000, duty | ||
| 551 | /// 0, up mode, and pins low. Must be started by calling `set_duty` | ||
| 552 | /// | ||
| 553 | /// # Safety | ||
| 554 | /// | ||
| 555 | /// The returned API is safe unless you use `mem::forget` (or similar safe | ||
| 556 | /// mechanisms) on stack allocated buffers which which have been passed to | ||
| 557 | /// [`new()`](SimplePwm::new). | ||
| 558 | #[allow(unused_unsafe)] | 606 | #[allow(unused_unsafe)] |
| 559 | pub fn new( | 607 | pub fn new_1ch( |
| 560 | _pwm: impl Unborrow<Target = T> + 'd, | 608 | pwm: impl Unborrow<Target = T> + 'd, |
| 561 | ch0: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 609 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, |
| 562 | ch1: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 610 | ) -> Self { |
| 563 | ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 611 | unborrow!(ch0); |
| 564 | ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 612 | Self::new_inner(pwm, Some(ch0.degrade()), None, None, None) |
| 613 | } | ||
| 614 | |||
| 615 | /// Create a new 2-channel PWM | ||
| 616 | #[allow(unused_unsafe)] | ||
| 617 | pub fn new_2ch( | ||
| 618 | pwm: impl Unborrow<Target = T> + 'd, | ||
| 619 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 620 | ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 621 | ) -> Self { | ||
| 622 | unborrow!(ch0, ch1); | ||
| 623 | Self::new_inner(pwm, Some(ch0.degrade()), Some(ch1.degrade()), None, None) | ||
| 624 | } | ||
| 625 | |||
| 626 | /// Create a new 3-channel PWM | ||
| 627 | #[allow(unused_unsafe)] | ||
| 628 | pub fn new_3ch( | ||
| 629 | pwm: impl Unborrow<Target = T> + 'd, | ||
| 630 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 631 | ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 632 | ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 633 | ) -> Self { | ||
| 634 | unborrow!(ch0, ch1, ch2); | ||
| 635 | Self::new_inner( | ||
| 636 | pwm, | ||
| 637 | Some(ch0.degrade()), | ||
| 638 | Some(ch1.degrade()), | ||
| 639 | Some(ch2.degrade()), | ||
| 640 | None, | ||
| 641 | ) | ||
| 642 | } | ||
| 643 | |||
| 644 | /// Create a new 4-channel PWM | ||
| 645 | #[allow(unused_unsafe)] | ||
| 646 | pub fn new_4ch( | ||
| 647 | pwm: impl Unborrow<Target = T> + 'd, | ||
| 648 | ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 649 | ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 650 | ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 651 | ch3: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 565 | ) -> Self { | 652 | ) -> Self { |
| 566 | unborrow!(ch0, ch1, ch2, ch3); | 653 | unborrow!(ch0, ch1, ch2, ch3); |
| 654 | Self::new_inner( | ||
| 655 | pwm, | ||
| 656 | Some(ch0.degrade()), | ||
| 657 | Some(ch1.degrade()), | ||
| 658 | Some(ch2.degrade()), | ||
| 659 | Some(ch3.degrade()), | ||
| 660 | ) | ||
| 661 | } | ||
| 567 | 662 | ||
| 663 | fn new_inner( | ||
| 664 | _pwm: impl Unborrow<Target = T> + 'd, | ||
| 665 | ch0: Option<AnyPin>, | ||
| 666 | ch1: Option<AnyPin>, | ||
| 667 | ch2: Option<AnyPin>, | ||
| 668 | ch3: Option<AnyPin>, | ||
| 669 | ) -> Self { | ||
| 568 | let r = T::regs(); | 670 | let r = T::regs(); |
| 569 | 671 | ||
| 570 | if let Some(pin) = ch0.pin_mut() { | 672 | if let Some(pin) = &ch0 { |
| 571 | pin.set_low(); | 673 | pin.set_low(); |
| 572 | pin.conf().write(|w| w.dir().output()); | 674 | pin.conf().write(|w| w.dir().output()); |
| 573 | } | 675 | } |
| 574 | if let Some(pin) = ch1.pin_mut() { | 676 | if let Some(pin) = &ch1 { |
| 575 | pin.set_low(); | 677 | pin.set_low(); |
| 576 | pin.conf().write(|w| w.dir().output()); | 678 | pin.conf().write(|w| w.dir().output()); |
| 577 | } | 679 | } |
| 578 | if let Some(pin) = ch2.pin_mut() { | 680 | if let Some(pin) = &ch2 { |
| 579 | pin.set_low(); | 681 | pin.set_low(); |
| 580 | pin.conf().write(|w| w.dir().output()); | 682 | pin.conf().write(|w| w.dir().output()); |
| 581 | } | 683 | } |
| 582 | if let Some(pin) = ch3.pin_mut() { | 684 | if let Some(pin) = &ch3 { |
| 583 | pin.set_low(); | 685 | pin.set_low(); |
| 584 | pin.conf().write(|w| w.dir().output()); | 686 | pin.conf().write(|w| w.dir().output()); |
| 585 | } | 687 | } |
| @@ -593,10 +695,10 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | |||
| 593 | 695 | ||
| 594 | let pwm = Self { | 696 | let pwm = Self { |
| 595 | phantom: PhantomData, | 697 | phantom: PhantomData, |
| 596 | ch0: ch0.degrade_optional(), | 698 | ch0, |
| 597 | ch1: ch1.degrade_optional(), | 699 | ch1, |
| 598 | ch2: ch2.degrade_optional(), | 700 | ch2, |
| 599 | ch3: ch3.degrade_optional(), | 701 | ch3, |
| 600 | duty: [0; 4], | 702 | duty: [0; 4], |
| 601 | }; | 703 | }; |
| 602 | 704 | ||
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index cd43b26e6..976a546ce 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -8,9 +8,9 @@ use embassy::util::Unborrow; | |||
| 8 | use embassy_hal_common::unborrow; | 8 | use embassy_hal_common::unborrow; |
| 9 | use futures::future::poll_fn; | 9 | use futures::future::poll_fn; |
| 10 | 10 | ||
| 11 | use crate::gpio; | ||
| 12 | use crate::gpio::sealed::Pin as _; | 11 | use crate::gpio::sealed::Pin as _; |
| 13 | use crate::gpio::{OptionalPin, Pin as GpioPin}; | 12 | use crate::gpio::{self, AnyPin}; |
| 13 | use crate::gpio::{Pin as GpioPin, PselBits}; | ||
| 14 | use crate::interrupt::Interrupt; | 14 | use crate::interrupt::Interrupt; |
| 15 | use crate::util::{slice_ptr_parts, slice_ptr_parts_mut}; | 15 | use crate::util::{slice_ptr_parts, slice_ptr_parts_mut}; |
| 16 | use crate::{pac, util::slice_in_ram_or}; | 16 | use crate::{pac, util::slice_in_ram_or}; |
| @@ -51,36 +51,77 @@ impl Default for Config { | |||
| 51 | 51 | ||
| 52 | impl<'d, T: Instance> Spim<'d, T> { | 52 | impl<'d, T: Instance> Spim<'d, T> { |
| 53 | pub fn new( | 53 | pub fn new( |
| 54 | _spim: impl Unborrow<Target = T> + 'd, | 54 | spim: impl Unborrow<Target = T> + 'd, |
| 55 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 56 | sck: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 57 | miso: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 58 | mosi: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 59 | config: Config, | ||
| 60 | ) -> Self { | ||
| 61 | unborrow!(sck, miso, mosi); | ||
| 62 | Self::new_inner( | ||
| 63 | spim, | ||
| 64 | irq, | ||
| 65 | sck.degrade(), | ||
| 66 | Some(miso.degrade()), | ||
| 67 | Some(mosi.degrade()), | ||
| 68 | config, | ||
| 69 | ) | ||
| 70 | } | ||
| 71 | |||
| 72 | pub fn new_txonly( | ||
| 73 | spim: impl Unborrow<Target = T> + 'd, | ||
| 55 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | 74 | irq: impl Unborrow<Target = T::Interrupt> + 'd, |
| 56 | sck: impl Unborrow<Target = impl GpioPin> + 'd, | 75 | sck: impl Unborrow<Target = impl GpioPin> + 'd, |
| 57 | miso: impl Unborrow<Target = impl OptionalPin> + 'd, | 76 | mosi: impl Unborrow<Target = impl GpioPin> + 'd, |
| 58 | mosi: impl Unborrow<Target = impl OptionalPin> + 'd, | 77 | config: Config, |
| 78 | ) -> Self { | ||
| 79 | unborrow!(sck, mosi); | ||
| 80 | Self::new_inner(spim, irq, sck.degrade(), None, Some(mosi.degrade()), config) | ||
| 81 | } | ||
| 82 | |||
| 83 | pub fn new_rxonly( | ||
| 84 | spim: impl Unborrow<Target = T> + 'd, | ||
| 85 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 86 | sck: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 87 | miso: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 88 | config: Config, | ||
| 89 | ) -> Self { | ||
| 90 | unborrow!(sck, miso); | ||
| 91 | Self::new_inner(spim, irq, sck.degrade(), Some(miso.degrade()), None, config) | ||
| 92 | } | ||
| 93 | |||
| 94 | fn new_inner( | ||
| 95 | _spim: impl Unborrow<Target = T> + 'd, | ||
| 96 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 97 | sck: AnyPin, | ||
| 98 | miso: Option<AnyPin>, | ||
| 99 | mosi: Option<AnyPin>, | ||
| 59 | config: Config, | 100 | config: Config, |
| 60 | ) -> Self { | 101 | ) -> Self { |
| 61 | unborrow!(irq, sck, miso, mosi); | 102 | unborrow!(irq); |
| 62 | 103 | ||
| 63 | let r = T::regs(); | 104 | let r = T::regs(); |
| 64 | 105 | ||
| 65 | // Configure pins | 106 | // Configure pins |
| 66 | sck.conf().write(|w| w.dir().output().drive().h0h1()); | 107 | sck.conf().write(|w| w.dir().output().drive().h0h1()); |
| 67 | if let Some(mosi) = mosi.pin_mut() { | 108 | if let Some(mosi) = &mosi { |
| 68 | mosi.conf().write(|w| w.dir().output().drive().h0h1()); | 109 | mosi.conf().write(|w| w.dir().output().drive().h0h1()); |
| 69 | } | 110 | } |
| 70 | if let Some(miso) = miso.pin_mut() { | 111 | if let Some(miso) = &miso { |
| 71 | miso.conf().write(|w| w.input().connect().drive().h0h1()); | 112 | miso.conf().write(|w| w.input().connect().drive().h0h1()); |
| 72 | } | 113 | } |
| 73 | 114 | ||
| 74 | match config.mode.polarity { | 115 | match config.mode.polarity { |
| 75 | Polarity::IdleHigh => { | 116 | Polarity::IdleHigh => { |
| 76 | sck.set_high(); | 117 | sck.set_high(); |
| 77 | if let Some(mosi) = mosi.pin_mut() { | 118 | if let Some(mosi) = &mosi { |
| 78 | mosi.set_high(); | 119 | mosi.set_high(); |
| 79 | } | 120 | } |
| 80 | } | 121 | } |
| 81 | Polarity::IdleLow => { | 122 | Polarity::IdleLow => { |
| 82 | sck.set_low(); | 123 | sck.set_low(); |
| 83 | if let Some(mosi) = mosi.pin_mut() { | 124 | if let Some(mosi) = &mosi { |
| 84 | mosi.set_low(); | 125 | mosi.set_low(); |
| 85 | } | 126 | } |
| 86 | } | 127 | } |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index b10e55a05..a1c47cff5 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -24,7 +24,7 @@ use futures::future::poll_fn; | |||
| 24 | 24 | ||
| 25 | use crate::chip::EASY_DMA_SIZE; | 25 | use crate::chip::EASY_DMA_SIZE; |
| 26 | use crate::gpio::sealed::Pin as _; | 26 | use crate::gpio::sealed::Pin as _; |
| 27 | use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin}; | 27 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; |
| 28 | use crate::interrupt::Interrupt; | 28 | use crate::interrupt::Interrupt; |
| 29 | use crate::pac; | 29 | use crate::pac; |
| 30 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 30 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| @@ -80,18 +80,50 @@ pub struct UarteRx<'d, T: Instance> { | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | impl<'d, T: Instance> Uarte<'d, T> { | 82 | impl<'d, T: Instance> Uarte<'d, T> { |
| 83 | /// Creates the interface to a UARTE instance. | 83 | /// Create a new UARTE without hardware flow control |
| 84 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | ||
| 85 | pub fn new( | 84 | pub fn new( |
| 86 | _uarte: impl Unborrow<Target = T> + 'd, | 85 | uarte: impl Unborrow<Target = T> + 'd, |
| 87 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | 86 | irq: impl Unborrow<Target = T::Interrupt> + 'd, |
| 88 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, | 87 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, |
| 89 | txd: impl Unborrow<Target = impl GpioPin> + 'd, | 88 | txd: impl Unborrow<Target = impl GpioPin> + 'd, |
| 90 | cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||
| 91 | rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||
| 92 | config: Config, | 89 | config: Config, |
| 93 | ) -> Self { | 90 | ) -> Self { |
| 94 | unborrow!(irq, rxd, txd, cts, rts); | 91 | unborrow!(rxd, txd); |
| 92 | Self::new_inner(uarte, irq, rxd.degrade(), txd.degrade(), None, None, config) | ||
| 93 | } | ||
| 94 | |||
| 95 | /// Create a new UARTE with hardware flow control (RTS/CTS) | ||
| 96 | pub fn new_with_rtscts( | ||
| 97 | uarte: impl Unborrow<Target = T> + 'd, | ||
| 98 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 99 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 100 | txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 101 | cts: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 102 | rts: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 103 | config: Config, | ||
| 104 | ) -> Self { | ||
| 105 | unborrow!(rxd, txd, cts, rts); | ||
| 106 | Self::new_inner( | ||
| 107 | uarte, | ||
| 108 | irq, | ||
| 109 | rxd.degrade(), | ||
| 110 | txd.degrade(), | ||
| 111 | Some(cts.degrade()), | ||
| 112 | Some(rts.degrade()), | ||
| 113 | config, | ||
| 114 | ) | ||
| 115 | } | ||
| 116 | |||
| 117 | fn new_inner( | ||
| 118 | _uarte: impl Unborrow<Target = T> + 'd, | ||
| 119 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 120 | rxd: AnyPin, | ||
| 121 | txd: AnyPin, | ||
| 122 | cts: Option<AnyPin>, | ||
| 123 | rts: Option<AnyPin>, | ||
| 124 | config: Config, | ||
| 125 | ) -> Self { | ||
| 126 | unborrow!(irq); | ||
| 95 | 127 | ||
| 96 | let r = T::regs(); | 128 | let r = T::regs(); |
| 97 | 129 | ||
| @@ -102,19 +134,19 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 102 | txd.conf().write(|w| w.dir().output().drive().h0h1()); | 134 | txd.conf().write(|w| w.dir().output().drive().h0h1()); |
| 103 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | 135 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); |
| 104 | 136 | ||
| 105 | if let Some(pin) = rts.pin_mut() { | 137 | if let Some(pin) = &cts { |
| 106 | pin.set_high(); | 138 | pin.conf().write(|w| w.input().connect().drive().h0h1()); |
| 107 | pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||
| 108 | } | 139 | } |
| 109 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | 140 | r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); |
| 110 | 141 | ||
| 111 | if let Some(pin) = cts.pin_mut() { | 142 | if let Some(pin) = &rts { |
| 112 | pin.conf().write(|w| w.input().connect().drive().h0h1()); | 143 | pin.set_high(); |
| 144 | pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||
| 113 | } | 145 | } |
| 114 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | 146 | r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); |
| 115 | 147 | ||
| 116 | // Configure | 148 | // Configure |
| 117 | let hardware_flow_control = match (rts.pin().is_some(), cts.pin().is_some()) { | 149 | let hardware_flow_control = match (rts.is_some(), cts.is_some()) { |
| 118 | (false, false) => false, | 150 | (false, false) => false, |
| 119 | (true, true) => true, | 151 | (true, true) => true, |
| 120 | _ => panic!("RTS and CTS pins must be either both set or none set."), | 152 | _ => panic!("RTS and CTS pins must be either both set or none set."), |
| @@ -491,8 +523,7 @@ pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { | |||
| 491 | } | 523 | } |
| 492 | 524 | ||
| 493 | impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | 525 | impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { |
| 494 | /// Creates the interface to a UARTE instance. | 526 | /// Create a new UARTE without hardware flow control |
| 495 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | ||
| 496 | pub fn new( | 527 | pub fn new( |
| 497 | uarte: impl Unborrow<Target = U> + 'd, | 528 | uarte: impl Unborrow<Target = U> + 'd, |
| 498 | timer: impl Unborrow<Target = T> + 'd, | 529 | timer: impl Unborrow<Target = T> + 'd, |
| @@ -501,12 +532,65 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | |||
| 501 | irq: impl Unborrow<Target = U::Interrupt> + 'd, | 532 | irq: impl Unborrow<Target = U::Interrupt> + 'd, |
| 502 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, | 533 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, |
| 503 | txd: impl Unborrow<Target = impl GpioPin> + 'd, | 534 | txd: impl Unborrow<Target = impl GpioPin> + 'd, |
| 504 | cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 535 | config: Config, |
| 505 | rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | 536 | ) -> Self { |
| 537 | unborrow!(rxd, txd); | ||
| 538 | Self::new_inner( | ||
| 539 | uarte, | ||
| 540 | timer, | ||
| 541 | ppi_ch1, | ||
| 542 | ppi_ch2, | ||
| 543 | irq, | ||
| 544 | rxd.degrade(), | ||
| 545 | txd.degrade(), | ||
| 546 | None, | ||
| 547 | None, | ||
| 548 | config, | ||
| 549 | ) | ||
| 550 | } | ||
| 551 | |||
| 552 | /// Create a new UARTE with hardware flow control (RTS/CTS) | ||
| 553 | pub fn new_with_rtscts( | ||
| 554 | uarte: impl Unborrow<Target = U> + 'd, | ||
| 555 | timer: impl Unborrow<Target = T> + 'd, | ||
| 556 | ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||
| 557 | ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||
| 558 | irq: impl Unborrow<Target = U::Interrupt> + 'd, | ||
| 559 | rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 560 | txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 561 | cts: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 562 | rts: impl Unborrow<Target = impl GpioPin> + 'd, | ||
| 563 | config: Config, | ||
| 564 | ) -> Self { | ||
| 565 | unborrow!(rxd, txd, cts, rts); | ||
| 566 | Self::new_inner( | ||
| 567 | uarte, | ||
| 568 | timer, | ||
| 569 | ppi_ch1, | ||
| 570 | ppi_ch2, | ||
| 571 | irq, | ||
| 572 | rxd.degrade(), | ||
| 573 | txd.degrade(), | ||
| 574 | Some(cts.degrade()), | ||
| 575 | Some(rts.degrade()), | ||
| 576 | config, | ||
| 577 | ) | ||
| 578 | } | ||
| 579 | |||
| 580 | fn new_inner( | ||
| 581 | uarte: impl Unborrow<Target = U> + 'd, | ||
| 582 | timer: impl Unborrow<Target = T> + 'd, | ||
| 583 | ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||
| 584 | ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||
| 585 | irq: impl Unborrow<Target = U::Interrupt> + 'd, | ||
| 586 | rxd: AnyPin, | ||
| 587 | txd: AnyPin, | ||
| 588 | cts: Option<AnyPin>, | ||
| 589 | rts: Option<AnyPin>, | ||
| 506 | config: Config, | 590 | config: Config, |
| 507 | ) -> Self { | 591 | ) -> Self { |
| 508 | let baudrate = config.baudrate; | 592 | let baudrate = config.baudrate; |
| 509 | let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); | 593 | let uarte = Uarte::new_inner(uarte, irq, rxd, txd, cts, rts, config); |
| 510 | let mut timer = Timer::new(timer); | 594 | let mut timer = Timer::new(timer); |
| 511 | 595 | ||
| 512 | unborrow!(ppi_ch1, ppi_ch2); | 596 | unborrow!(ppi_ch1, ppi_ch2); |
