Merge #614
614: nrf: remove OptionalPin r=Dirbaio a=Dirbaio Mirror of #605 for nrf Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
		| @@ -27,8 +27,7 @@ use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStor | ||||
| use embassy_hal_common::ring_buffer::RingBuffer; | ||||
| use embassy_hal_common::{low_power_wait_until, unborrow}; | ||||
|  | ||||
| use crate::gpio::sealed::Pin as _; | ||||
| use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; | ||||
| use crate::gpio::Pin as GpioPin; | ||||
| use crate::pac; | ||||
| use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | ||||
| use crate::timer::Instance as TimerInstance; | ||||
| @@ -89,8 +88,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | ||||
|         irq: impl Unborrow<Target = U::Interrupt> + 'd, | ||||
|         rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         cts: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         rts: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|         rx_buffer: &'d mut [u8], | ||||
|         tx_buffer: &'d mut [u8], | ||||
| @@ -108,28 +107,19 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | ||||
|         txd.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | ||||
|  | ||||
|         if let Some(pin) = rts.pin_mut() { | ||||
|             pin.set_high(); | ||||
|             pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         } | ||||
|         cts.conf().write(|w| w.input().connect().drive().h0h1()); | ||||
|         r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | ||||
|  | ||||
|         if let Some(pin) = cts.pin_mut() { | ||||
|             pin.conf().write(|w| w.input().connect().drive().h0h1()); | ||||
|         } | ||||
|         rts.set_high(); | ||||
|         rts.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | ||||
|  | ||||
|         r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); | ||||
|         r.config.write(|w| w.parity().variant(config.parity)); | ||||
|  | ||||
|         // Configure | ||||
|         let hardware_flow_control = match (rts.pin().is_some(), cts.pin().is_some()) { | ||||
|             (false, false) => false, | ||||
|             (true, true) => true, | ||||
|             _ => panic!("RTS and CTS pins must be either both set or none set."), | ||||
|         }; | ||||
|         r.config.write(|w| { | ||||
|             w.hwfc().bit(hardware_flow_control); | ||||
|             w.hwfc().bit(true); | ||||
|             w.parity().variant(config.parity); | ||||
|             w | ||||
|         }); | ||||
|   | ||||
| @@ -287,8 +287,6 @@ pub(crate) mod sealed { | ||||
|             unsafe { self.block().outclr.write(|w| w.bits(1u32 << self._pin())) } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub trait OptionalPin {} | ||||
| } | ||||
|  | ||||
| pub trait Pin: Unborrow<Target = Self> + sealed::Pin + Sized + 'static { | ||||
| @@ -346,59 +344,17 @@ impl sealed::Pin for AnyPin { | ||||
|  | ||||
| // ==================== | ||||
|  | ||||
| pub trait OptionalPin: Unborrow<Target = Self> + sealed::OptionalPin + Sized { | ||||
|     type Pin: Pin; | ||||
|     fn pin(&self) -> Option<&Self::Pin>; | ||||
|     fn pin_mut(&mut self) -> Option<&mut Self::Pin>; | ||||
| pub(crate) trait PselBits { | ||||
|     fn psel_bits(&self) -> u32; | ||||
| } | ||||
|  | ||||
| impl PselBits for Option<AnyPin> { | ||||
|     #[inline] | ||||
|     fn psel_bits(&self) -> u32 { | ||||
|         self.pin().map_or(1u32 << 31, Pin::psel_bits) | ||||
|     } | ||||
|  | ||||
|     /// 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()) | ||||
|         self.as_ref().map_or(1u32 << 31, Pin::psel_bits) | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Copy, Debug)] | ||||
| pub struct NoPin; | ||||
| unsafe_impl_unborrow!(NoPin); | ||||
| impl sealed::OptionalPin for NoPin {} | ||||
| impl OptionalPin for NoPin { | ||||
|     type Pin = AnyPin; | ||||
|  | ||||
|     #[inline] | ||||
|     fn pin(&self) -> Option<&AnyPin> { | ||||
|         None | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn pin_mut(&mut self) -> Option<&mut AnyPin> { | ||||
|         None | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ==================== | ||||
|  | ||||
| pub(crate) fn deconfigure_pin(psel_bits: u32) { | ||||
|     if psel_bits & 0x8000_0000 != 0 { | ||||
|         return; | ||||
|   | ||||
| @@ -6,7 +6,7 @@ use embassy::util::Unborrow; | ||||
| use embassy_hal_common::unborrow; | ||||
|  | ||||
| use crate::gpio::sealed::Pin as _; | ||||
| use crate::gpio::{AnyPin, OptionalPin as GpioOptionalPin}; | ||||
| use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; | ||||
| use crate::interrupt::Interrupt; | ||||
| use crate::pac; | ||||
| use crate::ppi::{Event, Task}; | ||||
| @@ -48,47 +48,104 @@ pub enum Error { | ||||
| const MAX_SEQUENCE_LEN: usize = 32767; | ||||
|  | ||||
| impl<'d, T: Instance> SequencePwm<'d, T> { | ||||
|     /// Creates the interface to a `SequencePwm`. | ||||
|     /// | ||||
|     /// Must be started by calling `start` | ||||
|     /// | ||||
|     /// # Safety | ||||
|     /// | ||||
|     /// The returned API is safe unless you use `mem::forget` (or similar safe | ||||
|     /// mechanisms) on stack allocated buffers which which have been passed to | ||||
|     /// [`new()`](SequencePwm::new). | ||||
|     /// Create a new 1-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new( | ||||
|         _pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|     pub fn new_1ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, Error> { | ||||
|         unborrow!(ch0); | ||||
|         Self::new_inner(pwm, Some(ch0.degrade()), None, None, None, config) | ||||
|     } | ||||
|  | ||||
|     /// Create a new 2-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new_2ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, Error> { | ||||
|         unborrow!(ch0, ch1); | ||||
|         Self::new_inner( | ||||
|             pwm, | ||||
|             Some(ch0.degrade()), | ||||
|             Some(ch1.degrade()), | ||||
|             None, | ||||
|             None, | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /// Create a new 3-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new_3ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, Error> { | ||||
|         unborrow!(ch0, ch1, ch2); | ||||
|         Self::new_inner( | ||||
|             pwm, | ||||
|             Some(ch0.degrade()), | ||||
|             Some(ch1.degrade()), | ||||
|             Some(ch2.degrade()), | ||||
|             None, | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /// Create a new 4-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new_4ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch3: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, Error> { | ||||
|         unborrow!(ch0, ch1, ch2, ch3); | ||||
|         Self::new_inner( | ||||
|             pwm, | ||||
|             Some(ch0.degrade()), | ||||
|             Some(ch1.degrade()), | ||||
|             Some(ch2.degrade()), | ||||
|             Some(ch3.degrade()), | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fn new_inner( | ||||
|         _pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: Option<AnyPin>, | ||||
|         ch1: Option<AnyPin>, | ||||
|         ch2: Option<AnyPin>, | ||||
|         ch3: Option<AnyPin>, | ||||
|         config: Config, | ||||
|     ) -> Result<Self, Error> { | ||||
|         let r = T::regs(); | ||||
|  | ||||
|         if let Some(pin) = ch0.pin_mut() { | ||||
|         if let Some(pin) = &ch0 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|         if let Some(pin) = ch1.pin_mut() { | ||||
|         if let Some(pin) = &ch1 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|         if let Some(pin) = ch2.pin_mut() { | ||||
|         if let Some(pin) = &ch2 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|         if let Some(pin) = ch3.pin_mut() { | ||||
|         if let Some(pin) = &ch3 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|  | ||||
|         // if NoPin provided writes disconnected (top bit 1) 0x80000000 else | ||||
|         // writes pin number ex 13 (0x0D) which is connected (top bit 0) | ||||
|         r.psel.out[0].write(|w| unsafe { w.bits(ch0.psel_bits()) }); | ||||
|         r.psel.out[1].write(|w| unsafe { w.bits(ch1.psel_bits()) }); | ||||
|         r.psel.out[2].write(|w| unsafe { w.bits(ch2.psel_bits()) }); | ||||
| @@ -121,10 +178,10 @@ impl<'d, T: Instance> SequencePwm<'d, T> { | ||||
|  | ||||
|         Ok(Self { | ||||
|             phantom: PhantomData, | ||||
|             ch0: ch0.degrade_optional(), | ||||
|             ch1: ch1.degrade_optional(), | ||||
|             ch2: ch2.degrade_optional(), | ||||
|             ch3: ch3.degrade_optional(), | ||||
|             ch0, | ||||
|             ch1, | ||||
|             ch2, | ||||
|             ch3, | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @@ -545,41 +602,86 @@ pub enum CounterMode { | ||||
| } | ||||
|  | ||||
| impl<'d, T: Instance> SimplePwm<'d, T> { | ||||
|     /// Creates the interface to a `SimplePwm` | ||||
|     /// | ||||
|     /// Enables the peripheral, defaults the freq to 1Mhz, max_duty 1000, duty | ||||
|     /// 0, up mode, and pins low. Must be started by calling `set_duty` | ||||
|     /// | ||||
|     /// # Safety | ||||
|     /// | ||||
|     /// The returned API is safe unless you use `mem::forget` (or similar safe | ||||
|     /// mechanisms) on stack allocated buffers which which have been passed to | ||||
|     /// [`new()`](SimplePwm::new). | ||||
|     /// Create a new 1-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new( | ||||
|         _pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|     pub fn new_1ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch0); | ||||
|         Self::new_inner(pwm, Some(ch0.degrade()), None, None, None) | ||||
|     } | ||||
|  | ||||
|     /// Create a new 2-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new_2ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch0, ch1); | ||||
|         Self::new_inner(pwm, Some(ch0.degrade()), Some(ch1.degrade()), None, None) | ||||
|     } | ||||
|  | ||||
|     /// Create a new 3-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new_3ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch0, ch1, ch2); | ||||
|         Self::new_inner( | ||||
|             pwm, | ||||
|             Some(ch0.degrade()), | ||||
|             Some(ch1.degrade()), | ||||
|             Some(ch2.degrade()), | ||||
|             None, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /// Create a new 4-channel PWM | ||||
|     #[allow(unused_unsafe)] | ||||
|     pub fn new_4ch( | ||||
|         pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch1: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch2: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         ch3: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|     ) -> Self { | ||||
|         unborrow!(ch0, ch1, ch2, ch3); | ||||
|         Self::new_inner( | ||||
|             pwm, | ||||
|             Some(ch0.degrade()), | ||||
|             Some(ch1.degrade()), | ||||
|             Some(ch2.degrade()), | ||||
|             Some(ch3.degrade()), | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fn new_inner( | ||||
|         _pwm: impl Unborrow<Target = T> + 'd, | ||||
|         ch0: Option<AnyPin>, | ||||
|         ch1: Option<AnyPin>, | ||||
|         ch2: Option<AnyPin>, | ||||
|         ch3: Option<AnyPin>, | ||||
|     ) -> Self { | ||||
|         let r = T::regs(); | ||||
|  | ||||
|         if let Some(pin) = ch0.pin_mut() { | ||||
|         if let Some(pin) = &ch0 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|         if let Some(pin) = ch1.pin_mut() { | ||||
|         if let Some(pin) = &ch1 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|         if let Some(pin) = ch2.pin_mut() { | ||||
|         if let Some(pin) = &ch2 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
|         if let Some(pin) = ch3.pin_mut() { | ||||
|         if let Some(pin) = &ch3 { | ||||
|             pin.set_low(); | ||||
|             pin.conf().write(|w| w.dir().output()); | ||||
|         } | ||||
| @@ -593,10 +695,10 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | ||||
|  | ||||
|         let pwm = Self { | ||||
|             phantom: PhantomData, | ||||
|             ch0: ch0.degrade_optional(), | ||||
|             ch1: ch1.degrade_optional(), | ||||
|             ch2: ch2.degrade_optional(), | ||||
|             ch3: ch3.degrade_optional(), | ||||
|             ch0, | ||||
|             ch1, | ||||
|             ch2, | ||||
|             ch3, | ||||
|             duty: [0; 4], | ||||
|         }; | ||||
|  | ||||
|   | ||||
| @@ -8,9 +8,9 @@ use embassy::util::Unborrow; | ||||
| use embassy_hal_common::unborrow; | ||||
| use futures::future::poll_fn; | ||||
|  | ||||
| use crate::gpio; | ||||
| use crate::gpio::sealed::Pin as _; | ||||
| use crate::gpio::{OptionalPin, Pin as GpioPin}; | ||||
| use crate::gpio::{self, AnyPin}; | ||||
| use crate::gpio::{Pin as GpioPin, PselBits}; | ||||
| use crate::interrupt::Interrupt; | ||||
| use crate::util::{slice_ptr_parts, slice_ptr_parts_mut}; | ||||
| use crate::{pac, util::slice_in_ram_or}; | ||||
| @@ -51,36 +51,77 @@ impl Default for Config { | ||||
|  | ||||
| impl<'d, T: Instance> Spim<'d, T> { | ||||
|     pub fn new( | ||||
|         _spim: impl Unborrow<Target = T> + 'd, | ||||
|         spim: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         sck: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         miso: impl Unborrow<Target = impl OptionalPin> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl OptionalPin> + 'd, | ||||
|         miso: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(irq, sck, miso, mosi); | ||||
|         unborrow!(sck, miso, mosi); | ||||
|         Self::new_inner( | ||||
|             spim, | ||||
|             irq, | ||||
|             sck.degrade(), | ||||
|             Some(miso.degrade()), | ||||
|             Some(mosi.degrade()), | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     pub fn new_txonly( | ||||
|         spim: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         sck: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         mosi: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(sck, mosi); | ||||
|         Self::new_inner(spim, irq, sck.degrade(), None, Some(mosi.degrade()), config) | ||||
|     } | ||||
|  | ||||
|     pub fn new_rxonly( | ||||
|         spim: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         sck: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         miso: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(sck, miso); | ||||
|         Self::new_inner(spim, irq, sck.degrade(), Some(miso.degrade()), None, config) | ||||
|     } | ||||
|  | ||||
|     fn new_inner( | ||||
|         _spim: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         sck: AnyPin, | ||||
|         miso: Option<AnyPin>, | ||||
|         mosi: Option<AnyPin>, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(irq); | ||||
|  | ||||
|         let r = T::regs(); | ||||
|  | ||||
|         // Configure pins | ||||
|         sck.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         if let Some(mosi) = mosi.pin_mut() { | ||||
|         if let Some(mosi) = &mosi { | ||||
|             mosi.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         } | ||||
|         if let Some(miso) = miso.pin_mut() { | ||||
|         if let Some(miso) = &miso { | ||||
|             miso.conf().write(|w| w.input().connect().drive().h0h1()); | ||||
|         } | ||||
|  | ||||
|         match config.mode.polarity { | ||||
|             Polarity::IdleHigh => { | ||||
|                 sck.set_high(); | ||||
|                 if let Some(mosi) = mosi.pin_mut() { | ||||
|                 if let Some(mosi) = &mosi { | ||||
|                     mosi.set_high(); | ||||
|                 } | ||||
|             } | ||||
|             Polarity::IdleLow => { | ||||
|                 sck.set_low(); | ||||
|                 if let Some(mosi) = mosi.pin_mut() { | ||||
|                 if let Some(mosi) = &mosi { | ||||
|                     mosi.set_low(); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -24,7 +24,7 @@ use futures::future::poll_fn; | ||||
|  | ||||
| use crate::chip::EASY_DMA_SIZE; | ||||
| use crate::gpio::sealed::Pin as _; | ||||
| use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin}; | ||||
| use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | ||||
| use crate::interrupt::Interrupt; | ||||
| use crate::pac; | ||||
| use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | ||||
| @@ -80,18 +80,50 @@ pub struct UarteRx<'d, T: Instance> { | ||||
| } | ||||
|  | ||||
| impl<'d, T: Instance> Uarte<'d, T> { | ||||
|     /// Creates the interface to a UARTE instance. | ||||
|     /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | ||||
|     /// Create a new UARTE without hardware flow control | ||||
|     pub fn new( | ||||
|         _uarte: impl Unborrow<Target = T> + 'd, | ||||
|         uarte: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(irq, rxd, txd, cts, rts); | ||||
|         unborrow!(rxd, txd); | ||||
|         Self::new_inner(uarte, irq, rxd.degrade(), txd.degrade(), None, None, config) | ||||
|     } | ||||
|  | ||||
|     /// Create a new UARTE with hardware flow control (RTS/CTS) | ||||
|     pub fn new_with_rtscts( | ||||
|         uarte: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         cts: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         rts: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(rxd, txd, cts, rts); | ||||
|         Self::new_inner( | ||||
|             uarte, | ||||
|             irq, | ||||
|             rxd.degrade(), | ||||
|             txd.degrade(), | ||||
|             Some(cts.degrade()), | ||||
|             Some(rts.degrade()), | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fn new_inner( | ||||
|         _uarte: impl Unborrow<Target = T> + 'd, | ||||
|         irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||||
|         rxd: AnyPin, | ||||
|         txd: AnyPin, | ||||
|         cts: Option<AnyPin>, | ||||
|         rts: Option<AnyPin>, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(irq); | ||||
|  | ||||
|         let r = T::regs(); | ||||
|  | ||||
| @@ -102,19 +134,19 @@ impl<'d, T: Instance> Uarte<'d, T> { | ||||
|         txd.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); | ||||
|  | ||||
|         if let Some(pin) = rts.pin_mut() { | ||||
|             pin.set_high(); | ||||
|             pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         if let Some(pin) = &cts { | ||||
|             pin.conf().write(|w| w.input().connect().drive().h0h1()); | ||||
|         } | ||||
|         r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); | ||||
|  | ||||
|         if let Some(pin) = cts.pin_mut() { | ||||
|             pin.conf().write(|w| w.input().connect().drive().h0h1()); | ||||
|         if let Some(pin) = &rts { | ||||
|             pin.set_high(); | ||||
|             pin.conf().write(|w| w.dir().output().drive().h0h1()); | ||||
|         } | ||||
|         r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); | ||||
|  | ||||
|         // Configure | ||||
|         let hardware_flow_control = match (rts.pin().is_some(), cts.pin().is_some()) { | ||||
|         let hardware_flow_control = match (rts.is_some(), cts.is_some()) { | ||||
|             (false, false) => false, | ||||
|             (true, true) => true, | ||||
|             _ => 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> { | ||||
| } | ||||
|  | ||||
| impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | ||||
|     /// Creates the interface to a UARTE instance. | ||||
|     /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | ||||
|     /// Create a new UARTE without hardware flow control | ||||
|     pub fn new( | ||||
|         uarte: impl Unborrow<Target = U> + 'd, | ||||
|         timer: impl Unborrow<Target = T> + 'd, | ||||
| @@ -501,12 +532,65 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | ||||
|         irq: impl Unborrow<Target = U::Interrupt> + 'd, | ||||
|         rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         cts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         rts: impl Unborrow<Target = impl GpioOptionalPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(rxd, txd); | ||||
|         Self::new_inner( | ||||
|             uarte, | ||||
|             timer, | ||||
|             ppi_ch1, | ||||
|             ppi_ch2, | ||||
|             irq, | ||||
|             rxd.degrade(), | ||||
|             txd.degrade(), | ||||
|             None, | ||||
|             None, | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /// Create a new UARTE with hardware flow control (RTS/CTS) | ||||
|     pub fn new_with_rtscts( | ||||
|         uarte: impl Unborrow<Target = U> + 'd, | ||||
|         timer: impl Unborrow<Target = T> + 'd, | ||||
|         ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||||
|         ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||||
|         irq: impl Unborrow<Target = U::Interrupt> + 'd, | ||||
|         rxd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         txd: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         cts: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         rts: impl Unborrow<Target = impl GpioPin> + 'd, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         unborrow!(rxd, txd, cts, rts); | ||||
|         Self::new_inner( | ||||
|             uarte, | ||||
|             timer, | ||||
|             ppi_ch1, | ||||
|             ppi_ch2, | ||||
|             irq, | ||||
|             rxd.degrade(), | ||||
|             txd.degrade(), | ||||
|             Some(cts.degrade()), | ||||
|             Some(rts.degrade()), | ||||
|             config, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fn new_inner( | ||||
|         uarte: impl Unborrow<Target = U> + 'd, | ||||
|         timer: impl Unborrow<Target = T> + 'd, | ||||
|         ppi_ch1: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||||
|         ppi_ch2: impl Unborrow<Target = impl ConfigurableChannel + 'd> + 'd, | ||||
|         irq: impl Unborrow<Target = U::Interrupt> + 'd, | ||||
|         rxd: AnyPin, | ||||
|         txd: AnyPin, | ||||
|         cts: Option<AnyPin>, | ||||
|         rts: Option<AnyPin>, | ||||
|         config: Config, | ||||
|     ) -> Self { | ||||
|         let baudrate = config.baudrate; | ||||
|         let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); | ||||
|         let uarte = Uarte::new_inner(uarte, irq, rxd, txd, cts, rts, config); | ||||
|         let mut timer = Timer::new(timer); | ||||
|  | ||||
|         unborrow!(ppi_ch1, ppi_ch2); | ||||
|   | ||||
| @@ -85,7 +85,7 @@ static DUTY: [u16; 1024] = [ | ||||
|  | ||||
| #[embassy::main] | ||||
| async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     let mut pwm = SimplePwm::new(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); | ||||
|     let mut pwm = SimplePwm::new_4ch(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); | ||||
|     pwm.set_prescaler(Prescaler::Div1); | ||||
|     pwm.set_max_duty(32767); | ||||
|     info!("pwm initialized!"); | ||||
|   | ||||
| @@ -7,7 +7,6 @@ mod example_common; | ||||
| use defmt::*; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::pwm::{ | ||||
|     Config, Prescaler, Sequence, SequenceConfig, SequenceMode, SequencePwm, Sequencer, | ||||
|     StartSequence, | ||||
| @@ -29,9 +28,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     seq_config.refresh = 624; | ||||
|     // thus our sequence takes 5 * 5000ms or 25 seconds | ||||
|  | ||||
|     let mut pwm = unwrap!(SequencePwm::new( | ||||
|         p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, | ||||
|     )); | ||||
|     let mut pwm = unwrap!(SequencePwm::new_1ch(p.PWM0, p.P0_13, config)); | ||||
|  | ||||
|     let sequence_0 = Sequence::new(&seq_words_0, seq_config.clone()); | ||||
|     let sequence_1 = Sequence::new(&seq_words_1, seq_config); | ||||
|   | ||||
| @@ -7,7 +7,6 @@ mod example_common; | ||||
| use defmt::*; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::pwm::{ | ||||
|     Config, Prescaler, SequenceConfig, SequencePwm, SingleSequenceMode, SingleSequencer, | ||||
| }; | ||||
| @@ -27,9 +26,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     seq_config.refresh = 624; | ||||
|     // thus our sequence takes 5 * 5000ms or 25 seconds | ||||
|  | ||||
|     let mut pwm = unwrap!(SequencePwm::new( | ||||
|         p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, | ||||
|     )); | ||||
|     let mut pwm = unwrap!(SequencePwm::new_1ch(p.PWM0, p.P0_13, config,)); | ||||
|  | ||||
|     let sequencer = SingleSequencer::new(&mut pwm, &seq_words, seq_config); | ||||
|     unwrap!(sequencer.start(SingleSequenceMode::Times(1))); | ||||
|   | ||||
| @@ -8,7 +8,7 @@ mod example_common; | ||||
| use core::future::pending; | ||||
| use defmt::*; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy_nrf::gpio::{Input, NoPin, Pull}; | ||||
| use embassy_nrf::gpio::{Input, Pull}; | ||||
| use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; | ||||
| use embassy_nrf::ppi::Ppi; | ||||
| use embassy_nrf::pwm::{ | ||||
| @@ -29,9 +29,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     let mut seq_config = SequenceConfig::default(); | ||||
|     seq_config.refresh = 30; | ||||
|  | ||||
|     let mut pwm = unwrap!(SequencePwm::new( | ||||
|         p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config, | ||||
|     )); | ||||
|     let mut pwm = unwrap!(SequencePwm::new_1ch(p.PWM0, p.P0_13, config)); | ||||
|  | ||||
|     // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work | ||||
|     // so its going to have to start running in order load the configuration | ||||
|   | ||||
| @@ -7,7 +7,6 @@ mod example_common; | ||||
| use defmt::*; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::pwm::{ | ||||
|     Config, Prescaler, SequenceConfig, SequenceLoad, SequencePwm, SingleSequenceMode, | ||||
|     SingleSequencer, | ||||
| @@ -35,9 +34,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     config.sequence_load = SequenceLoad::Common; | ||||
|     config.prescaler = Prescaler::Div1; | ||||
|     config.max_duty = 20; // 1.25us (1s / 16Mhz * 20) | ||||
|     let mut pwm = unwrap!(SequencePwm::new( | ||||
|         p.PWM0, p.P1_05, NoPin, NoPin, NoPin, config, | ||||
|     )); | ||||
|     let mut pwm = unwrap!(SequencePwm::new_1ch(p.PWM0, p.P1_05, config)); | ||||
|  | ||||
|     // Declare the bits of 24 bits in a buffer we'll be | ||||
|     // mutating later. | ||||
|   | ||||
| @@ -7,13 +7,12 @@ mod example_common; | ||||
| use defmt::*; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::pwm::{Prescaler, SimplePwm}; | ||||
| use embassy_nrf::Peripherals; | ||||
|  | ||||
| #[embassy::main] | ||||
| async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     let mut pwm = SimplePwm::new(p.PWM0, p.P0_05, NoPin, NoPin, NoPin); | ||||
|     let mut pwm = SimplePwm::new_1ch(p.PWM0, p.P0_05); | ||||
|     // sg90 microervo requires 50hz or 20ms period | ||||
|     // set_period can only set down to 125khz so we cant use it directly | ||||
|     // Div128 is 125khz or 0.000008s or 0.008ms, 20/0.008 is 2500 is top | ||||
|   | ||||
| @@ -7,7 +7,6 @@ mod example_common; | ||||
| use example_common::*; | ||||
|  | ||||
| use embassy::executor::Spawner; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::{interrupt, uarte, Peripherals}; | ||||
|  | ||||
| #[embassy::main] | ||||
| @@ -17,7 +16,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|     config.baudrate = uarte::Baudrate::BAUD115200; | ||||
|  | ||||
|     let irq = interrupt::take!(UARTE0_UART0); | ||||
|     let mut uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, NoPin, NoPin, config); | ||||
|     let mut uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, config); | ||||
|  | ||||
|     info!("uarte initialized!"); | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,6 @@ mod example_common; | ||||
| use example_common::*; | ||||
|  | ||||
| use embassy::executor::Spawner; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::{interrupt, uarte, Peripherals}; | ||||
|  | ||||
| #[embassy::main] | ||||
| @@ -18,7 +17,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { | ||||
|  | ||||
|     let irq = interrupt::take!(UARTE0_UART0); | ||||
|     let mut uart = uarte::UarteWithIdle::new( | ||||
|         p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, | ||||
|         p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, config, | ||||
|     ); | ||||
|  | ||||
|     info!("uarte initialized!"); | ||||
|   | ||||
| @@ -10,7 +10,6 @@ use embassy::blocking_mutex::kind::Noop; | ||||
| use embassy::channel::mpsc::{self, Channel, Sender}; | ||||
| use embassy::executor::Spawner; | ||||
| use embassy::util::Forever; | ||||
| use embassy_nrf::gpio::NoPin; | ||||
| use embassy_nrf::peripherals::UARTE0; | ||||
| use embassy_nrf::uarte::UarteRx; | ||||
| use embassy_nrf::{interrupt, uarte, Peripherals}; | ||||
| @@ -24,7 +23,7 @@ async fn main(spawner: Spawner, p: Peripherals) { | ||||
|     config.baudrate = uarte::Baudrate::BAUD115200; | ||||
|  | ||||
|     let irq = interrupt::take!(UARTE0_UART0); | ||||
|     let uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, NoPin, NoPin, config); | ||||
|     let uart = uarte::Uarte::new(p.UARTE0, irq, p.P0_08, p.P0_06, config); | ||||
|     let (mut tx, rx) = uart.split(); | ||||
|  | ||||
|     let c = CHANNEL.put(Channel::new()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user