From e7d4bf258a8cc30d650d7babc80c79a672052549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Mon, 29 Aug 2022 00:30:50 +0200 Subject: [PATCH 01/14] dma --- embassy-rp/src/spi.rs | 91 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index d0261598e..c8589dd75 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -1,7 +1,10 @@ +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 crate::dma::{AnyChannel, Channel}; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Pin as GpioPin}; use crate::{pac, peripherals, Peripheral}; @@ -30,8 +33,11 @@ impl Default for Config { } } -pub struct Spi<'d, T: Instance> { +pub struct Spi<'d, T: Instance, M: Mode> { inner: PeripheralRef<'d, T>, + tx_dma: Option>, + rx_dma: Option>, + phantom: PhantomData<(&'d mut T, M)>, } fn div_roundup(a: u32, b: u32) -> u32 { @@ -57,9 +63,11 @@ fn calc_prescs(freq: u32) -> (u8, u8) { ((presc * 2) as u8, (postdiv - 1) as u8) } -impl<'d, T: Instance> Spi<'d, T> { +impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { pub fn new( inner: impl Peripheral

+ 'd, + tx_dma: Option>, + rx_dma: Option>, clk: impl Peripheral

+ 'd> + 'd, mosi: impl Peripheral

+ 'd> + 'd, miso: impl Peripheral

+ 'd> + 'd, @@ -68,6 +76,8 @@ impl<'d, T: Instance> Spi<'d, T> { into_ref!(clk, mosi, miso); Self::new_inner( inner, + tx_dma, + rx_dma, Some(clk.map_into()), Some(mosi.map_into()), Some(miso.map_into()), @@ -78,26 +88,48 @@ impl<'d, T: Instance> Spi<'d, T> { pub fn new_txonly( inner: impl Peripheral

+ 'd, + tx_dma: Option>, clk: impl Peripheral

+ 'd> + 'd, mosi: impl Peripheral

+ 'd> + 'd, config: Config, ) -> Self { into_ref!(clk, mosi); - Self::new_inner(inner, Some(clk.map_into()), Some(mosi.map_into()), None, None, config) + Self::new_inner( + inner, + tx_dma, + None, + Some(clk.map_into()), + Some(mosi.map_into()), + None, + None, + config, + ) } pub fn new_rxonly( inner: impl Peripheral

+ 'd, + rx_dma: Option>, clk: impl Peripheral

+ 'd> + 'd, miso: impl Peripheral

+ 'd> + 'd, config: Config, ) -> Self { into_ref!(clk, miso); - Self::new_inner(inner, Some(clk.map_into()), None, Some(miso.map_into()), None, config) + Self::new_inner( + inner, + None, + rx_dma, + Some(clk.map_into()), + None, + Some(miso.map_into()), + None, + config, + ) } fn new_inner( inner: impl Peripheral

+ 'd, + tx_dma: Option>, + rx_dma: Option>, clk: Option>, mosi: Option>, miso: Option>, @@ -134,7 +166,12 @@ impl<'d, T: Instance> Spi<'d, T> { pin.io().ctrl().write(|w| w.set_funcsel(1)); } } - Self { inner } + Self { + inner, + tx_dma, + rx_dma, + phantom: PhantomData, + } } pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { @@ -228,16 +265,25 @@ impl<'d, T: Instance> Spi<'d, T> { mod sealed { use super::*; + pub trait Mode {} + pub trait Instance { + const TX_DREQ: u8; + const RX_DREQ: u8; + fn regs(&self) -> pac::spi::Spi; } } +pub trait Mode: sealed::Mode {} pub trait Instance: sealed::Instance {} macro_rules! impl_instance { - ($type:ident, $irq:ident) => { + ($type:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => { impl sealed::Instance for peripherals::$type { + const TX_DREQ: u8 = $tx_dreq; + const RX_DREQ: u8 = $rx_dreq; + fn regs(&self) -> pac::spi::Spi { pac::$type } @@ -246,8 +292,8 @@ macro_rules! impl_instance { }; } -impl_instance!(SPI0, Spi0); -impl_instance!(SPI1, Spi1); +impl_instance!(SPI0, Spi0, 16, 17); +impl_instance!(SPI1, Spi1, 18, 19); pub trait ClkPin: GpioPin {} pub trait CsPin: GpioPin {} @@ -281,12 +327,25 @@ impl_pin!(PIN_17, SPI0, CsPin); impl_pin!(PIN_18, SPI0, ClkPin); impl_pin!(PIN_19, SPI0, MosiPin); +macro_rules! impl_mode { + ($name:ident) => { + impl sealed::Mode for $name {} + impl Mode for $name {} + }; +} + +pub struct Blocking; +pub struct Async; + +impl_mode!(Blocking); +impl_mode!(Async); + // ==================== mod eh02 { use super::*; - impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::spi::Transfer for Spi<'d, T, M> { type Error = Error; fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { self.blocking_transfer_in_place(words)?; @@ -294,7 +353,7 @@ mod eh02 { } } - impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::spi::Write for Spi<'d, T, M> { type Error = Error; fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { @@ -313,29 +372,29 @@ mod eh1 { } } - impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::ErrorType for Spi<'d, T, M> { type Error = Error; } - impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusFlush for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBusFlush for Spi<'d, T, M> { fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } } - impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBusRead for Spi<'d, T, M> { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.blocking_transfer(words, &[]) } } - impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBusWrite for Spi<'d, T, M> { fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { self.blocking_write(words) } } - impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus for Spi<'d, T> { + impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBus for Spi<'d, T, M> { fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.blocking_transfer(read, write) } @@ -346,7 +405,7 @@ mod eh1 { } } -impl<'d, T: Instance> SetConfig for Spi<'d, T> { +impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> { type Config = Config; fn set_config(&mut self, config: &Self::Config) { let p = self.inner.regs(); From 07c64d902e001ab0943382e9da35f9280a5533d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Tue, 30 Aug 2022 00:30:47 +0200 Subject: [PATCH 02/14] example --- embassy-rp/src/spi.rs | 84 ++++++++++++++++++++++++++++++-- examples/rp/src/bin/spi.rs | 4 +- examples/rp/src/bin/spi_async.rs | 31 ++++++++++++ 3 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 examples/rp/src/bin/spi_async.rs diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index c8589dd75..a91a1fd19 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

+ 'd, - tx_dma: Option>, - rx_dma: Option>, clk: impl Peripheral

+ 'd> + 'd, mosi: impl Peripheral

+ 'd> + 'd, miso: impl Peripheral

+ '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

+ 'd, + tx_dma: impl Peripheral

+ 'd, + rx_dma: impl Peripheral

+ 'd, + clk: impl Peripheral

+ 'd> + 'd, + mosi: impl Peripheral

+ 'd> + 'd, + miso: impl Peripheral

+ '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::*; diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index 88003ee17..e50297ae4 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::Spi; +use embassy_rp::spi::{Blocking, Spi}; use embassy_rp::{gpio, spi}; use gpio::{Level, Output}; use {defmt_rtt as _, panic_probe as _}; @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { // create SPI let mut config = spi::Config::default(); config.frequency = 2_000_000; - let mut spi = Spi::new(p.SPI1, clk, mosi, miso, config); + let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); // Configure CS let mut cs = Output::new(touch_cs, Level::Low); diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs new file mode 100644 index 000000000..f21377ede --- /dev/null +++ b/examples/rp/src/bin/spi_async.rs @@ -0,0 +1,31 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::spi::{Async, Spi}; +use embassy_rp::{gpio, spi}; +use embassy_time::{Duration, Timer}; +use gpio::{Level, Output}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let miso = p.PIN_12; + let mosi = p.PIN_11; + let clk = p.PIN_10; + + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, spi::Config::default()); + + loop { + let tx_buf = [1_u8, 2, 3, 4, 5, 6]; + let mut rx_buf = [0_u8; 6]; + spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); + info!("{:?}", rx_buf); + Timer::after(Duration::from_secs(1)).await; + } +} From 44150c483017c18979e58d8557aac3df031ba47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Tue, 30 Aug 2022 01:18:28 +0200 Subject: [PATCH 03/14] impl embedded-hal-async --- embassy-rp/src/spi.rs | 54 ++++++++++++++++++++++++++++++++ examples/rp/src/bin/spi_async.rs | 6 ++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index a91a1fd19..be639504f 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -479,6 +479,60 @@ mod eh1 { } } +cfg_if::cfg_if! { + if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] { + use core::future::Future; + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Async> { + type FlushFuture<'a> = impl Future> + 'a where Self: 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + async { Ok(()) } + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite + for Spi<'d, T, Async> + { + type WriteFuture<'a> = impl Future> + 'a where Self: 'a; + + fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(data) + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead + for Spi<'d, T, Async> + { + type ReadFuture<'a> = impl Future> + 'a where Self: 'a; + + fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(data) + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::SpiBus + for Spi<'d, T, Async> + { + type TransferFuture<'a> = impl Future> + 'a where Self: 'a; + + fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> { + self.transfer(rx, tx) + } + + type TransferInPlaceFuture<'a> = impl Future> + 'a where Self: 'a; + + fn transfer_in_place<'a>( + &'a mut self, + words: &'a mut [u8], + ) -> Self::TransferInPlaceFuture<'a> { + let (ptr, len) = crate::dma::slice_ptr_parts(words); + let tx_buffer = unsafe { core::slice::from_raw_parts(ptr as *const _, len) }; + self.transfer(words, tx_buffer) + } + } + } +} + impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> { type Config = Config; fn set_config(&mut self, config: &Self::Config) { diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index f21377ede..359ad50e7 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -4,10 +4,8 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::{Async, Spi}; -use embassy_rp::{gpio, spi}; +use embassy_rp::spi::{Async, Config, Spi}; use embassy_time::{Duration, Timer}; -use gpio::{Level, Output}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -19,7 +17,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_11; let clk = p.PIN_10; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, spi::Config::default()); + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; From c8ecc557109bd14bea0564e4a1505a26947e1851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Tue, 30 Aug 2022 01:39:08 +0200 Subject: [PATCH 04/14] Fix example --- examples/rp/src/bin/spi_display.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index f0e54d87f..d0fbd6847 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{Level, Output}; use embassy_rp::spi; -use embassy_rp::spi::Spi; +use embassy_rp::spi::{Spi, Blocking}; use embassy_time::Delay; use embedded_graphics::image::{Image, ImageRawLE}; use embedded_graphics::mono_font::ascii::FONT_10X20; @@ -48,7 +48,8 @@ async fn main(_spawner: Spawner) { config.phase = spi::Phase::CaptureOnSecondTransition; config.polarity = spi::Polarity::IdleHigh; - let spi_bus = RefCell::new(Spi::new(p.SPI1, clk, mosi, miso, config)); + let spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); + let spi_bus = RefCell::new(spi); let display_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(display_cs, Level::High)); let touch_spi = SpiDeviceWithCs::new(&spi_bus, Output::new(touch_cs, Level::High)); From 6d347af9fae3a9c594e13900796ec57537c402e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Tue, 30 Aug 2022 06:50:58 +0200 Subject: [PATCH 05/14] transfer_in_place --- embassy-rp/src/spi.rs | 15 ++++++++------- examples/rp/src/bin/spi_display.rs | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index be639504f..11aad6305 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -334,6 +334,12 @@ impl<'d, T: Instance> Spi<'d, T, Async> { join(tx_transfer, rx_transfer).await; Ok(()) } + + pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { + let (ptr, len) = crate::dma::slice_ptr_parts(words); + let tx_buffer = unsafe { core::slice::from_raw_parts(ptr as *const _, len) }; + self.transfer(words, tx_buffer).await + } } mod sealed { @@ -521,13 +527,8 @@ cfg_if::cfg_if! { type TransferInPlaceFuture<'a> = impl Future> + 'a where Self: 'a; - fn transfer_in_place<'a>( - &'a mut self, - words: &'a mut [u8], - ) -> Self::TransferInPlaceFuture<'a> { - let (ptr, len) = crate::dma::slice_ptr_parts(words); - let tx_buffer = unsafe { core::slice::from_raw_parts(ptr as *const _, len) }; - self.transfer(words, tx_buffer) + fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Self::TransferInPlaceFuture<'a> { + self.transfer_in_place(words) } } } diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index d0fbd6847..23cd4355e 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::gpio::{Level, Output}; use embassy_rp::spi; -use embassy_rp::spi::{Spi, Blocking}; +use embassy_rp::spi::{Blocking, Spi}; use embassy_time::Delay; use embedded_graphics::image::{Image, ImageRawLE}; use embedded_graphics::mono_font::ascii::FONT_10X20; From 99dd2a9386c83f4e625f4c849c8b5e519e12a87c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Tue, 30 Aug 2022 22:55:53 +0200 Subject: [PATCH 06/14] Reorder args --- embassy-rp/src/spi.rs | 4 ++-- examples/rp/src/bin/spi_async.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 11aad6305..6f68777b2 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -264,11 +264,11 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { impl<'d, T: Instance> Spi<'d, T, Async> { pub fn new( inner: impl Peripheral

+ 'd, - tx_dma: impl Peripheral

+ 'd, - rx_dma: impl Peripheral

+ 'd, clk: impl Peripheral

+ 'd> + 'd, mosi: impl Peripheral

+ 'd> + 'd, miso: impl Peripheral

+ 'd> + 'd, + tx_dma: impl Peripheral

+ 'd, + rx_dma: impl Peripheral

+ 'd, config: Config, ) -> Self { into_ref!(tx_dma, rx_dma, clk, mosi, miso); diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index 359ad50e7..b2df0dd11 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_11; let clk = p.PIN_10; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, Config::default()); + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; From 7954cbc4e7f44ff5292052da00b1ced857d3183a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Tue, 30 Aug 2022 23:04:58 +0200 Subject: [PATCH 07/14] Add HIL tests --- tests/rp/src/bin/spi.rs | 28 ++++++++++++++++++++++++++++ tests/rp/src/bin/spi_async.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/rp/src/bin/spi.rs create mode 100644 tests/rp/src/bin/spi_async.rs diff --git a/tests/rp/src/bin/spi.rs b/tests/rp/src/bin/spi.rs new file mode 100644 index 000000000..3ce85a95c --- /dev/null +++ b/tests/rp/src/bin/spi.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{assert_eq, *}; +use embassy_executor::Spawner; +use embassy_rp::spi::{Blocking, Config, Spi}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let clk = p.PIN_2; + let mosi = p.PIN_3; + let miso = p.PIN_4; + + let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI0, clk, mosi, miso, Config::default()); + + let tx_buf = [1_u8, 2, 3, 4, 5, 6]; + let mut rx_buf = [0_u8; 6]; + spi.blocking_transfer(&mut rx_buf, &tx_buf).unwrap(); + assert_eq!(rx_buf, tx_buf); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/tests/rp/src/bin/spi_async.rs b/tests/rp/src/bin/spi_async.rs new file mode 100644 index 000000000..41c711f70 --- /dev/null +++ b/tests/rp/src/bin/spi_async.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{assert_eq, *}; +use embassy_executor::Spawner; +use embassy_rp::spi::{Async, Config, Spi}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let clk = p.PIN_2; + let mosi = p.PIN_3; + let miso = p.PIN_4; + + let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + + let tx_buf = [1_u8, 2, 3, 4, 5, 6]; + let mut rx_buf = [0_u8; 6]; + spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); + assert_eq!(rx_buf, tx_buf); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} From 27905f1be1e2404952b1a5c333d4a07f2e4c18f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Wed, 31 Aug 2022 19:54:38 +0200 Subject: [PATCH 08/14] Change DMA write/read to use raw pointers --- embassy-rp/src/dma.rs | 12 ++++++------ embassy-rp/src/spi.rs | 39 +++++++++++++++++++++++++++++---------- embassy-rp/src/uart.rs | 6 ++++-- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 75d7492e0..526c83822 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -40,14 +40,14 @@ pub(crate) unsafe fn init() { pub unsafe fn read<'a, C: Channel, W: Word>( ch: impl Peripheral

+ 'a, from: *const W, - to: &mut [W], + to: *mut W, + len: usize, dreq: u8, ) -> Transfer<'a, C> { - let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(to); copy_inner( ch, from as *const u32, - to_ptr as *mut u32, + to as *mut u32, len, W::size(), false, @@ -58,14 +58,14 @@ pub unsafe fn read<'a, C: Channel, W: Word>( pub unsafe fn write<'a, C: Channel, W: Word>( ch: impl Peripheral

+ 'a, - from: &[W], + from: *const W, to: *mut W, + len: usize, dreq: u8, ) -> Transfer<'a, C> { - let (from_ptr, len) = crate::dma::slice_ptr_parts(from); copy_inner( ch, - from_ptr as *const u32, + from as *const u32, to as *mut u32, len, W::size(), diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 6f68777b2..720aad0e5 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -285,6 +285,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> { } pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { + let (from_ptr, len) = crate::dma::slice_ptr_parts(buffer); let ch = self.tx_dma.as_mut().unwrap(); let transfer = unsafe { self.inner.regs().dmacr().modify(|reg| { @@ -292,13 +293,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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) + crate::dma::write(ch, from_ptr as *const u32, self.inner.regs().dr().ptr() as *mut _, len, T::TX_DREQ) }; transfer.await; Ok(()) } pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(buffer); let ch = self.rx_dma.as_mut().unwrap(); let transfer = unsafe { self.inner.regs().dmacr().modify(|reg| { @@ -306,13 +308,24 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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) + crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, to_ptr as *mut u32, len, T::RX_DREQ) }; transfer.await; Ok(()) } pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> { + self.transfer_inner(rx_buffer, tx_buffer).await + } + + pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { + self.transfer_inner(words, words).await + } + + async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> { + let (from_ptr, from_len) = crate::dma::slice_ptr_parts(tx_ptr); + let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); + assert_eq!(from_len, to_len); let tx_ch = self.tx_dma.as_mut().unwrap(); let tx_transfer = unsafe { self.inner.regs().dmacr().modify(|reg| { @@ -320,7 +333,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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) + crate::dma::write( + tx_ch, + from_ptr as *const u32, + self.inner.regs().dr().ptr() as *mut _, + from_len, + T::TX_DREQ, + ) }; let rx_ch = self.rx_dma.as_mut().unwrap(); let rx_transfer = unsafe { @@ -329,17 +348,17 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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) + crate::dma::read( + rx_ch, + self.inner.regs().dr().ptr() as *const _, + to_ptr as *mut u32, + to_len, + T::RX_DREQ, + ) }; join(tx_transfer, rx_transfer).await; Ok(()) } - - pub async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { - let (ptr, len) = crate::dma::slice_ptr_parts(words); - let tx_buffer = unsafe { core::slice::from_raw_parts(ptr as *const _, len) }; - self.transfer(words, tx_buffer).await - } } mod sealed { diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs index 987b716b4..f8a10bd9d 100644 --- a/embassy-rp/src/uart.rs +++ b/embassy-rp/src/uart.rs @@ -120,6 +120,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { impl<'d, T: Instance> UartTx<'d, T, Async> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { + let (from_ptr, len) = crate::dma::slice_ptr_parts(buffer); let ch = self.tx_dma.as_mut().unwrap(); let transfer = unsafe { T::regs().uartdmacr().modify(|reg| { @@ -127,7 +128,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> { }); // 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, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) + crate::dma::write(ch, from_ptr as *const u32, T::regs().uartdr().ptr() as *mut _, len, T::TX_DREQ) }; transfer.await; Ok(()) @@ -173,6 +174,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { impl<'d, T: Instance> UartRx<'d, T, Async> { pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(buffer); let ch = self.rx_dma.as_mut().unwrap(); let transfer = unsafe { T::regs().uartdmacr().modify(|reg| { @@ -180,7 +182,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { }); // 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, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) + crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, to_ptr as *mut u32, len, T::RX_DREQ) }; transfer.await; Ok(()) From 3fce6ec649953fac52b731ea0aa7587ed60e55c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Wed, 31 Aug 2022 21:54:42 +0200 Subject: [PATCH 09/14] Rearrange new:s --- embassy-rp/src/spi.rs | 176 ++++++++++++++++++++++++++--------------- embassy-rp/src/uart.rs | 16 +++- 2 files changed, 128 insertions(+), 64 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 720aad0e5..9bf6a9119 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -65,66 +65,6 @@ fn calc_prescs(freq: u32) -> (u8, u8) { } impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { - pub fn new_blocking( - inner: impl Peripheral

+ 'd, - clk: impl Peripheral

+ 'd> + 'd, - mosi: impl Peripheral

+ 'd> + 'd, - miso: impl Peripheral

+ 'd> + 'd, - config: Config, - ) -> Self { - into_ref!(clk, mosi, miso); - Self::new_inner( - inner, - None, - None, - Some(clk.map_into()), - Some(mosi.map_into()), - Some(miso.map_into()), - None, - config, - ) - } - - pub fn new_txonly( - inner: impl Peripheral

+ 'd, - tx_dma: Option>, - clk: impl Peripheral

+ 'd> + 'd, - mosi: impl Peripheral

+ 'd> + 'd, - config: Config, - ) -> Self { - into_ref!(clk, mosi); - Self::new_inner( - inner, - tx_dma, - None, - Some(clk.map_into()), - Some(mosi.map_into()), - None, - None, - config, - ) - } - - pub fn new_rxonly( - inner: impl Peripheral

+ 'd, - rx_dma: Option>, - clk: impl Peripheral

+ 'd> + 'd, - miso: impl Peripheral

+ 'd> + 'd, - config: Config, - ) -> Self { - into_ref!(clk, miso); - Self::new_inner( - inner, - None, - rx_dma, - Some(clk.map_into()), - None, - Some(miso.map_into()), - None, - config, - ) - } - fn new_inner( inner: impl Peripheral

+ 'd, tx_dma: Option>, @@ -261,6 +201,66 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { } } +impl<'d, T: Instance> Spi<'d, T, Blocking> { + pub fn new_blocking( + inner: impl Peripheral

+ 'd, + clk: impl Peripheral

+ 'd> + 'd, + mosi: impl Peripheral

+ 'd> + 'd, + miso: impl Peripheral

+ 'd> + 'd, + config: Config, + ) -> Self { + into_ref!(clk, mosi, miso); + Self::new_inner( + inner, + None, + None, + Some(clk.map_into()), + Some(mosi.map_into()), + Some(miso.map_into()), + None, + config, + ) + } + + pub fn new_blocking_txonly( + inner: impl Peripheral

+ 'd, + clk: impl Peripheral

+ 'd> + 'd, + mosi: impl Peripheral

+ 'd> + 'd, + config: Config, + ) -> Self { + into_ref!(clk, mosi); + Self::new_inner( + inner, + None, + None, + Some(clk.map_into()), + Some(mosi.map_into()), + None, + None, + config, + ) + } + + pub fn new_blocking_rxonly( + inner: impl Peripheral

+ 'd, + clk: impl Peripheral

+ 'd> + 'd, + miso: impl Peripheral

+ 'd> + 'd, + config: Config, + ) -> Self { + into_ref!(clk, miso); + Self::new_inner( + inner, + None, + None, + Some(clk.map_into()), + None, + Some(miso.map_into()), + None, + config, + ) + } +} + impl<'d, T: Instance> Spi<'d, T, Async> { pub fn new( inner: impl Peripheral

+ 'd, @@ -284,6 +284,46 @@ impl<'d, T: Instance> Spi<'d, T, Async> { ) } + pub fn new_txonly( + inner: impl Peripheral

+ 'd, + tx_dma: impl Peripheral

+ 'd, + clk: impl Peripheral

+ 'd> + 'd, + mosi: impl Peripheral

+ 'd> + 'd, + config: Config, + ) -> Self { + into_ref!(tx_dma, clk, mosi); + Self::new_inner( + inner, + Some(tx_dma.map_into()), + None, + Some(clk.map_into()), + Some(mosi.map_into()), + None, + None, + config, + ) + } + + pub fn new_rxonly( + inner: impl Peripheral

+ 'd, + rx_dma: impl Peripheral

+ 'd, + clk: impl Peripheral

+ 'd> + 'd, + miso: impl Peripheral

+ 'd> + 'd, + config: Config, + ) -> Self { + into_ref!(rx_dma, clk, miso); + Self::new_inner( + inner, + None, + Some(rx_dma.map_into()), + Some(clk.map_into()), + None, + Some(miso.map_into()), + None, + config, + ) + } + pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { let (from_ptr, len) = crate::dma::slice_ptr_parts(buffer); let ch = self.tx_dma.as_mut().unwrap(); @@ -293,7 +333,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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, from_ptr as *const u32, self.inner.regs().dr().ptr() as *mut _, len, T::TX_DREQ) + crate::dma::write( + ch, + from_ptr as *const u32, + self.inner.regs().dr().ptr() as *mut _, + len, + T::TX_DREQ, + ) }; transfer.await; Ok(()) @@ -308,7 +354,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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 _, to_ptr as *mut u32, len, T::RX_DREQ) + crate::dma::read( + ch, + self.inner.regs().dr().ptr() as *const _, + to_ptr as *mut u32, + len, + T::RX_DREQ, + ) }; transfer.await; Ok(()) diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs index f8a10bd9d..87d5fbd46 100644 --- a/embassy-rp/src/uart.rs +++ b/embassy-rp/src/uart.rs @@ -128,7 +128,13 @@ impl<'d, T: Instance> UartTx<'d, T, Async> { }); // 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, from_ptr as *const u32, T::regs().uartdr().ptr() as *mut _, len, T::TX_DREQ) + crate::dma::write( + ch, + from_ptr as *const u32, + T::regs().uartdr().ptr() as *mut _, + len, + T::TX_DREQ, + ) }; transfer.await; Ok(()) @@ -182,7 +188,13 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { }); // 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, T::regs().uartdr().ptr() as *const _, to_ptr as *mut u32, len, T::RX_DREQ) + crate::dma::read( + ch, + T::regs().uartdr().ptr() as *const _, + to_ptr as *mut u32, + len, + T::RX_DREQ, + ) }; transfer.await; Ok(()) From b934f3f12e0414ac92ce812b73aca44d0f47a5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Wed, 31 Aug 2022 22:03:34 +0200 Subject: [PATCH 10/14] Remove cfg_if --- embassy-rp/src/spi.rs | 77 ++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 9bf6a9119..cd40a4a31 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -556,51 +556,46 @@ mod eh1 { } } -cfg_if::cfg_if! { - if #[cfg(all(feature = "unstable-traits", feature = "nightly"))] { - use core::future::Future; - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Async> { - type FlushFuture<'a> = impl Future> + 'a where Self: 'a; +#[cfg(all(feature = "unstable-traits", feature = "nightly"))] +mod eha { + use super::*; + use core::future::Future; - fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { - async { Ok(()) } - } + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Async> { + type FlushFuture<'a> = impl Future> + 'a where Self: 'a; + + fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { + async { Ok(()) } + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite for Spi<'d, T, Async> { + type WriteFuture<'a> = impl Future> + 'a where Self: 'a; + + fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { + self.write(data) + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead for Spi<'d, T, Async> { + type ReadFuture<'a> = impl Future> + 'a where Self: 'a; + + fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { + self.read(data) + } + } + + impl<'d, T: Instance> embedded_hal_async::spi::SpiBus for Spi<'d, T, Async> { + type TransferFuture<'a> = impl Future> + 'a where Self: 'a; + + fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> { + self.transfer(rx, tx) } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite - for Spi<'d, T, Async> - { - type WriteFuture<'a> = impl Future> + 'a where Self: 'a; + type TransferInPlaceFuture<'a> = impl Future> + 'a where Self: 'a; - fn write<'a>(&'a mut self, data: &'a [u8]) -> Self::WriteFuture<'a> { - self.write(data) - } - } - - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead - for Spi<'d, T, Async> - { - type ReadFuture<'a> = impl Future> + 'a where Self: 'a; - - fn read<'a>(&'a mut self, data: &'a mut [u8]) -> Self::ReadFuture<'a> { - self.read(data) - } - } - - impl<'d, T: Instance> embedded_hal_async::spi::SpiBus - for Spi<'d, T, Async> - { - type TransferFuture<'a> = impl Future> + 'a where Self: 'a; - - fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Self::TransferFuture<'a> { - self.transfer(rx, tx) - } - - type TransferInPlaceFuture<'a> = impl Future> + 'a where Self: 'a; - - fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Self::TransferInPlaceFuture<'a> { - self.transfer_in_place(words) - } + fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Self::TransferInPlaceFuture<'a> { + self.transfer_in_place(words) } } } From e2181cb4396710c8dfef5d06ee5c498510524ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Wed, 31 Aug 2022 22:07:03 +0200 Subject: [PATCH 11/14] rustfmt --- embassy-rp/src/spi.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index cd40a4a31..8ae1c8b03 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -558,9 +558,10 @@ mod eh1 { #[cfg(all(feature = "unstable-traits", feature = "nightly"))] mod eha { - use super::*; use core::future::Future; + use super::*; + impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Async> { type FlushFuture<'a> = impl Future> + 'a where Self: 'a; From 71c130488b465012d1cb076deb182c5946c011d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Wed, 31 Aug 2022 22:12:14 +0200 Subject: [PATCH 12/14] Reorder args --- embassy-rp/src/spi.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 8ae1c8b03..c5d9647db 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -67,12 +67,12 @@ fn calc_prescs(freq: u32) -> (u8, u8) { impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { fn new_inner( inner: impl Peripheral

+ 'd, - tx_dma: Option>, - rx_dma: Option>, clk: Option>, mosi: Option>, miso: Option>, cs: Option>, + tx_dma: Option>, + rx_dma: Option>, config: Config, ) -> Self { into_ref!(inner); @@ -212,12 +212,12 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> { into_ref!(clk, mosi, miso); Self::new_inner( inner, - None, - None, Some(clk.map_into()), Some(mosi.map_into()), Some(miso.map_into()), None, + None, + None, config, ) } @@ -231,12 +231,12 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> { into_ref!(clk, mosi); Self::new_inner( inner, - None, - None, Some(clk.map_into()), Some(mosi.map_into()), None, None, + None, + None, config, ) } @@ -250,12 +250,12 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> { into_ref!(clk, miso); Self::new_inner( inner, - None, - None, Some(clk.map_into()), None, Some(miso.map_into()), None, + None, + None, config, ) } @@ -274,52 +274,52 @@ impl<'d, T: Instance> Spi<'d, T, Async> { 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, + Some(tx_dma.map_into()), + Some(rx_dma.map_into()), config, ) } pub fn new_txonly( inner: impl Peripheral

+ 'd, - tx_dma: impl Peripheral

+ 'd, clk: impl Peripheral

+ 'd> + 'd, mosi: impl Peripheral

+ 'd> + 'd, + tx_dma: impl Peripheral

+ 'd, config: Config, ) -> Self { into_ref!(tx_dma, clk, mosi); Self::new_inner( inner, - Some(tx_dma.map_into()), - None, Some(clk.map_into()), Some(mosi.map_into()), None, None, + Some(tx_dma.map_into()), + None, config, ) } pub fn new_rxonly( inner: impl Peripheral

+ 'd, - rx_dma: impl Peripheral

+ 'd, clk: impl Peripheral

+ 'd> + 'd, miso: impl Peripheral

+ 'd> + 'd, + rx_dma: impl Peripheral

+ 'd, config: Config, ) -> Self { into_ref!(rx_dma, clk, miso); Self::new_inner( inner, - None, - Some(rx_dma.map_into()), Some(clk.map_into()), None, Some(miso.map_into()), None, + None, + Some(rx_dma.map_into()), config, ) } From 9ff5c507741cfadc8a1fc125a353d8438433494f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Wed, 31 Aug 2022 22:28:47 +0200 Subject: [PATCH 13/14] Cleanup examples --- examples/rp/src/bin/spi.rs | 4 ++-- examples/rp/src/bin/spi_async.rs | 4 ++-- tests/rp/src/bin/spi.rs | 4 ++-- tests/rp/src/bin/spi_async.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index e50297ae4..a830a17a2 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::{Blocking, Spi}; +use embassy_rp::spi::Spi; use embassy_rp::{gpio, spi}; use gpio::{Level, Output}; use {defmt_rtt as _, panic_probe as _}; @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { // create SPI let mut config = spi::Config::default(); config.frequency = 2_000_000; - let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); + let mut spi = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); // Configure CS let mut cs = Output::new(touch_cs, Level::Low); diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index b2df0dd11..671a9caaf 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::spi::{Async, Config, Spi}; +use embassy_rp::spi::{Config, Spi}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_11; let clk = p.PIN_10; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + let mut spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); loop { let tx_buf = [1_u8, 2, 3, 4, 5, 6]; diff --git a/tests/rp/src/bin/spi.rs b/tests/rp/src/bin/spi.rs index 3ce85a95c..478d62ee0 100644 --- a/tests/rp/src/bin/spi.rs +++ b/tests/rp/src/bin/spi.rs @@ -4,7 +4,7 @@ use defmt::{assert_eq, *}; use embassy_executor::Spawner; -use embassy_rp::spi::{Blocking, Config, Spi}; +use embassy_rp::spi::{Config, Spi}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_3; let miso = p.PIN_4; - let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI0, clk, mosi, miso, Config::default()); + let mut spi = Spi::new_blocking(p.SPI0, clk, mosi, miso, Config::default()); let tx_buf = [1_u8, 2, 3, 4, 5, 6]; let mut rx_buf = [0_u8; 6]; diff --git a/tests/rp/src/bin/spi_async.rs b/tests/rp/src/bin/spi_async.rs index 41c711f70..6c85ef60a 100644 --- a/tests/rp/src/bin/spi_async.rs +++ b/tests/rp/src/bin/spi_async.rs @@ -4,7 +4,7 @@ use defmt::{assert_eq, *}; use embassy_executor::Spawner; -use embassy_rp::spi::{Async, Config, Spi}; +use embassy_rp::spi::{Config, Spi}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let mosi = p.PIN_3; let miso = p.PIN_4; - let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); + let mut spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default()); let tx_buf = [1_u8, 2, 3, 4, 5, 6]; let mut rx_buf = [0_u8; 6]; From efe456ab1414a19a4e0469a6bb7686a04029a44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Als=C3=A9r?= Date: Thu, 1 Sep 2022 12:00:11 +0200 Subject: [PATCH 14/14] Fix dma --- embassy-rp/src/dma.rs | 12 ++++++------ embassy-rp/src/spi.rs | 38 ++++++-------------------------------- embassy-rp/src/uart.rs | 18 ++---------------- 3 files changed, 14 insertions(+), 54 deletions(-) diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 526c83822..acf338225 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -40,14 +40,14 @@ pub(crate) unsafe fn init() { pub unsafe fn read<'a, C: Channel, W: Word>( ch: impl Peripheral

+ 'a, from: *const W, - to: *mut W, - len: usize, + to: *mut [W], dreq: u8, ) -> Transfer<'a, C> { + let (to_ptr, len) = crate::dma::slice_ptr_parts(to); copy_inner( ch, from as *const u32, - to as *mut u32, + to_ptr as *mut u32, len, W::size(), false, @@ -58,14 +58,14 @@ pub unsafe fn read<'a, C: Channel, W: Word>( pub unsafe fn write<'a, C: Channel, W: Word>( ch: impl Peripheral

+ 'a, - from: *const W, + from: *const [W], to: *mut W, - len: usize, dreq: u8, ) -> Transfer<'a, C> { + let (from_ptr, len) = crate::dma::slice_ptr_parts(from); copy_inner( ch, - from as *const u32, + from_ptr as *const u32, to as *mut u32, len, W::size(), diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index c5d9647db..74f0b04de 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -325,7 +325,6 @@ impl<'d, T: Instance> Spi<'d, T, Async> { } pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { - let (from_ptr, len) = crate::dma::slice_ptr_parts(buffer); let ch = self.tx_dma.as_mut().unwrap(); let transfer = unsafe { self.inner.regs().dmacr().modify(|reg| { @@ -333,20 +332,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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, - from_ptr as *const u32, - self.inner.regs().dr().ptr() as *mut _, - len, - T::TX_DREQ, - ) + 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 (to_ptr, len) = crate::dma::slice_ptr_parts_mut(buffer); let ch = self.rx_dma.as_mut().unwrap(); let transfer = unsafe { self.inner.regs().dmacr().modify(|reg| { @@ -354,13 +346,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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 _, - to_ptr as *mut u32, - len, - T::RX_DREQ, - ) + crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) }; transfer.await; Ok(()) @@ -375,8 +361,8 @@ impl<'d, T: Instance> Spi<'d, T, Async> { } async fn transfer_inner(&mut self, rx_ptr: *mut [u8], tx_ptr: *const [u8]) -> Result<(), Error> { - let (from_ptr, from_len) = crate::dma::slice_ptr_parts(tx_ptr); - let (to_ptr, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); + let (_, from_len) = crate::dma::slice_ptr_parts(tx_ptr); + let (_, to_len) = crate::dma::slice_ptr_parts_mut(rx_ptr); assert_eq!(from_len, to_len); let tx_ch = self.tx_dma.as_mut().unwrap(); let tx_transfer = unsafe { @@ -385,13 +371,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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, - from_ptr as *const u32, - self.inner.regs().dr().ptr() as *mut _, - from_len, - T::TX_DREQ, - ) + crate::dma::write(tx_ch, tx_ptr, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) }; let rx_ch = self.rx_dma.as_mut().unwrap(); let rx_transfer = unsafe { @@ -400,13 +380,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> { }); // 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 _, - to_ptr as *mut u32, - to_len, - T::RX_DREQ, - ) + crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) }; join(tx_transfer, rx_transfer).await; Ok(()) diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart.rs index 87d5fbd46..987b716b4 100644 --- a/embassy-rp/src/uart.rs +++ b/embassy-rp/src/uart.rs @@ -120,7 +120,6 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { impl<'d, T: Instance> UartTx<'d, T, Async> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { - let (from_ptr, len) = crate::dma::slice_ptr_parts(buffer); let ch = self.tx_dma.as_mut().unwrap(); let transfer = unsafe { T::regs().uartdmacr().modify(|reg| { @@ -128,13 +127,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> { }); // 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, - from_ptr as *const u32, - T::regs().uartdr().ptr() as *mut _, - len, - T::TX_DREQ, - ) + crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) }; transfer.await; Ok(()) @@ -180,7 +173,6 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { impl<'d, T: Instance> UartRx<'d, T, Async> { pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - let (to_ptr, len) = crate::dma::slice_ptr_parts_mut(buffer); let ch = self.rx_dma.as_mut().unwrap(); let transfer = unsafe { T::regs().uartdmacr().modify(|reg| { @@ -188,13 +180,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { }); // 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, - T::regs().uartdr().ptr() as *const _, - to_ptr as *mut u32, - len, - T::RX_DREQ, - ) + crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) }; transfer.await; Ok(())