diff options
author | Henrik Alsér <henrik.alser@me.com> | 2022-08-30 00:30:47 +0200 |
---|---|---|
committer | Henrik Alsér <henrik@mindbite.se> | 2022-09-01 15:12:43 +0200 |
commit | 07c64d902e001ab0943382e9da35f9280a5533d0 (patch) | |
tree | 7b7033da1fdbdfa1ece68fff623957c16b1cc5bb /embassy-rp/src/spi.rs | |
parent | e7d4bf258a8cc30d650d7babc80c79a672052549 (diff) | |
download | embassy-07c64d902e001ab0943382e9da35f9280a5533d0.zip |
example
Diffstat (limited to 'embassy-rp/src/spi.rs')
-rw-r--r-- | embassy-rp/src/spi.rs | 84 |
1 files changed, 79 insertions, 5 deletions
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index c8589dd7..a91a1fd1 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -3,6 +3,7 @@ use core::marker::PhantomData; use embassy_embedded_hal::SetConfig; use embassy_hal_common::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Phase, Polarity}; +use futures::future::join; use crate::dma::{AnyChannel, Channel}; use crate::gpio::sealed::Pin as _; @@ -64,10 +65,8 @@ fn calc_prescs(freq: u32) -> (u8, u8) { } impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { - pub fn new( + pub fn new_blocking( inner: impl Peripheral<P = T> + 'd, - tx_dma: Option<PeripheralRef<'d, AnyChannel>>, - rx_dma: Option<PeripheralRef<'d, AnyChannel>>, clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, @@ -76,8 +75,8 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { into_ref!(clk, mosi, miso); Self::new_inner( inner, - tx_dma, - rx_dma, + None, + None, Some(clk.map_into()), Some(mosi.map_into()), Some(miso.map_into()), @@ -262,6 +261,81 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { } } +impl<'d, T: Instance> Spi<'d, T, Async> { + pub fn new( + inner: impl Peripheral<P = T> + 'd, + tx_dma: impl Peripheral<P = impl Channel> + 'd, + rx_dma: impl Peripheral<P = impl Channel> + 'd, + clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, + mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, + miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, + config: Config, + ) -> Self { + into_ref!(tx_dma, rx_dma, clk, mosi, miso); + Self::new_inner( + inner, + Some(tx_dma.map_into()), + Some(rx_dma.map_into()), + Some(clk.map_into()), + Some(mosi.map_into()), + Some(miso.map_into()), + None, + config, + ) + } + + pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { + let ch = self.tx_dma.as_mut().unwrap(); + let transfer = unsafe { + self.inner.regs().dmacr().modify(|reg| { + reg.set_txdmae(true); + }); + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::write(ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) + }; + transfer.await; + Ok(()) + } + + pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + let ch = self.rx_dma.as_mut().unwrap(); + let transfer = unsafe { + self.inner.regs().dmacr().modify(|reg| { + reg.set_rxdmae(true); + }); + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) + }; + transfer.await; + Ok(()) + } + + pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> { + let tx_ch = self.tx_dma.as_mut().unwrap(); + let tx_transfer = unsafe { + self.inner.regs().dmacr().modify(|reg| { + reg.set_txdmae(true); + }); + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::write(tx_ch, tx_buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) + }; + let rx_ch = self.rx_dma.as_mut().unwrap(); + let rx_transfer = unsafe { + self.inner.regs().dmacr().modify(|reg| { + reg.set_rxdmae(true); + }); + // If we don't assign future to a variable, the data register pointer + // is held across an await and makes the future non-Send. + crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_buffer, T::RX_DREQ) + }; + join(tx_transfer, rx_transfer).await; + Ok(()) + } +} + mod sealed { use super::*; |