diff options
| author | Henrik Alsér <[email protected]> | 2022-08-29 00:30:50 +0200 |
|---|---|---|
| committer | Henrik Alsér <[email protected]> | 2022-09-01 15:12:43 +0200 |
| commit | e7d4bf258a8cc30d650d7babc80c79a672052549 (patch) | |
| tree | bac5bd9c3c73251559c7ff4e1eb43314382f6789 /embassy-rp | |
| parent | 838f3065ea1ecc68f4db8ceb2fea0026df4f6ff8 (diff) | |
dma
Diffstat (limited to 'embassy-rp')
| -rw-r--r-- | embassy-rp/src/spi.rs | 91 |
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 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 1 | use embassy_embedded_hal::SetConfig; | 3 | use embassy_embedded_hal::SetConfig; |
| 2 | use embassy_hal_common::{into_ref, PeripheralRef}; | 4 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 3 | pub use embedded_hal_02::spi::{Phase, Polarity}; | 5 | pub use embedded_hal_02::spi::{Phase, Polarity}; |
| 4 | 6 | ||
| 7 | use crate::dma::{AnyChannel, Channel}; | ||
| 5 | use crate::gpio::sealed::Pin as _; | 8 | use crate::gpio::sealed::Pin as _; |
| 6 | use crate::gpio::{AnyPin, Pin as GpioPin}; | 9 | use crate::gpio::{AnyPin, Pin as GpioPin}; |
| 7 | use crate::{pac, peripherals, Peripheral}; | 10 | use crate::{pac, peripherals, Peripheral}; |
| @@ -30,8 +33,11 @@ impl Default for Config { | |||
| 30 | } | 33 | } |
| 31 | } | 34 | } |
| 32 | 35 | ||
| 33 | pub struct Spi<'d, T: Instance> { | 36 | pub 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 | ||
| 37 | fn div_roundup(a: u32, b: u32) -> u32 { | 43 | fn 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 | ||
| 60 | impl<'d, T: Instance> Spi<'d, T> { | 66 | impl<'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> { | |||
| 228 | mod sealed { | 265 | mod 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 | ||
| 278 | pub trait Mode: sealed::Mode {} | ||
| 236 | pub trait Instance: sealed::Instance {} | 279 | pub trait Instance: sealed::Instance {} |
| 237 | 280 | ||
| 238 | macro_rules! impl_instance { | 281 | macro_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 | ||
| 249 | impl_instance!(SPI0, Spi0); | 295 | impl_instance!(SPI0, Spi0, 16, 17); |
| 250 | impl_instance!(SPI1, Spi1); | 296 | impl_instance!(SPI1, Spi1, 18, 19); |
| 251 | 297 | ||
| 252 | pub trait ClkPin<T: Instance>: GpioPin {} | 298 | pub trait ClkPin<T: Instance>: GpioPin {} |
| 253 | pub trait CsPin<T: Instance>: GpioPin {} | 299 | pub trait CsPin<T: Instance>: GpioPin {} |
| @@ -281,12 +327,25 @@ impl_pin!(PIN_17, SPI0, CsPin); | |||
| 281 | impl_pin!(PIN_18, SPI0, ClkPin); | 327 | impl_pin!(PIN_18, SPI0, ClkPin); |
| 282 | impl_pin!(PIN_19, SPI0, MosiPin); | 328 | impl_pin!(PIN_19, SPI0, MosiPin); |
| 283 | 329 | ||
| 330 | macro_rules! impl_mode { | ||
| 331 | ($name:ident) => { | ||
| 332 | impl sealed::Mode for $name {} | ||
| 333 | impl Mode for $name {} | ||
| 334 | }; | ||
| 335 | } | ||
| 336 | |||
| 337 | pub struct Blocking; | ||
| 338 | pub struct Async; | ||
| 339 | |||
| 340 | impl_mode!(Blocking); | ||
| 341 | impl_mode!(Async); | ||
| 342 | |||
| 284 | // ==================== | 343 | // ==================== |
| 285 | 344 | ||
| 286 | mod eh02 { | 345 | mod 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 | ||
| 349 | impl<'d, T: Instance> SetConfig for Spi<'d, T> { | 408 | impl<'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(); |
