diff options
| author | Pietro Lorefice <[email protected]> | 2025-12-11 16:13:07 +0100 |
|---|---|---|
| committer | Pietro Lorefice <[email protected]> | 2025-12-11 16:13:07 +0100 |
| commit | 3bc913b77572e91e38709071f7f7bb8777847ccf (patch) | |
| tree | ea77e21d71d9c0c835407c3770782598531cbd0a /embassy-stm32 | |
| parent | f650afc33b2d6b39116f27c6545c5f2d9e3c7d06 (diff) | |
stm32/spi: make SS signal polarity configurable on supported hardware
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index c90e0cef4..af51b79b4 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -64,6 +64,16 @@ pub enum Direction { | |||
| 64 | Receive, | 64 | Receive, |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | /// Slave Select (SS) pin polarity. | ||
| 68 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
| 69 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 70 | pub enum SlaveSelectPolarity { | ||
| 71 | /// SS active high | ||
| 72 | ActiveHigh, | ||
| 73 | /// SS active low | ||
| 74 | ActiveLow, | ||
| 75 | } | ||
| 76 | |||
| 67 | /// SPI configuration. | 77 | /// SPI configuration. |
| 68 | #[non_exhaustive] | 78 | #[non_exhaustive] |
| 69 | #[derive(Copy, Clone)] | 79 | #[derive(Copy, Clone)] |
| @@ -86,6 +96,9 @@ pub struct Config { | |||
| 86 | /// NSS output enabled (SSM = 0, SSOE = 1): The NSS signal is driven low when the master starts the communication and is kept low until the SPI is disabled. | 96 | /// NSS output enabled (SSM = 0, SSOE = 1): The NSS signal is driven low when the master starts the communication and is kept low until the SPI is disabled. |
| 87 | /// NSS output disabled (SSM = 0, SSOE = 0): For devices set as slave, the NSS pin acts as a classical NSS input: the slave is selected when NSS is low and deselected when NSS high. | 97 | /// NSS output disabled (SSM = 0, SSOE = 0): For devices set as slave, the NSS pin acts as a classical NSS input: the slave is selected when NSS is low and deselected when NSS high. |
| 88 | pub nss_output_disable: bool, | 98 | pub nss_output_disable: bool, |
| 99 | /// Slave Select (SS) pin polarity. | ||
| 100 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 101 | pub nss_polarity: SlaveSelectPolarity, | ||
| 89 | } | 102 | } |
| 90 | 103 | ||
| 91 | impl Default for Config { | 104 | impl Default for Config { |
| @@ -97,6 +110,8 @@ impl Default for Config { | |||
| 97 | miso_pull: Pull::None, | 110 | miso_pull: Pull::None, |
| 98 | gpio_speed: Speed::VeryHigh, | 111 | gpio_speed: Speed::VeryHigh, |
| 99 | nss_output_disable: false, | 112 | nss_output_disable: false, |
| 113 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 114 | nss_polarity: SlaveSelectPolarity::ActiveHigh, | ||
| 100 | } | 115 | } |
| 101 | } | 116 | } |
| 102 | } | 117 | } |
| @@ -123,6 +138,14 @@ impl Config { | |||
| 123 | } | 138 | } |
| 124 | } | 139 | } |
| 125 | 140 | ||
| 141 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 142 | fn raw_nss_polarity(&self) -> vals::Ssiop { | ||
| 143 | match self.nss_polarity { | ||
| 144 | SlaveSelectPolarity::ActiveHigh => vals::Ssiop::ACTIVE_HIGH, | ||
| 145 | SlaveSelectPolarity::ActiveLow => vals::Ssiop::ACTIVE_LOW, | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 126 | #[cfg(gpio_v1)] | 149 | #[cfg(gpio_v1)] |
| 127 | fn sck_af(&self) -> AfType { | 150 | fn sck_af(&self) -> AfType { |
| 128 | AfType::output(OutputType::PushPull, self.gpio_speed) | 151 | AfType::output(OutputType::PushPull, self.gpio_speed) |
| @@ -305,6 +328,7 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { | |||
| 305 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | 328 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 306 | { | 329 | { |
| 307 | let ssoe = CM::MASTER == vals::Master::MASTER && !config.nss_output_disable; | 330 | let ssoe = CM::MASTER == vals::Master::MASTER && !config.nss_output_disable; |
| 331 | let ssiop = config.raw_nss_polarity(); | ||
| 308 | regs.ifcr().write(|w| w.0 = 0xffff_ffff); | 332 | regs.ifcr().write(|w| w.0 = 0xffff_ffff); |
| 309 | regs.cfg2().modify(|w| { | 333 | regs.cfg2().modify(|w| { |
| 310 | w.set_ssoe(ssoe); | 334 | w.set_ssoe(ssoe); |
| @@ -318,7 +342,7 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { | |||
| 318 | w.set_midi(0); | 342 | w.set_midi(0); |
| 319 | w.set_mssi(0); | 343 | w.set_mssi(0); |
| 320 | w.set_afcntr(true); | 344 | w.set_afcntr(true); |
| 321 | w.set_ssiop(vals::Ssiop::ACTIVE_HIGH); | 345 | w.set_ssiop(ssiop); |
| 322 | }); | 346 | }); |
| 323 | regs.cfg1().modify(|w| { | 347 | regs.cfg1().modify(|w| { |
| 324 | w.set_crcen(false); | 348 | w.set_crcen(false); |
| @@ -366,6 +390,8 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { | |||
| 366 | 390 | ||
| 367 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | 391 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 368 | { | 392 | { |
| 393 | let ssiop = config.raw_nss_polarity(); | ||
| 394 | |||
| 369 | self.info.regs.cr1().modify(|w| { | 395 | self.info.regs.cr1().modify(|w| { |
| 370 | w.set_spe(false); | 396 | w.set_spe(false); |
| 371 | }); | 397 | }); |
| @@ -374,6 +400,7 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { | |||
| 374 | w.set_cpha(cpha); | 400 | w.set_cpha(cpha); |
| 375 | w.set_cpol(cpol); | 401 | w.set_cpol(cpol); |
| 376 | w.set_lsbfirst(lsbfirst); | 402 | w.set_lsbfirst(lsbfirst); |
| 403 | w.set_ssiop(ssiop); | ||
| 377 | }); | 404 | }); |
| 378 | self.info.regs.cfg1().modify(|w| { | 405 | self.info.regs.cfg1().modify(|w| { |
| 379 | w.set_mbr(br); | 406 | w.set_mbr(br); |
| @@ -446,6 +473,13 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { | |||
| 446 | // NSS output disabled if SSOE=0 or if SSM=1 software slave management enabled | 473 | // NSS output disabled if SSOE=0 or if SSM=1 software slave management enabled |
| 447 | let nss_output_disable = !ssoe || cfg.ssm(); | 474 | let nss_output_disable = !ssoe || cfg.ssm(); |
| 448 | 475 | ||
| 476 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 477 | let nss_polarity = if cfg.ssiop() == vals::Ssiop::ACTIVE_LOW { | ||
| 478 | SlaveSelectPolarity::ActiveLow | ||
| 479 | } else { | ||
| 480 | SlaveSelectPolarity::ActiveHigh | ||
| 481 | }; | ||
| 482 | |||
| 449 | Config { | 483 | Config { |
| 450 | mode: Mode { polarity, phase }, | 484 | mode: Mode { polarity, phase }, |
| 451 | bit_order, | 485 | bit_order, |
| @@ -453,6 +487,8 @@ impl<'d, M: PeriMode, CM: CommunicationMode> Spi<'d, M, CM> { | |||
| 453 | miso_pull, | 487 | miso_pull, |
| 454 | gpio_speed: self.gpio_speed, | 488 | gpio_speed: self.gpio_speed, |
| 455 | nss_output_disable, | 489 | nss_output_disable, |
| 490 | #[cfg(any(spi_v4, spi_v5, spi_v6))] | ||
| 491 | nss_polarity, | ||
| 456 | } | 492 | } |
| 457 | } | 493 | } |
| 458 | 494 | ||
| @@ -769,7 +805,7 @@ impl<'d> Spi<'d, Async, Master> { | |||
| 769 | ) | 805 | ) |
| 770 | } | 806 | } |
| 771 | 807 | ||
| 772 | /// Create a new SPI driver, in bidirectional mode, specifically in tranmit mode | 808 | /// Create a new SPI driver, in bidirectional mode, specifically in tranmit mode |
| 773 | #[cfg(any(spi_v1, spi_v2, spi_v3))] | 809 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 774 | pub fn new_bidi<T: Instance, #[cfg(afio)] A>( | 810 | pub fn new_bidi<T: Instance, #[cfg(afio)] A>( |
| 775 | peri: Peri<'d, T>, | 811 | peri: Peri<'d, T>, |
