diff options
| -rw-r--r-- | embassy-rp/src/spi.rs | 84 | ||||
| -rw-r--r-- | examples/rp/src/bin/spi.rs | 4 | ||||
| -rw-r--r-- | examples/rp/src/bin/spi_async.rs | 31 |
3 files changed, 112 insertions, 7 deletions
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; | |||
| 3 | use embassy_embedded_hal::SetConfig; | 3 | use embassy_embedded_hal::SetConfig; |
| 4 | use embassy_hal_common::{into_ref, PeripheralRef}; | 4 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 5 | pub use embedded_hal_02::spi::{Phase, Polarity}; | 5 | pub use embedded_hal_02::spi::{Phase, Polarity}; |
| 6 | use futures::future::join; | ||
| 6 | 7 | ||
| 7 | use crate::dma::{AnyChannel, Channel}; | 8 | use crate::dma::{AnyChannel, Channel}; |
| 8 | use crate::gpio::sealed::Pin as _; | 9 | use crate::gpio::sealed::Pin as _; |
| @@ -64,10 +65,8 @@ fn calc_prescs(freq: u32) -> (u8, u8) { | |||
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { | 67 | impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { |
| 67 | pub fn new( | 68 | pub fn new_blocking( |
| 68 | inner: impl Peripheral<P = T> + 'd, | 69 | inner: impl Peripheral<P = T> + 'd, |
| 69 | tx_dma: Option<PeripheralRef<'d, AnyChannel>>, | ||
| 70 | rx_dma: Option<PeripheralRef<'d, AnyChannel>>, | ||
| 71 | clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, | 70 | clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, |
| 72 | mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, | 71 | mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, |
| 73 | miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, | 72 | miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, |
| @@ -76,8 +75,8 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { | |||
| 76 | into_ref!(clk, mosi, miso); | 75 | into_ref!(clk, mosi, miso); |
| 77 | Self::new_inner( | 76 | Self::new_inner( |
| 78 | inner, | 77 | inner, |
| 79 | tx_dma, | 78 | None, |
| 80 | rx_dma, | 79 | None, |
| 81 | Some(clk.map_into()), | 80 | Some(clk.map_into()), |
| 82 | Some(mosi.map_into()), | 81 | Some(mosi.map_into()), |
| 83 | Some(miso.map_into()), | 82 | Some(miso.map_into()), |
| @@ -262,6 +261,81 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { | |||
| 262 | } | 261 | } |
| 263 | } | 262 | } |
| 264 | 263 | ||
| 264 | impl<'d, T: Instance> Spi<'d, T, Async> { | ||
| 265 | pub fn new( | ||
| 266 | inner: impl Peripheral<P = T> + 'd, | ||
| 267 | tx_dma: impl Peripheral<P = impl Channel> + 'd, | ||
| 268 | rx_dma: impl Peripheral<P = impl Channel> + 'd, | ||
| 269 | clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, | ||
| 270 | mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, | ||
| 271 | miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, | ||
| 272 | config: Config, | ||
| 273 | ) -> Self { | ||
| 274 | into_ref!(tx_dma, rx_dma, clk, mosi, miso); | ||
| 275 | Self::new_inner( | ||
| 276 | inner, | ||
| 277 | Some(tx_dma.map_into()), | ||
| 278 | Some(rx_dma.map_into()), | ||
| 279 | Some(clk.map_into()), | ||
| 280 | Some(mosi.map_into()), | ||
| 281 | Some(miso.map_into()), | ||
| 282 | None, | ||
| 283 | config, | ||
| 284 | ) | ||
| 285 | } | ||
| 286 | |||
| 287 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { | ||
| 288 | let ch = self.tx_dma.as_mut().unwrap(); | ||
| 289 | let transfer = unsafe { | ||
| 290 | self.inner.regs().dmacr().modify(|reg| { | ||
| 291 | reg.set_txdmae(true); | ||
| 292 | }); | ||
| 293 | // If we don't assign future to a variable, the data register pointer | ||
| 294 | // is held across an await and makes the future non-Send. | ||
| 295 | crate::dma::write(ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) | ||
| 296 | }; | ||
| 297 | transfer.await; | ||
| 298 | Ok(()) | ||
| 299 | } | ||
| 300 | |||
| 301 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 302 | let ch = self.rx_dma.as_mut().unwrap(); | ||
| 303 | let transfer = unsafe { | ||
| 304 | self.inner.regs().dmacr().modify(|reg| { | ||
| 305 | reg.set_rxdmae(true); | ||
| 306 | }); | ||
| 307 | // If we don't assign future to a variable, the data register pointer | ||
| 308 | // is held across an await and makes the future non-Send. | ||
| 309 | crate::dma::read(ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) | ||
| 310 | }; | ||
| 311 | transfer.await; | ||
| 312 | Ok(()) | ||
| 313 | } | ||
| 314 | |||
| 315 | pub async fn transfer(&mut self, rx_buffer: &mut [u8], tx_buffer: &[u8]) -> Result<(), Error> { | ||
| 316 | let tx_ch = self.tx_dma.as_mut().unwrap(); | ||
| 317 | let tx_transfer = unsafe { | ||
| 318 | self.inner.regs().dmacr().modify(|reg| { | ||
| 319 | reg.set_txdmae(true); | ||
| 320 | }); | ||
| 321 | // If we don't assign future to a variable, the data register pointer | ||
| 322 | // is held across an await and makes the future non-Send. | ||
| 323 | crate::dma::write(tx_ch, tx_buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) | ||
| 324 | }; | ||
| 325 | let rx_ch = self.rx_dma.as_mut().unwrap(); | ||
| 326 | let rx_transfer = unsafe { | ||
| 327 | self.inner.regs().dmacr().modify(|reg| { | ||
| 328 | reg.set_rxdmae(true); | ||
| 329 | }); | ||
| 330 | // If we don't assign future to a variable, the data register pointer | ||
| 331 | // is held across an await and makes the future non-Send. | ||
| 332 | crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_buffer, T::RX_DREQ) | ||
| 333 | }; | ||
| 334 | join(tx_transfer, rx_transfer).await; | ||
| 335 | Ok(()) | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 265 | mod sealed { | 339 | mod sealed { |
| 266 | use super::*; | 340 | use super::*; |
| 267 | 341 | ||
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 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::spi::Spi; | 7 | use embassy_rp::spi::{Blocking, Spi}; |
| 8 | use embassy_rp::{gpio, spi}; | 8 | use embassy_rp::{gpio, spi}; |
| 9 | use gpio::{Level, Output}; | 9 | use gpio::{Level, Output}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 24 | // create SPI | 24 | // create SPI |
| 25 | let mut config = spi::Config::default(); | 25 | let mut config = spi::Config::default(); |
| 26 | config.frequency = 2_000_000; | 26 | config.frequency = 2_000_000; |
| 27 | let mut spi = Spi::new(p.SPI1, clk, mosi, miso, config); | 27 | let mut spi: Spi<'_, _, Blocking> = Spi::new_blocking(p.SPI1, clk, mosi, miso, config); |
| 28 | 28 | ||
| 29 | // Configure CS | 29 | // Configure CS |
| 30 | let mut cs = Output::new(touch_cs, Level::Low); | 30 | 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 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_rp::spi::{Async, Spi}; | ||
| 8 | use embassy_rp::{gpio, spi}; | ||
| 9 | use embassy_time::{Duration, Timer}; | ||
| 10 | use gpio::{Level, Output}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | #[embassy_executor::main] | ||
| 14 | async fn main(_spawner: Spawner) { | ||
| 15 | let p = embassy_rp::init(Default::default()); | ||
| 16 | info!("Hello World!"); | ||
| 17 | |||
| 18 | let miso = p.PIN_12; | ||
| 19 | let mosi = p.PIN_11; | ||
| 20 | let clk = p.PIN_10; | ||
| 21 | |||
| 22 | let mut spi: Spi<'_, _, Async> = Spi::new(p.SPI1, p.DMA_CH0, p.DMA_CH1, clk, mosi, miso, spi::Config::default()); | ||
| 23 | |||
| 24 | loop { | ||
| 25 | let tx_buf = [1_u8, 2, 3, 4, 5, 6]; | ||
| 26 | let mut rx_buf = [0_u8; 6]; | ||
| 27 | spi.transfer(&mut rx_buf, &tx_buf).await.unwrap(); | ||
| 28 | info!("{:?}", rx_buf); | ||
| 29 | Timer::after(Duration::from_secs(1)).await; | ||
| 30 | } | ||
| 31 | } | ||
