diff options
| author | Cristian Milatinov <[email protected]> | 2025-07-09 20:35:01 -0400 |
|---|---|---|
| committer | Cristian Milatinov <[email protected]> | 2025-11-04 22:39:33 -0500 |
| commit | 141f826e10802a40ac1bca8fdcdfa3da821e0f28 (patch) | |
| tree | e289966bbdb69123a3e996330a0f0741d650e7fb | |
| parent | ff42c61dc6c0f870b4022aca52f3c45d992ae735 (diff) | |
feat: stm32 spi driver slave mode
Add SPI slave constructors
Fix SPI slave constructors
Fix embedded hal async trait
One more constructor fix
Set SSM bit in SPI driver according to CommunicationMode
Fix embedded_hal_async trait to be generic for both master and slave
Fix I2S driver to use async master SPI
Forgot import from spi mode
Fix CommunicationMode associated const conditionals
Duplicate doc for CommunicationMode const
Add missing nss argument
Fix existing SPI tests not compiling
Fix stm32h7rs examples not compiling
Fix failing stm32l4 example
Fix stm32h7 example
Fix stm32h7 spi_bdma example
Fix stm32h7 spi example
Fix stm32f4 example
docs: added entry in changelog.md
fix: spi_v3 vals mismatch + rise_fall_speed renamed to gpio_speed
fix: added spi_v6 conditional compilation feature
fix: use if_afio macro in slave constructors
fix: add missing trait bound
fix: if_afio for cs pin trait
fix: changelog message
fix: broken rebase
| -rw-r--r-- | embassy-stm32/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/i2s.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 147 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/eth_w5500.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/spi.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/spi_bdma.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/spi_dma.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7rs/src/bin/spi.rs | 2 | ||||
| -rw-r--r-- | examples/stm32h7rs/src/bin/spi_dma.rs | 2 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/spi.rs | 7 | ||||
| -rw-r--r-- | tests/stm32/src/bin/spi_dma.rs | 7 |
12 files changed, 145 insertions, 36 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index ee76a5d1b..2a7a89bc9 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md | |||
| @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 44 | - feat: Added RTC low-power support for STM32WLEx ([#4716](https://github.com/embassy-rs/embassy/pull/4716)) | 44 | - feat: Added RTC low-power support for STM32WLEx ([#4716](https://github.com/embassy-rs/embassy/pull/4716)) |
| 45 | - fix: Correct STM32WBA VREFBUFTRIM values | 45 | - fix: Correct STM32WBA VREFBUFTRIM values |
| 46 | - low_power: remove stop_with rtc and initialize in init if low-power feature enabled. | 46 | - low_power: remove stop_with rtc and initialize in init if low-power feature enabled. |
| 47 | - feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388)) | ||
| 47 | 48 | ||
| 48 | ## 0.4.0 - 2025-08-26 | 49 | ## 0.4.0 - 2025-08-26 |
| 49 | 50 | ||
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index db22cfa11..df077a3ae 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs | |||
| @@ -7,6 +7,7 @@ use crate::Peri; | |||
| 7 | use crate::dma::{ChannelAndRequest, ReadableRingBuffer, TransferOptions, WritableRingBuffer, ringbuffer}; | 7 | use crate::dma::{ChannelAndRequest, ReadableRingBuffer, TransferOptions, WritableRingBuffer, ringbuffer}; |
| 8 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | 8 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; |
| 9 | use crate::mode::Async; | 9 | use crate::mode::Async; |
| 10 | use crate::spi::mode::Master; | ||
| 10 | use crate::spi::{Config as SpiConfig, RegsExt as _, *}; | 11 | use crate::spi::{Config as SpiConfig, RegsExt as _, *}; |
| 11 | use crate::time::Hertz; | 12 | use crate::time::Hertz; |
| 12 | 13 | ||
| @@ -225,7 +226,7 @@ impl<'s, 'd, W: Word> Reader<'s, 'd, W> { | |||
| 225 | pub struct I2S<'d, W: Word> { | 226 | pub struct I2S<'d, W: Word> { |
| 226 | #[allow(dead_code)] | 227 | #[allow(dead_code)] |
| 227 | mode: Mode, | 228 | mode: Mode, |
| 228 | spi: Spi<'d, Async>, | 229 | spi: Spi<'d, Async, Master>, |
| 229 | txsd: Option<Peri<'d, AnyPin>>, | 230 | txsd: Option<Peri<'d, AnyPin>>, |
| 230 | rxsd: Option<Peri<'d, AnyPin>>, | 231 | rxsd: Option<Peri<'d, AnyPin>>, |
| 231 | ws: Option<Peri<'d, AnyPin>>, | 232 | ws: Option<Peri<'d, AnyPin>>, |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index c27d09ea7..abb80ed26 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -125,26 +125,69 @@ impl Config { | |||
| 125 | ) | 125 | ) |
| 126 | } | 126 | } |
| 127 | } | 127 | } |
| 128 | |||
| 129 | /// SPI communication mode | ||
| 130 | pub mod mode { | ||
| 131 | use stm32_metapac::spi::vals; | ||
| 132 | |||
| 133 | trait SealedMode {} | ||
| 134 | |||
| 135 | /// Trait for SPI communication mode operations. | ||
| 136 | #[allow(private_bounds)] | ||
| 137 | pub trait CommunicationMode: SealedMode { | ||
| 138 | /// Spi communication mode | ||
| 139 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] | ||
| 140 | const MASTER: vals::Mstr; | ||
| 141 | /// Spi communication mode | ||
| 142 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 143 | const MASTER: vals::Master; | ||
| 144 | } | ||
| 145 | |||
| 146 | /// Mode allowing for SPI master operations. | ||
| 147 | pub struct Master; | ||
| 148 | /// Mode allowing for SPI slave operations. | ||
| 149 | pub struct Slave; | ||
| 150 | |||
| 151 | impl SealedMode for Master {} | ||
| 152 | impl CommunicationMode for Master { | ||
| 153 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] | ||
| 154 | const MASTER: vals::Mstr = vals::Mstr::MASTER; | ||
| 155 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 156 | const MASTER: vals::Master = vals::Master::MASTER; | ||
| 157 | } | ||
| 158 | |||
| 159 | impl SealedMode for Slave {} | ||
| 160 | impl CommunicationMode for Slave { | ||
| 161 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] | ||
| 162 | const MASTER: vals::Mstr = vals::Mstr::SLAVE; | ||
| 163 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 164 | const MASTER: vals::Master = vals::Master::SLAVE; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | use mode::{CommunicationMode, Master, Slave}; | ||
| 168 | |||
| 128 | /// SPI driver. | 169 | /// SPI driver. |
| 129 | pub struct Spi<'d, M: PeriMode> { | 170 | pub struct Spi<'d, M: PeriMode, CM: CommunicationMode> { |
| 130 | pub(crate) info: &'static Info, | 171 | pub(crate) info: &'static Info, |
| 131 | kernel_clock: Hertz, | 172 | kernel_clock: Hertz, |
| 132 | sck: Option<Peri<'d, AnyPin>>, | 173 | sck: Option<Peri<'d, AnyPin>>, |
| 133 | mosi: Option<Peri<'d, AnyPin>>, | 174 | mosi: Option<Peri<'d, AnyPin>>, |
| 134 | miso: Option<Peri<'d, AnyPin>>, | 175 | miso: Option<Peri<'d, AnyPin>>, |
| 176 | nss: Option<Peri<'d, AnyPin>>, | ||
| 135 | tx_dma: Option<ChannelAndRequest<'d>>, | 177 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 136 | rx_dma: Option<ChannelAndRequest<'d>>, | 178 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 137 | _phantom: PhantomData<M>, | 179 | _phantom: PhantomData<(M, CM)>, |
| 138 | current_word_size: word_impl::Config, | 180 | current_word_size: word_impl::Config, |
| 139 | gpio_speed: Speed, | 181 | gpio_speed: Speed, |
| 140 | } | 182 | } |
| 141 | 183 | ||
| 142 | impl<'d, M: PeriMode> Spi<'d, M> { | 184 | impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { |
| 143 | fn new_inner<T: Instance>( | 185 | fn new_inner<T: Instance>( |
| 144 | _peri: Peri<'d, T>, | 186 | _peri: Peri<'d, T>, |
| 145 | sck: Option<Peri<'d, AnyPin>>, | 187 | sck: Option<Peri<'d, AnyPin>>, |
| 146 | mosi: Option<Peri<'d, AnyPin>>, | 188 | mosi: Option<Peri<'d, AnyPin>>, |
| 147 | miso: Option<Peri<'d, AnyPin>>, | 189 | miso: Option<Peri<'d, AnyPin>>, |
| 190 | nss: Option<Peri<'d, AnyPin>>, | ||
| 148 | tx_dma: Option<ChannelAndRequest<'d>>, | 191 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 149 | rx_dma: Option<ChannelAndRequest<'d>>, | 192 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 150 | config: Config, | 193 | config: Config, |
| @@ -155,6 +198,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 155 | sck, | 198 | sck, |
| 156 | mosi, | 199 | mosi, |
| 157 | miso, | 200 | miso, |
| 201 | nss, | ||
| 158 | tx_dma, | 202 | tx_dma, |
| 159 | rx_dma, | 203 | rx_dma, |
| 160 | current_word_size: <u8 as SealedWord>::CONFIG, | 204 | current_word_size: <u8 as SealedWord>::CONFIG, |
| @@ -183,12 +227,12 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 183 | w.set_cpha(cpha); | 227 | w.set_cpha(cpha); |
| 184 | w.set_cpol(cpol); | 228 | w.set_cpol(cpol); |
| 185 | 229 | ||
| 186 | w.set_mstr(vals::Mstr::MASTER); | 230 | w.set_mstr(CM::MASTER); |
| 187 | w.set_br(br); | 231 | w.set_br(br); |
| 188 | w.set_spe(true); | 232 | w.set_spe(true); |
| 189 | w.set_lsbfirst(lsbfirst); | 233 | w.set_lsbfirst(lsbfirst); |
| 190 | w.set_ssi(true); | 234 | w.set_ssi(CM::MASTER == vals::Mstr::MASTER); |
| 191 | w.set_ssm(true); | 235 | w.set_ssm(CM::MASTER == vals::Mstr::MASTER); |
| 192 | w.set_crcen(false); | 236 | w.set_crcen(false); |
| 193 | w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); | 237 | w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); |
| 194 | // we're doing "fake rxonly", by actually writing one | 238 | // we're doing "fake rxonly", by actually writing one |
| @@ -210,11 +254,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 210 | w.set_cpha(cpha); | 254 | w.set_cpha(cpha); |
| 211 | w.set_cpol(cpol); | 255 | w.set_cpol(cpol); |
| 212 | 256 | ||
| 213 | w.set_mstr(vals::Mstr::MASTER); | 257 | w.set_mstr(CM::MASTER); |
| 214 | w.set_br(br); | 258 | w.set_br(br); |
| 215 | w.set_lsbfirst(lsbfirst); | 259 | w.set_lsbfirst(lsbfirst); |
| 216 | w.set_ssi(true); | 260 | w.set_ssi(CM::MASTER == vals::Mstr::MASTER); |
| 217 | w.set_ssm(true); | 261 | w.set_ssm(CM::MASTER == vals::Mstr::MASTER); |
| 218 | w.set_crcen(false); | 262 | w.set_crcen(false); |
| 219 | w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); | 263 | w.set_bidimode(vals::Bidimode::UNIDIRECTIONAL); |
| 220 | w.set_spe(true); | 264 | w.set_spe(true); |
| @@ -229,8 +273,8 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 229 | w.set_cpha(cpha); | 273 | w.set_cpha(cpha); |
| 230 | w.set_cpol(cpol); | 274 | w.set_cpol(cpol); |
| 231 | w.set_lsbfirst(lsbfirst); | 275 | w.set_lsbfirst(lsbfirst); |
| 232 | w.set_ssm(true); | 276 | w.set_ssm(CM::MASTER == vals::Master::MASTER); |
| 233 | w.set_master(vals::Master::MASTER); | 277 | w.set_master(CM::MASTER); |
| 234 | w.set_comm(vals::Comm::FULL_DUPLEX); | 278 | w.set_comm(vals::Comm::FULL_DUPLEX); |
| 235 | w.set_ssom(vals::Ssom::ASSERTED); | 279 | w.set_ssom(vals::Ssom::ASSERTED); |
| 236 | w.set_midi(0); | 280 | w.set_midi(0); |
| @@ -469,7 +513,30 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 469 | } | 513 | } |
| 470 | } | 514 | } |
| 471 | 515 | ||
| 472 | impl<'d> Spi<'d, Blocking> { | 516 | impl<'d> Spi<'d, Blocking, Slave> { |
| 517 | /// Create a new blocking SPI slave driver. | ||
| 518 | pub fn new_blocking_slave<T: Instance, #[cfg(afio)] A>( | ||
| 519 | peri: Peri<'d, T>, | ||
| 520 | sck: Peri<'d, if_afio!(impl SckPin<T, A>)>, | ||
| 521 | mosi: Peri<'d, if_afio!(impl MosiPin<T, A>)>, | ||
| 522 | miso: Peri<'d, if_afio!(impl MisoPin<T, A>)>, | ||
| 523 | cs: Peri<'d, if_afio!(impl CsPin<T, A>)>, | ||
| 524 | config: Config, | ||
| 525 | ) -> Self { | ||
| 526 | Self::new_inner( | ||
| 527 | peri, | ||
| 528 | new_pin!(sck, config.sck_af()), | ||
| 529 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), | ||
| 530 | new_pin!(miso, AfType::input(config.miso_pull)), | ||
| 531 | new_pin!(cs, AfType::input(Pull::None)), | ||
| 532 | None, | ||
| 533 | None, | ||
| 534 | config, | ||
| 535 | ) | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | impl<'d> Spi<'d, Blocking, Master> { | ||
| 473 | /// Create a new blocking SPI driver. | 540 | /// Create a new blocking SPI driver. |
| 474 | pub fn new_blocking<T: Instance, #[cfg(afio)] A>( | 541 | pub fn new_blocking<T: Instance, #[cfg(afio)] A>( |
| 475 | peri: Peri<'d, T>, | 542 | peri: Peri<'d, T>, |
| @@ -485,6 +552,7 @@ impl<'d> Spi<'d, Blocking> { | |||
| 485 | new_pin!(miso, AfType::input(config.miso_pull)), | 552 | new_pin!(miso, AfType::input(config.miso_pull)), |
| 486 | None, | 553 | None, |
| 487 | None, | 554 | None, |
| 555 | None, | ||
| 488 | config, | 556 | config, |
| 489 | ) | 557 | ) |
| 490 | } | 558 | } |
| @@ -503,6 +571,7 @@ impl<'d> Spi<'d, Blocking> { | |||
| 503 | new_pin!(miso, AfType::input(config.miso_pull)), | 571 | new_pin!(miso, AfType::input(config.miso_pull)), |
| 504 | None, | 572 | None, |
| 505 | None, | 573 | None, |
| 574 | None, | ||
| 506 | config, | 575 | config, |
| 507 | ) | 576 | ) |
| 508 | } | 577 | } |
| @@ -521,6 +590,7 @@ impl<'d> Spi<'d, Blocking> { | |||
| 521 | None, | 590 | None, |
| 522 | None, | 591 | None, |
| 523 | None, | 592 | None, |
| 593 | None, | ||
| 524 | config, | 594 | config, |
| 525 | ) | 595 | ) |
| 526 | } | 596 | } |
| @@ -540,12 +610,38 @@ impl<'d> Spi<'d, Blocking> { | |||
| 540 | None, | 610 | None, |
| 541 | None, | 611 | None, |
| 542 | None, | 612 | None, |
| 613 | None, | ||
| 614 | config, | ||
| 615 | ) | ||
| 616 | } | ||
| 617 | } | ||
| 618 | |||
| 619 | impl<'d> Spi<'d, Async, Slave> { | ||
| 620 | /// Create a new SPI slave driver. | ||
| 621 | pub fn new_slave<T: Instance, #[cfg(afio)] A>( | ||
| 622 | peri: Peri<'d, T>, | ||
| 623 | sck: Peri<'d, if_afio!(impl SckPin<T, A>)>, | ||
| 624 | mosi: Peri<'d, if_afio!(impl MosiPin<T, A>)>, | ||
| 625 | miso: Peri<'d, if_afio!(impl MisoPin<T, A>)>, | ||
| 626 | cs: Peri<'d, if_afio!(impl CsPin<T, A>)>, | ||
| 627 | tx_dma: Peri<'d, impl TxDma<T>>, | ||
| 628 | rx_dma: Peri<'d, impl RxDma<T>>, | ||
| 629 | config: Config, | ||
| 630 | ) -> Self { | ||
| 631 | Self::new_inner( | ||
| 632 | peri, | ||
| 633 | new_pin!(sck, config.sck_af()), | ||
| 634 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), | ||
| 635 | new_pin!(miso, AfType::input(config.miso_pull)), | ||
| 636 | new_pin!(cs, AfType::input(Pull::None)), | ||
| 637 | new_dma!(tx_dma), | ||
| 638 | new_dma!(rx_dma), | ||
| 543 | config, | 639 | config, |
| 544 | ) | 640 | ) |
| 545 | } | 641 | } |
| 546 | } | 642 | } |
| 547 | 643 | ||
| 548 | impl<'d> Spi<'d, Async> { | 644 | impl<'d> Spi<'d, Async, Master> { |
| 549 | /// Create a new SPI driver. | 645 | /// Create a new SPI driver. |
| 550 | pub fn new<T: Instance, #[cfg(afio)] A>( | 646 | pub fn new<T: Instance, #[cfg(afio)] A>( |
| 551 | peri: Peri<'d, T>, | 647 | peri: Peri<'d, T>, |
| @@ -561,6 +657,7 @@ impl<'d> Spi<'d, Async> { | |||
| 561 | new_pin!(sck, config.sck_af()), | 657 | new_pin!(sck, config.sck_af()), |
| 562 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), | 658 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), |
| 563 | new_pin!(miso, AfType::input(config.miso_pull)), | 659 | new_pin!(miso, AfType::input(config.miso_pull)), |
| 660 | None, | ||
| 564 | new_dma!(tx_dma), | 661 | new_dma!(tx_dma), |
| 565 | new_dma!(rx_dma), | 662 | new_dma!(rx_dma), |
| 566 | config, | 663 | config, |
| @@ -581,6 +678,7 @@ impl<'d> Spi<'d, Async> { | |||
| 581 | new_pin!(sck, config.sck_af()), | 678 | new_pin!(sck, config.sck_af()), |
| 582 | None, | 679 | None, |
| 583 | new_pin!(miso, AfType::input(config.miso_pull)), | 680 | new_pin!(miso, AfType::input(config.miso_pull)), |
| 681 | None, | ||
| 584 | #[cfg(any(spi_v1, spi_v2, spi_v3))] | 682 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 585 | new_dma!(tx_dma), | 683 | new_dma!(tx_dma), |
| 586 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | 684 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| @@ -603,6 +701,7 @@ impl<'d> Spi<'d, Async> { | |||
| 603 | new_pin!(sck, config.sck_af()), | 701 | new_pin!(sck, config.sck_af()), |
| 604 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), | 702 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), |
| 605 | None, | 703 | None, |
| 704 | None, | ||
| 606 | new_dma!(tx_dma), | 705 | new_dma!(tx_dma), |
| 607 | None, | 706 | None, |
| 608 | config, | 707 | config, |
| @@ -623,6 +722,7 @@ impl<'d> Spi<'d, Async> { | |||
| 623 | None, | 722 | None, |
| 624 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), | 723 | new_pin!(mosi, AfType::output(OutputType::PushPull, config.gpio_speed)), |
| 625 | None, | 724 | None, |
| 725 | None, | ||
| 626 | new_dma!(tx_dma), | 726 | new_dma!(tx_dma), |
| 627 | None, | 727 | None, |
| 628 | config, | 728 | config, |
| @@ -646,7 +746,7 @@ impl<'d> Spi<'d, Async> { | |||
| 646 | config.bit_order = BitOrder::MsbFirst; | 746 | config.bit_order = BitOrder::MsbFirst; |
| 647 | config.frequency = freq; | 747 | config.frequency = freq; |
| 648 | 748 | ||
| 649 | Self::new_inner(peri, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config) | 749 | Self::new_inner(peri, None, None, None, None, new_dma!(tx_dma), new_dma!(rx_dma), config) |
| 650 | } | 750 | } |
| 651 | 751 | ||
| 652 | #[allow(dead_code)] | 752 | #[allow(dead_code)] |
| @@ -656,9 +756,11 @@ impl<'d> Spi<'d, Async> { | |||
| 656 | rx_dma: Option<ChannelAndRequest<'d>>, | 756 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 657 | config: Config, | 757 | config: Config, |
| 658 | ) -> Self { | 758 | ) -> Self { |
| 659 | Self::new_inner(peri, None, None, None, tx_dma, rx_dma, config) | 759 | Self::new_inner(peri, None, None, None, None, tx_dma, rx_dma, config) |
| 660 | } | 760 | } |
| 761 | } | ||
| 661 | 762 | ||
| 763 | impl<'d, CM: CommunicationMode> Spi<'d, Async, CM> { | ||
| 662 | /// SPI write, using DMA. | 764 | /// SPI write, using DMA. |
| 663 | pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> { | 765 | pub async fn write<W: Word>(&mut self, data: &[W]) -> Result<(), Error> { |
| 664 | if data.is_empty() { | 766 | if data.is_empty() { |
| @@ -888,11 +990,12 @@ impl<'d> Spi<'d, Async> { | |||
| 888 | } | 990 | } |
| 889 | } | 991 | } |
| 890 | 992 | ||
| 891 | impl<'d, M: PeriMode> Drop for Spi<'d, M> { | 993 | impl<'d, M: PeriMode, CM: CommunicationMode> Drop for Spi<'d, M, CM> { |
| 892 | fn drop(&mut self) { | 994 | fn drop(&mut self) { |
| 893 | self.sck.as_ref().map(|x| x.set_as_disconnected()); | 995 | self.sck.as_ref().map(|x| x.set_as_disconnected()); |
| 894 | self.mosi.as_ref().map(|x| x.set_as_disconnected()); | 996 | self.mosi.as_ref().map(|x| x.set_as_disconnected()); |
| 895 | self.miso.as_ref().map(|x| x.set_as_disconnected()); | 997 | self.miso.as_ref().map(|x| x.set_as_disconnected()); |
| 998 | self.nss.as_ref().map(|x| x.set_as_disconnected()); | ||
| 896 | 999 | ||
| 897 | self.info.rcc.disable(); | 1000 | self.info.rcc.disable(); |
| 898 | } | 1001 | } |
| @@ -1127,7 +1230,7 @@ fn write_word<W: Word>(regs: Regs, tx_word: W) -> Result<(), Error> { | |||
| 1127 | // some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289 | 1230 | // some marker traits. For details, see https://github.com/rust-embedded/embedded-hal/pull/289 |
| 1128 | macro_rules! impl_blocking { | 1231 | macro_rules! impl_blocking { |
| 1129 | ($w:ident) => { | 1232 | ($w:ident) => { |
| 1130 | impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M> { | 1233 | impl<'d, M: PeriMode, CM: CommunicationMode> embedded_hal_02::blocking::spi::Write<$w> for Spi<'d, M, CM> { |
| 1131 | type Error = Error; | 1234 | type Error = Error; |
| 1132 | 1235 | ||
| 1133 | fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> { | 1236 | fn write(&mut self, words: &[$w]) -> Result<(), Self::Error> { |
| @@ -1135,7 +1238,7 @@ macro_rules! impl_blocking { | |||
| 1135 | } | 1238 | } |
| 1136 | } | 1239 | } |
| 1137 | 1240 | ||
| 1138 | impl<'d, M: PeriMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M> { | 1241 | impl<'d, M: PeriMode, CM: CommunicationMode> embedded_hal_02::blocking::spi::Transfer<$w> for Spi<'d, M, CM> { |
| 1139 | type Error = Error; | 1242 | type Error = Error; |
| 1140 | 1243 | ||
| 1141 | fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> { | 1244 | fn transfer<'w>(&mut self, words: &'w mut [$w]) -> Result<&'w [$w], Self::Error> { |
| @@ -1149,11 +1252,11 @@ macro_rules! impl_blocking { | |||
| 1149 | impl_blocking!(u8); | 1252 | impl_blocking!(u8); |
| 1150 | impl_blocking!(u16); | 1253 | impl_blocking!(u16); |
| 1151 | 1254 | ||
| 1152 | impl<'d, M: PeriMode> embedded_hal_1::spi::ErrorType for Spi<'d, M> { | 1255 | impl<'d, M: PeriMode, CM: CommunicationMode> embedded_hal_1::spi::ErrorType for Spi<'d, M, CM> { |
| 1153 | type Error = Error; | 1256 | type Error = Error; |
| 1154 | } | 1257 | } |
| 1155 | 1258 | ||
| 1156 | impl<'d, W: Word, M: PeriMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M> { | 1259 | impl<'d, W: Word, M: PeriMode, CM: CommunicationMode> embedded_hal_1::spi::SpiBus<W> for Spi<'d, M, CM> { |
| 1157 | fn flush(&mut self) -> Result<(), Self::Error> { | 1260 | fn flush(&mut self) -> Result<(), Self::Error> { |
| 1158 | Ok(()) | 1261 | Ok(()) |
| 1159 | } | 1262 | } |
| @@ -1186,7 +1289,7 @@ impl embedded_hal_1::spi::Error for Error { | |||
| 1186 | } | 1289 | } |
| 1187 | } | 1290 | } |
| 1188 | 1291 | ||
| 1189 | impl<'d, W: Word> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async> { | 1292 | impl<'d, W: Word, CM: CommunicationMode> embedded_hal_async::spi::SpiBus<W> for Spi<'d, Async, CM> { |
| 1190 | async fn flush(&mut self) -> Result<(), Self::Error> { | 1293 | async fn flush(&mut self) -> Result<(), Self::Error> { |
| 1191 | Ok(()) | 1294 | Ok(()) |
| 1192 | } | 1295 | } |
| @@ -1328,7 +1431,7 @@ foreach_peripheral!( | |||
| 1328 | }; | 1431 | }; |
| 1329 | ); | 1432 | ); |
| 1330 | 1433 | ||
| 1331 | impl<'d, M: PeriMode> SetConfig for Spi<'d, M> { | 1434 | impl<'d, M: PeriMode, CM: CommunicationMode> SetConfig for Spi<'d, M, CM> { |
| 1332 | type Config = Config; | 1435 | type Config = Config; |
| 1333 | type ConfigError = (); | 1436 | type ConfigError = (); |
| 1334 | fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { | 1437 | fn set_config(&mut self, config: &Self::Config) -> Result<(), ()> { |
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs index cccf20949..0adcda614 100644 --- a/examples/stm32f4/src/bin/eth_w5500.rs +++ b/examples/stm32f4/src/bin/eth_w5500.rs | |||
| @@ -12,6 +12,7 @@ use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | |||
| 12 | use embassy_stm32::mode::Async; | 12 | use embassy_stm32::mode::Async; |
| 13 | use embassy_stm32::rng::Rng; | 13 | use embassy_stm32::rng::Rng; |
| 14 | use embassy_stm32::spi::Spi; | 14 | use embassy_stm32::spi::Spi; |
| 15 | use embassy_stm32::spi::mode::Master; | ||
| 15 | use embassy_stm32::time::Hertz; | 16 | use embassy_stm32::time::Hertz; |
| 16 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi}; | 17 | use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi}; |
| 17 | use embassy_time::{Delay, Timer}; | 18 | use embassy_time::{Delay, Timer}; |
| @@ -24,7 +25,7 @@ bind_interrupts!(struct Irqs { | |||
| 24 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; | 25 | HASH_RNG => rng::InterruptHandler<peripherals::RNG>; |
| 25 | }); | 26 | }); |
| 26 | 27 | ||
| 27 | type EthernetSPI = ExclusiveDevice<Spi<'static, Async>, Output<'static>, Delay>; | 28 | type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>; |
| 28 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| 29 | async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { | 30 | async fn ethernet_task(runner: Runner<'static, W5500, EthernetSPI, ExtiInput<'static>, Output<'static>>) -> ! { |
| 30 | runner.run().await | 31 | runner.run().await |
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index 61f31be24..f7ab20cdd 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs | |||
| @@ -15,7 +15,7 @@ use static_cell::StaticCell; | |||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); | 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); |
diff --git a/examples/stm32h7/src/bin/spi_bdma.rs b/examples/stm32h7/src/bin/spi_bdma.rs index be6a26d82..cd9d6c789 100644 --- a/examples/stm32h7/src/bin/spi_bdma.rs +++ b/examples/stm32h7/src/bin/spi_bdma.rs | |||
| @@ -20,7 +20,7 @@ use {defmt_rtt as _, panic_probe as _}; | |||
| 20 | static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); | 20 | static mut RAM_D3: GroundedArrayCell<u8, 256> = GroundedArrayCell::uninit(); |
| 21 | 21 | ||
| 22 | #[embassy_executor::task] | 22 | #[embassy_executor::task] |
| 23 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 23 | async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) { |
| 24 | let (read_buffer, write_buffer) = unsafe { | 24 | let (read_buffer, write_buffer) = unsafe { |
| 25 | let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); | 25 | let ram = &mut *core::ptr::addr_of_mut!(RAM_D3); |
| 26 | ram.initialize_all_copied(0); | 26 | ram.initialize_all_copied(0); |
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 20cb67ba0..3d3c2f43e 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs | |||
| @@ -15,7 +15,7 @@ use static_cell::StaticCell; | |||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | let mut read = [0; 128]; | 21 | let mut read = [0; 128]; |
diff --git a/examples/stm32h7rs/src/bin/spi.rs b/examples/stm32h7rs/src/bin/spi.rs index 8c280fdae..3253304eb 100644 --- a/examples/stm32h7rs/src/bin/spi.rs +++ b/examples/stm32h7rs/src/bin/spi.rs | |||
| @@ -15,7 +15,7 @@ use static_cell::StaticCell; | |||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Blocking, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); | 21 | core::write!(&mut write, "Hello DMA World {}!\r\n", n).unwrap(); |
diff --git a/examples/stm32h7rs/src/bin/spi_dma.rs b/examples/stm32h7rs/src/bin/spi_dma.rs index 3fa69fd15..ca644c6a8 100644 --- a/examples/stm32h7rs/src/bin/spi_dma.rs +++ b/examples/stm32h7rs/src/bin/spi_dma.rs | |||
| @@ -15,7 +15,7 @@ use static_cell::StaticCell; | |||
| 15 | use {defmt_rtt as _, panic_probe as _}; | 15 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 16 | ||
| 17 | #[embassy_executor::task] | 17 | #[embassy_executor::task] |
| 18 | async fn main_task(mut spi: spi::Spi<'static, Async>) { | 18 | async fn main_task(mut spi: spi::Spi<'static, Async, spi::mode::Master>) { |
| 19 | for n in 0u32.. { | 19 | for n in 0u32.. { |
| 20 | let mut write: String<128> = String::new(); | 20 | let mut write: String<128> = String::new(); |
| 21 | let mut read = [0; 128]; | 21 | let mut read = [0; 128]; |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 8e54938d1..0dbf515cf 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -28,6 +28,7 @@ use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; | |||
| 28 | use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; | 28 | use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; |
| 29 | use embassy_stm32::mode::Async; | 29 | use embassy_stm32::mode::Async; |
| 30 | use embassy_stm32::rng::{self, Rng}; | 30 | use embassy_stm32::rng::{self, Rng}; |
| 31 | use embassy_stm32::spi::mode::Master; | ||
| 31 | use embassy_stm32::spi::{Config as SPI_Config, Spi}; | 32 | use embassy_stm32::spi::{Config as SPI_Config, Spi}; |
| 32 | use embassy_stm32::time::Hertz; | 33 | use embassy_stm32::time::Hertz; |
| 33 | use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; | 34 | use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; |
| @@ -54,7 +55,7 @@ const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address::new(192, 168, 1, 5), 24) | |||
| 54 | // Listen port for the webserver | 55 | // Listen port for the webserver |
| 55 | const HTTP_LISTEN_PORT: u16 = 80; | 56 | const HTTP_LISTEN_PORT: u16 = 80; |
| 56 | 57 | ||
| 57 | pub type SpeSpi = Spi<'static, Async>; | 58 | pub type SpeSpi = Spi<'static, Async, Master>; |
| 58 | pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; | 59 | pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static>, Delay>; |
| 59 | pub type SpeInt = exti::ExtiInput<'static>; | 60 | pub type SpeInt = exti::ExtiInput<'static>; |
| 60 | pub type SpeRst = Output<'static>; | 61 | pub type SpeRst = Output<'static>; |
diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs index e8310866a..cedff772c 100644 --- a/tests/stm32/src/bin/spi.rs +++ b/tests/stm32/src/bin/spi.rs | |||
| @@ -8,6 +8,7 @@ use defmt::assert_eq; | |||
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | 9 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 10 | use embassy_stm32::mode::Blocking; | 10 | use embassy_stm32::mode::Blocking; |
| 11 | use embassy_stm32::spi::mode::Master; | ||
| 11 | use embassy_stm32::spi::{self, Spi, Word}; | 12 | use embassy_stm32::spi::{self, Spi, Word}; |
| 12 | use embassy_stm32::time::Hertz; | 13 | use embassy_stm32::time::Hertz; |
| 13 | 14 | ||
| @@ -65,7 +66,7 @@ async fn main(_spawner: Spawner) { | |||
| 65 | cortex_m::asm::bkpt(); | 66 | cortex_m::asm::bkpt(); |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking>) | 69 | fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking, Master>) |
| 69 | where | 70 | where |
| 70 | W: core::ops::Not<Output = W>, | 71 | W: core::ops::Not<Output = W>, |
| 71 | { | 72 | { |
| @@ -109,7 +110,7 @@ where | |||
| 109 | spi.blocking_write::<u8>(&[]).unwrap(); | 110 | spi.blocking_write::<u8>(&[]).unwrap(); |
| 110 | } | 111 | } |
| 111 | 112 | ||
| 112 | fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking>, mosi_out: &mut Output<'_>) | 113 | fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking, Master>, mosi_out: &mut Output<'_>) |
| 113 | where | 114 | where |
| 114 | W: core::ops::Not<Output = W>, | 115 | W: core::ops::Not<Output = W>, |
| 115 | { | 116 | { |
| @@ -125,7 +126,7 @@ where | |||
| 125 | spi.blocking_read::<u8>(&mut []).unwrap(); | 126 | spi.blocking_read::<u8>(&mut []).unwrap(); |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking>) | 129 | fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Blocking, Master>) |
| 129 | where | 130 | where |
| 130 | W: core::ops::Not<Output = W>, | 131 | W: core::ops::Not<Output = W>, |
| 131 | { | 132 | { |
diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs index b4fdb8faa..c8cd92401 100644 --- a/tests/stm32/src/bin/spi_dma.rs +++ b/tests/stm32/src/bin/spi_dma.rs | |||
| @@ -8,6 +8,7 @@ use defmt::assert_eq; | |||
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | 9 | use embassy_stm32::gpio::{Level, Output, Speed}; |
| 10 | use embassy_stm32::mode::Async; | 10 | use embassy_stm32::mode::Async; |
| 11 | use embassy_stm32::spi::mode::Master; | ||
| 11 | use embassy_stm32::spi::{self, Spi, Word}; | 12 | use embassy_stm32::spi::{self, Spi, Word}; |
| 12 | use embassy_stm32::time::Hertz; | 13 | use embassy_stm32::time::Hertz; |
| 13 | 14 | ||
| @@ -78,7 +79,7 @@ async fn main(_spawner: Spawner) { | |||
| 78 | cortex_m::asm::bkpt(); | 79 | cortex_m::asm::bkpt(); |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | async fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async>) | 82 | async fn test_txrx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async, Master>) |
| 82 | where | 83 | where |
| 83 | W: core::ops::Not<Output = W>, | 84 | W: core::ops::Not<Output = W>, |
| 84 | { | 85 | { |
| @@ -142,7 +143,7 @@ where | |||
| 142 | spi.write(&buf).await.unwrap(); | 143 | spi.write(&buf).await.unwrap(); |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | async fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async>, mosi_out: &mut Output<'_>) | 146 | async fn test_rx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async, Master>, mosi_out: &mut Output<'_>) |
| 146 | where | 147 | where |
| 147 | W: core::ops::Not<Output = W>, | 148 | W: core::ops::Not<Output = W>, |
| 148 | { | 149 | { |
| @@ -168,7 +169,7 @@ where | |||
| 168 | spi.blocking_read::<u8>(&mut []).unwrap(); | 169 | spi.blocking_read::<u8>(&mut []).unwrap(); |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | async fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async>) | 172 | async fn test_tx<W: Word + From<u8> + defmt::Format + Eq>(spi: &mut Spi<'_, Async, Master>) |
| 172 | where | 173 | where |
| 173 | W: core::ops::Not<Output = W>, | 174 | W: core::ops::Not<Output = W>, |
| 174 | { | 175 | { |
