aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/spi.rs84
-rw-r--r--examples/rp/src/bin/spi.rs4
-rw-r--r--examples/rp/src/bin/spi_async.rs31
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;
3use embassy_embedded_hal::SetConfig; 3use embassy_embedded_hal::SetConfig;
4use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_common::{into_ref, PeripheralRef};
5pub use embedded_hal_02::spi::{Phase, Polarity}; 5pub use embedded_hal_02::spi::{Phase, Polarity};
6use futures::future::join;
6 7
7use crate::dma::{AnyChannel, Channel}; 8use crate::dma::{AnyChannel, Channel};
8use crate::gpio::sealed::Pin as _; 9use crate::gpio::sealed::Pin as _;
@@ -64,10 +65,8 @@ fn calc_prescs(freq: u32) -> (u8, u8) {
64} 65}
65 66
66impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { 67impl<'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
264impl<'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
265mod sealed { 339mod 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
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::spi::Spi; 7use embassy_rp::spi::{Blocking, Spi};
8use embassy_rp::{gpio, spi}; 8use embassy_rp::{gpio, spi};
9use gpio::{Level, Output}; 9use gpio::{Level, Output};
10use {defmt_rtt as _, panic_probe as _}; 10use {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
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_rp::spi::{Async, Spi};
8use embassy_rp::{gpio, spi};
9use embassy_time::{Duration, Timer};
10use gpio::{Level, Output};
11use {defmt_rtt as _, panic_probe as _};
12
13#[embassy_executor::main]
14async 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}