aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp
diff options
context:
space:
mode:
authorHenrik Alsér <[email protected]>2022-08-29 00:30:50 +0200
committerHenrik Alsér <[email protected]>2022-09-01 15:12:43 +0200
commite7d4bf258a8cc30d650d7babc80c79a672052549 (patch)
treebac5bd9c3c73251559c7ff4e1eb43314382f6789 /embassy-rp
parent838f3065ea1ecc68f4db8ceb2fea0026df4f6ff8 (diff)
dma
Diffstat (limited to 'embassy-rp')
-rw-r--r--embassy-rp/src/spi.rs91
1 files 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 @@
1use core::marker::PhantomData;
2
1use embassy_embedded_hal::SetConfig; 3use embassy_embedded_hal::SetConfig;
2use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_common::{into_ref, PeripheralRef};
3pub use embedded_hal_02::spi::{Phase, Polarity}; 5pub use embedded_hal_02::spi::{Phase, Polarity};
4 6
7use crate::dma::{AnyChannel, Channel};
5use crate::gpio::sealed::Pin as _; 8use crate::gpio::sealed::Pin as _;
6use crate::gpio::{AnyPin, Pin as GpioPin}; 9use crate::gpio::{AnyPin, Pin as GpioPin};
7use crate::{pac, peripherals, Peripheral}; 10use crate::{pac, peripherals, Peripheral};
@@ -30,8 +33,11 @@ impl Default for Config {
30 } 33 }
31} 34}
32 35
33pub struct Spi<'d, T: Instance> { 36pub struct Spi<'d, T: Instance, M: Mode> {
34 inner: PeripheralRef<'d, T>, 37 inner: PeripheralRef<'d, T>,
38 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
39 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
40 phantom: PhantomData<(&'d mut T, M)>,
35} 41}
36 42
37fn div_roundup(a: u32, b: u32) -> u32 { 43fn div_roundup(a: u32, b: u32) -> u32 {
@@ -57,9 +63,11 @@ fn calc_prescs(freq: u32) -> (u8, u8) {
57 ((presc * 2) as u8, (postdiv - 1) as u8) 63 ((presc * 2) as u8, (postdiv - 1) as u8)
58} 64}
59 65
60impl<'d, T: Instance> Spi<'d, T> { 66impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
61 pub fn new( 67 pub fn new(
62 inner: impl Peripheral<P = T> + 'd, 68 inner: impl Peripheral<P = T> + 'd,
69 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
70 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
63 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 71 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
64 mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, 72 mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
65 miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, 73 miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
@@ -68,6 +76,8 @@ impl<'d, T: Instance> Spi<'d, T> {
68 into_ref!(clk, mosi, miso); 76 into_ref!(clk, mosi, miso);
69 Self::new_inner( 77 Self::new_inner(
70 inner, 78 inner,
79 tx_dma,
80 rx_dma,
71 Some(clk.map_into()), 81 Some(clk.map_into()),
72 Some(mosi.map_into()), 82 Some(mosi.map_into()),
73 Some(miso.map_into()), 83 Some(miso.map_into()),
@@ -78,26 +88,48 @@ impl<'d, T: Instance> Spi<'d, T> {
78 88
79 pub fn new_txonly( 89 pub fn new_txonly(
80 inner: impl Peripheral<P = T> + 'd, 90 inner: impl Peripheral<P = T> + 'd,
91 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
81 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 92 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
82 mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd, 93 mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
83 config: Config, 94 config: Config,
84 ) -> Self { 95 ) -> Self {
85 into_ref!(clk, mosi); 96 into_ref!(clk, mosi);
86 Self::new_inner(inner, Some(clk.map_into()), Some(mosi.map_into()), None, None, config) 97 Self::new_inner(
98 inner,
99 tx_dma,
100 None,
101 Some(clk.map_into()),
102 Some(mosi.map_into()),
103 None,
104 None,
105 config,
106 )
87 } 107 }
88 108
89 pub fn new_rxonly( 109 pub fn new_rxonly(
90 inner: impl Peripheral<P = T> + 'd, 110 inner: impl Peripheral<P = T> + 'd,
111 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
91 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd, 112 clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
92 miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd, 113 miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
93 config: Config, 114 config: Config,
94 ) -> Self { 115 ) -> Self {
95 into_ref!(clk, miso); 116 into_ref!(clk, miso);
96 Self::new_inner(inner, Some(clk.map_into()), None, Some(miso.map_into()), None, config) 117 Self::new_inner(
118 inner,
119 None,
120 rx_dma,
121 Some(clk.map_into()),
122 None,
123 Some(miso.map_into()),
124 None,
125 config,
126 )
97 } 127 }
98 128
99 fn new_inner( 129 fn new_inner(
100 inner: impl Peripheral<P = T> + 'd, 130 inner: impl Peripheral<P = T> + 'd,
131 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
132 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
101 clk: Option<PeripheralRef<'d, AnyPin>>, 133 clk: Option<PeripheralRef<'d, AnyPin>>,
102 mosi: Option<PeripheralRef<'d, AnyPin>>, 134 mosi: Option<PeripheralRef<'d, AnyPin>>,
103 miso: Option<PeripheralRef<'d, AnyPin>>, 135 miso: Option<PeripheralRef<'d, AnyPin>>,
@@ -134,7 +166,12 @@ impl<'d, T: Instance> Spi<'d, T> {
134 pin.io().ctrl().write(|w| w.set_funcsel(1)); 166 pin.io().ctrl().write(|w| w.set_funcsel(1));
135 } 167 }
136 } 168 }
137 Self { inner } 169 Self {
170 inner,
171 tx_dma,
172 rx_dma,
173 phantom: PhantomData,
174 }
138 } 175 }
139 176
140 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { 177 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
@@ -228,16 +265,25 @@ impl<'d, T: Instance> Spi<'d, T> {
228mod sealed { 265mod sealed {
229 use super::*; 266 use super::*;
230 267
268 pub trait Mode {}
269
231 pub trait Instance { 270 pub trait Instance {
271 const TX_DREQ: u8;
272 const RX_DREQ: u8;
273
232 fn regs(&self) -> pac::spi::Spi; 274 fn regs(&self) -> pac::spi::Spi;
233 } 275 }
234} 276}
235 277
278pub trait Mode: sealed::Mode {}
236pub trait Instance: sealed::Instance {} 279pub trait Instance: sealed::Instance {}
237 280
238macro_rules! impl_instance { 281macro_rules! impl_instance {
239 ($type:ident, $irq:ident) => { 282 ($type:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {
240 impl sealed::Instance for peripherals::$type { 283 impl sealed::Instance for peripherals::$type {
284 const TX_DREQ: u8 = $tx_dreq;
285 const RX_DREQ: u8 = $rx_dreq;
286
241 fn regs(&self) -> pac::spi::Spi { 287 fn regs(&self) -> pac::spi::Spi {
242 pac::$type 288 pac::$type
243 } 289 }
@@ -246,8 +292,8 @@ macro_rules! impl_instance {
246 }; 292 };
247} 293}
248 294
249impl_instance!(SPI0, Spi0); 295impl_instance!(SPI0, Spi0, 16, 17);
250impl_instance!(SPI1, Spi1); 296impl_instance!(SPI1, Spi1, 18, 19);
251 297
252pub trait ClkPin<T: Instance>: GpioPin {} 298pub trait ClkPin<T: Instance>: GpioPin {}
253pub trait CsPin<T: Instance>: GpioPin {} 299pub trait CsPin<T: Instance>: GpioPin {}
@@ -281,12 +327,25 @@ impl_pin!(PIN_17, SPI0, CsPin);
281impl_pin!(PIN_18, SPI0, ClkPin); 327impl_pin!(PIN_18, SPI0, ClkPin);
282impl_pin!(PIN_19, SPI0, MosiPin); 328impl_pin!(PIN_19, SPI0, MosiPin);
283 329
330macro_rules! impl_mode {
331 ($name:ident) => {
332 impl sealed::Mode for $name {}
333 impl Mode for $name {}
334 };
335}
336
337pub struct Blocking;
338pub struct Async;
339
340impl_mode!(Blocking);
341impl_mode!(Async);
342
284// ==================== 343// ====================
285 344
286mod eh02 { 345mod eh02 {
287 use super::*; 346 use super::*;
288 347
289 impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer<u8> for Spi<'d, T> { 348 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::spi::Transfer<u8> for Spi<'d, T, M> {
290 type Error = Error; 349 type Error = Error;
291 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { 350 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
292 self.blocking_transfer_in_place(words)?; 351 self.blocking_transfer_in_place(words)?;
@@ -294,7 +353,7 @@ mod eh02 {
294 } 353 }
295 } 354 }
296 355
297 impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write<u8> for Spi<'d, T> { 356 impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::spi::Write<u8> for Spi<'d, T, M> {
298 type Error = Error; 357 type Error = Error;
299 358
300 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { 359 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
@@ -313,29 +372,29 @@ mod eh1 {
313 } 372 }
314 } 373 }
315 374
316 impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spi<'d, T> { 375 impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::ErrorType for Spi<'d, T, M> {
317 type Error = Error; 376 type Error = Error;
318 } 377 }
319 378
320 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusFlush for Spi<'d, T> { 379 impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBusFlush for Spi<'d, T, M> {
321 fn flush(&mut self) -> Result<(), Self::Error> { 380 fn flush(&mut self) -> Result<(), Self::Error> {
322 Ok(()) 381 Ok(())
323 } 382 }
324 } 383 }
325 384
326 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusRead<u8> for Spi<'d, T> { 385 impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBusRead<u8> for Spi<'d, T, M> {
327 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { 386 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
328 self.blocking_transfer(words, &[]) 387 self.blocking_transfer(words, &[])
329 } 388 }
330 } 389 }
331 390
332 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBusWrite<u8> for Spi<'d, T> { 391 impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBusWrite<u8> for Spi<'d, T, M> {
333 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { 392 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
334 self.blocking_write(words) 393 self.blocking_write(words)
335 } 394 }
336 } 395 }
337 396
338 impl<'d, T: Instance> embedded_hal_1::spi::blocking::SpiBus<u8> for Spi<'d, T> { 397 impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::blocking::SpiBus<u8> for Spi<'d, T, M> {
339 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { 398 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
340 self.blocking_transfer(read, write) 399 self.blocking_transfer(read, write)
341 } 400 }
@@ -346,7 +405,7 @@ mod eh1 {
346 } 405 }
347} 406}
348 407
349impl<'d, T: Instance> SetConfig for Spi<'d, T> { 408impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> {
350 type Config = Config; 409 type Config = Config;
351 fn set_config(&mut self, config: &Self::Config) { 410 fn set_config(&mut self, config: &Self::Config) {
352 let p = self.inner.regs(); 411 let p = self.inner.regs();