diff options
| -rw-r--r-- | embassy-stm32/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | embassy-stm32/Cargo.toml | 8 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/mod.rs | 68 | ||||
| -rw-r--r-- | embassy-stm32/src/i2s.rs | 183 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 134 |
6 files changed, 181 insertions, 215 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 8ed4dbd65..5545fc454 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md | |||
| @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 12 | - feat: Derive Clone, Copy for QSPI Config | 12 | - feat: Derive Clone, Copy for QSPI Config |
| 13 | - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received | 13 | - fix: stm32/i2c in master mode (blocking): subsequent transmissions failed after a NACK was received |
| 14 | - feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm | 14 | - feat: stm32/timer: add set_polarity functions for main and complementary outputs in complementary_pwm |
| 15 | - Add I2S support for STM32F1, STM32C0, STM32F0, STM32F3, STM32F7, STM32G0, STM32WL, STM32H5, STM32H7RS | ||
| 15 | 16 | ||
| 16 | ## 0.4.0 - 2025-08-26 | 17 | ## 0.4.0 - 2025-08-26 |
| 17 | 18 | ||
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index cdb4e07d1..9c2ba1f53 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -173,8 +173,8 @@ cortex-m = "0.7.6" | |||
| 173 | futures-util = { version = "0.3.30", default-features = false } | 173 | futures-util = { version = "0.3.30", default-features = false } |
| 174 | sdio-host = "0.9.0" | 174 | sdio-host = "0.9.0" |
| 175 | critical-section = "1.1" | 175 | critical-section = "1.1" |
| 176 | stm32-metapac = { version = "18" } | 176 | #stm32-metapac = { version = "18" } |
| 177 | #stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7" } | 177 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d8432edd0406495adec19d31923584e80b8e03cb" } |
| 178 | 178 | ||
| 179 | vcell = "0.1.3" | 179 | vcell = "0.1.3" |
| 180 | nb = "1.0.0" | 180 | nb = "1.0.0" |
| @@ -202,8 +202,8 @@ proptest-state-machine = "0.3.0" | |||
| 202 | proc-macro2 = "1.0.36" | 202 | proc-macro2 = "1.0.36" |
| 203 | quote = "1.0.15" | 203 | quote = "1.0.15" |
| 204 | 204 | ||
| 205 | stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} | 205 | #stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} |
| 206 | #stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7", default-features = false, features = ["metadata"] } | 206 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d8432edd0406495adec19d31923584e80b8e03cb", default-features = false, features = ["metadata"] } |
| 207 | 207 | ||
| 208 | [features] | 208 | [features] |
| 209 | default = ["rt"] | 209 | default = ["rt"] |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 778edc6f6..ea986f4cf 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -2,12 +2,12 @@ | |||
| 2 | 2 | ||
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | #![allow(missing_docs)] // TODO | 4 | #![allow(missing_docs)] // TODO |
| 5 | #![cfg_attr(adc_f3_v2, allow(unused))] | 5 | #![cfg_attr(adc_f3v3, allow(unused))] |
| 6 | 6 | ||
| 7 | #[cfg(not(any(adc_f3_v2, adc_wba)))] | 7 | #[cfg(not(any(adc_f3v3, adc_wba)))] |
| 8 | #[cfg_attr(adc_f1, path = "f1.rs")] | 8 | #[cfg_attr(adc_f1, path = "f1.rs")] |
| 9 | #[cfg_attr(adc_f3, path = "f3.rs")] | 9 | #[cfg_attr(adc_f3v1, path = "f3.rs")] |
| 10 | #[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")] | 10 | #[cfg_attr(adc_f3v2, path = "f3_v1_1.rs")] |
| 11 | #[cfg_attr(adc_v1, path = "v1.rs")] | 11 | #[cfg_attr(adc_v1, path = "v1.rs")] |
| 12 | #[cfg_attr(adc_l0, path = "v1.rs")] | 12 | #[cfg_attr(adc_l0, path = "v1.rs")] |
| 13 | #[cfg_attr(adc_v2, path = "v2.rs")] | 13 | #[cfg_attr(adc_v2, path = "v2.rs")] |
| @@ -20,10 +20,10 @@ mod _version; | |||
| 20 | use core::marker::PhantomData; | 20 | use core::marker::PhantomData; |
| 21 | 21 | ||
| 22 | #[allow(unused)] | 22 | #[allow(unused)] |
| 23 | #[cfg(not(any(adc_f3_v2, adc_wba)))] | 23 | #[cfg(not(any(adc_f3v3, adc_wba)))] |
| 24 | pub use _version::*; | 24 | pub use _version::*; |
| 25 | use embassy_hal_internal::{impl_peripheral, PeripheralType}; | 25 | use embassy_hal_internal::{impl_peripheral, PeripheralType}; |
| 26 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 26 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] |
| 27 | use embassy_sync::waitqueue::AtomicWaker; | 27 | use embassy_sync::waitqueue::AtomicWaker; |
| 28 | 28 | ||
| 29 | #[cfg(any(adc_u5, adc_wba))] | 29 | #[cfg(any(adc_u5, adc_wba))] |
| @@ -31,7 +31,7 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 31 | pub mod adc4; | 31 | pub mod adc4; |
| 32 | 32 | ||
| 33 | pub use crate::pac::adc::vals; | 33 | pub use crate::pac::adc::vals; |
| 34 | #[cfg(not(any(adc_f1, adc_f3_v2)))] | 34 | #[cfg(not(any(adc_f1, adc_f3v3)))] |
| 35 | pub use crate::pac::adc::vals::Res as Resolution; | 35 | pub use crate::pac::adc::vals::Res as Resolution; |
| 36 | pub use crate::pac::adc::vals::SampleTime; | 36 | pub use crate::pac::adc::vals::SampleTime; |
| 37 | use crate::peripherals; | 37 | use crate::peripherals; |
| @@ -47,16 +47,16 @@ dma_trait!(RxDma4, adc4::Instance); | |||
| 47 | pub struct Adc<'d, T: Instance> { | 47 | pub struct Adc<'d, T: Instance> { |
| 48 | #[allow(unused)] | 48 | #[allow(unused)] |
| 49 | adc: crate::Peri<'d, T>, | 49 | adc: crate::Peri<'d, T>, |
| 50 | #[cfg(not(any(adc_f3_v2, adc_f3_v1_1, adc_wba)))] | 50 | #[cfg(not(any(adc_f3v3, adc_f3v2, adc_wba)))] |
| 51 | sample_time: SampleTime, | 51 | sample_time: SampleTime, |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 54 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] |
| 55 | pub struct State { | 55 | pub struct State { |
| 56 | pub waker: AtomicWaker, | 56 | pub waker: AtomicWaker, |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 59 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] |
| 60 | impl State { | 60 | impl State { |
| 61 | pub const fn new() -> Self { | 61 | pub const fn new() -> Self { |
| 62 | Self { | 62 | Self { |
| @@ -69,10 +69,10 @@ trait SealedInstance { | |||
| 69 | #[cfg(not(adc_wba))] | 69 | #[cfg(not(adc_wba))] |
| 70 | #[allow(unused)] | 70 | #[allow(unused)] |
| 71 | fn regs() -> crate::pac::adc::Adc; | 71 | fn regs() -> crate::pac::adc::Adc; |
| 72 | #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] | 72 | #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0)))] |
| 73 | #[allow(unused)] | 73 | #[allow(unused)] |
| 74 | fn common_regs() -> crate::pac::adccommon::AdcCommon; | 74 | fn common_regs() -> crate::pac::adccommon::AdcCommon; |
| 75 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 75 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] |
| 76 | fn state() -> &'static State; | 76 | fn state() -> &'static State; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| @@ -100,22 +100,8 @@ pub(crate) fn blocking_delay_us(us: u32) { | |||
| 100 | 100 | ||
| 101 | /// ADC instance. | 101 | /// ADC instance. |
| 102 | #[cfg(not(any( | 102 | #[cfg(not(any( |
| 103 | adc_f1, | 103 | adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, |
| 104 | adc_v1, | 104 | adc_u5, adc_c0, adc_wba, |
| 105 | adc_l0, | ||
| 106 | adc_v2, | ||
| 107 | adc_v3, | ||
| 108 | adc_v4, | ||
| 109 | adc_g4, | ||
| 110 | adc_f3, | ||
| 111 | adc_f3_v1_1, | ||
| 112 | adc_g0, | ||
| 113 | adc_u0, | ||
| 114 | adc_h5, | ||
| 115 | adc_h7rs, | ||
| 116 | adc_u5, | ||
| 117 | adc_c0, | ||
| 118 | adc_wba, | ||
| 119 | )))] | 105 | )))] |
| 120 | #[allow(private_bounds)] | 106 | #[allow(private_bounds)] |
| 121 | pub trait Instance: SealedInstance + crate::PeripheralType { | 107 | pub trait Instance: SealedInstance + crate::PeripheralType { |
| @@ -123,22 +109,8 @@ pub trait Instance: SealedInstance + crate::PeripheralType { | |||
| 123 | } | 109 | } |
| 124 | /// ADC instance. | 110 | /// ADC instance. |
| 125 | #[cfg(any( | 111 | #[cfg(any( |
| 126 | adc_f1, | 112 | adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, |
| 127 | adc_v1, | 113 | adc_u5, adc_c0, adc_wba, |
| 128 | adc_l0, | ||
| 129 | adc_v2, | ||
| 130 | adc_v3, | ||
| 131 | adc_v4, | ||
| 132 | adc_g4, | ||
| 133 | adc_f3, | ||
| 134 | adc_f3_v1_1, | ||
| 135 | adc_g0, | ||
| 136 | adc_u0, | ||
| 137 | adc_h5, | ||
| 138 | adc_h7rs, | ||
| 139 | adc_u5, | ||
| 140 | adc_c0, | ||
| 141 | adc_wba, | ||
| 142 | ))] | 114 | ))] |
| 143 | #[allow(private_bounds)] | 115 | #[allow(private_bounds)] |
| 144 | pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { | 116 | pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { |
| @@ -258,12 +230,12 @@ foreach_adc!( | |||
| 258 | crate::pac::$inst | 230 | crate::pac::$inst |
| 259 | } | 231 | } |
| 260 | 232 | ||
| 261 | #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0, adc_u5, adc_wba)))] | 233 | #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3v3, adc_f3v2, adc_g0, adc_u5, adc_wba)))] |
| 262 | fn common_regs() -> crate::pac::adccommon::AdcCommon { | 234 | fn common_regs() -> crate::pac::adccommon::AdcCommon { |
| 263 | return crate::pac::$common_inst | 235 | return crate::pac::$common_inst |
| 264 | } | 236 | } |
| 265 | 237 | ||
| 266 | #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] | 238 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] |
| 267 | fn state() -> &'static State { | 239 | fn state() -> &'static State { |
| 268 | static STATE: State = State::new(); | 240 | static STATE: State = State::new(); |
| 269 | &STATE | 241 | &STATE |
| @@ -295,7 +267,7 @@ macro_rules! impl_adc_pin { | |||
| 295 | /// Get the maximum reading value for this resolution. | 267 | /// Get the maximum reading value for this resolution. |
| 296 | /// | 268 | /// |
| 297 | /// This is `2**n - 1`. | 269 | /// This is `2**n - 1`. |
| 298 | #[cfg(not(any(adc_f1, adc_f3_v2)))] | 270 | #[cfg(not(any(adc_f1, adc_f3v3)))] |
| 299 | pub const fn resolution_to_max_count(res: Resolution) -> u32 { | 271 | pub const fn resolution_to_max_count(res: Resolution) -> u32 { |
| 300 | match res { | 272 | match res { |
| 301 | #[cfg(adc_v4)] | 273 | #[cfg(adc_v4)] |
| @@ -309,7 +281,7 @@ pub const fn resolution_to_max_count(res: Resolution) -> u32 { | |||
| 309 | Resolution::BITS12 => (1 << 12) - 1, | 281 | Resolution::BITS12 => (1 << 12) - 1, |
| 310 | Resolution::BITS10 => (1 << 10) - 1, | 282 | Resolution::BITS10 => (1 << 10) - 1, |
| 311 | Resolution::BITS8 => (1 << 8) - 1, | 283 | Resolution::BITS8 => (1 << 8) - 1, |
| 312 | #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_c0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))] | 284 | #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_c0, adc_g0, adc_f3v1, adc_f3v2, adc_h5))] |
| 313 | Resolution::BITS6 => (1 << 6) - 1, | 285 | Resolution::BITS6 => (1 << 6) - 1, |
| 314 | #[allow(unreachable_patterns)] | 286 | #[allow(unreachable_patterns)] |
| 315 | _ => core::unreachable!(), | 287 | _ => core::unreachable!(), |
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index a51d21bb0..0c4ab56e3 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs | |||
| @@ -27,7 +27,8 @@ enum Function { | |||
| 27 | Transmit, | 27 | Transmit, |
| 28 | /// Receive audio data | 28 | /// Receive audio data |
| 29 | Receive, | 29 | Receive, |
| 30 | #[cfg(spi_v3)] | 30 | #[cfg(any(spi_v4, spi_v5))] |
| 31 | |||
| 31 | /// Transmit and Receive audio data | 32 | /// Transmit and Receive audio data |
| 32 | FullDuplex, | 33 | FullDuplex, |
| 33 | } | 34 | } |
| @@ -72,7 +73,6 @@ impl From<ringbuffer::Error> for Error { | |||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | impl Standard { | 75 | impl Standard { |
| 75 | #[cfg(any(spi_v1, spi_v3, spi_f1))] | ||
| 76 | const fn i2sstd(&self) -> vals::I2sstd { | 76 | const fn i2sstd(&self) -> vals::I2sstd { |
| 77 | match self { | 77 | match self { |
| 78 | Standard::Philips => vals::I2sstd::PHILIPS, | 78 | Standard::Philips => vals::I2sstd::PHILIPS, |
| @@ -83,7 +83,6 @@ impl Standard { | |||
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | #[cfg(any(spi_v1, spi_v3, spi_f1))] | ||
| 87 | const fn pcmsync(&self) -> vals::Pcmsync { | 86 | const fn pcmsync(&self) -> vals::Pcmsync { |
| 88 | match self { | 87 | match self { |
| 89 | Standard::PcmLongSync => vals::Pcmsync::LONG, | 88 | Standard::PcmLongSync => vals::Pcmsync::LONG, |
| @@ -106,7 +105,6 @@ pub enum Format { | |||
| 106 | } | 105 | } |
| 107 | 106 | ||
| 108 | impl Format { | 107 | impl Format { |
| 109 | #[cfg(any(spi_v1, spi_v3, spi_f1))] | ||
| 110 | const fn datlen(&self) -> vals::Datlen { | 108 | const fn datlen(&self) -> vals::Datlen { |
| 111 | match self { | 109 | match self { |
| 112 | Format::Data16Channel16 => vals::Datlen::BITS16, | 110 | Format::Data16Channel16 => vals::Datlen::BITS16, |
| @@ -116,7 +114,6 @@ impl Format { | |||
| 116 | } | 114 | } |
| 117 | } | 115 | } |
| 118 | 116 | ||
| 119 | #[cfg(any(spi_v1, spi_v3, spi_f1))] | ||
| 120 | const fn chlen(&self) -> vals::Chlen { | 117 | const fn chlen(&self) -> vals::Chlen { |
| 121 | match self { | 118 | match self { |
| 122 | Format::Data16Channel16 => vals::Chlen::BITS16, | 119 | Format::Data16Channel16 => vals::Chlen::BITS16, |
| @@ -137,7 +134,6 @@ pub enum ClockPolarity { | |||
| 137 | } | 134 | } |
| 138 | 135 | ||
| 139 | impl ClockPolarity { | 136 | impl ClockPolarity { |
| 140 | #[cfg(any(spi_v1, spi_v3, spi_f1))] | ||
| 141 | const fn ckpol(&self) -> vals::Ckpol { | 137 | const fn ckpol(&self) -> vals::Ckpol { |
| 142 | match self { | 138 | match self { |
| 143 | ClockPolarity::IdleHigh => vals::Ckpol::IDLE_HIGH, | 139 | ClockPolarity::IdleHigh => vals::Ckpol::IDLE_HIGH, |
| @@ -314,7 +310,8 @@ impl<'d, W: Word> I2S<'d, W> { | |||
| 314 | ) | 310 | ) |
| 315 | } | 311 | } |
| 316 | 312 | ||
| 317 | #[cfg(spi_v3)] | 313 | #[cfg(any(spi_v4, spi_v5))] |
| 314 | |||
| 318 | /// Create a full duplex driver. | 315 | /// Create a full duplex driver. |
| 319 | pub fn new_full_duplex<T: Instance>( | 316 | pub fn new_full_duplex<T: Instance>( |
| 320 | peri: Peri<'d, T>, | 317 | peri: Peri<'d, T>, |
| @@ -357,7 +354,7 @@ impl<'d, W: Word> I2S<'d, W> { | |||
| 357 | if let Some(rx_ring_buffer) = &mut self.rx_ring_buffer { | 354 | if let Some(rx_ring_buffer) = &mut self.rx_ring_buffer { |
| 358 | rx_ring_buffer.start(); | 355 | rx_ring_buffer.start(); |
| 359 | // SPIv3 clears rxfifo on SPE=0 | 356 | // SPIv3 clears rxfifo on SPE=0 |
| 360 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 357 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 361 | flush_rx_fifo(self.spi.info.regs); | 358 | flush_rx_fifo(self.spi.info.regs); |
| 362 | 359 | ||
| 363 | set_rxdmaen(self.spi.info.regs, true); | 360 | set_rxdmaen(self.spi.info.regs, true); |
| @@ -365,7 +362,7 @@ impl<'d, W: Word> I2S<'d, W> { | |||
| 365 | self.spi.info.regs.cr1().modify(|w| { | 362 | self.spi.info.regs.cr1().modify(|w| { |
| 366 | w.set_spe(true); | 363 | w.set_spe(true); |
| 367 | }); | 364 | }); |
| 368 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 365 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 369 | self.spi.info.regs.cr1().modify(|w| { | 366 | self.spi.info.regs.cr1().modify(|w| { |
| 370 | w.set_cstart(true); | 367 | w.set_cstart(true); |
| 371 | }); | 368 | }); |
| @@ -404,7 +401,7 @@ impl<'d, W: Word> I2S<'d, W> { | |||
| 404 | 401 | ||
| 405 | join(rx_f, tx_f).await; | 402 | join(rx_f, tx_f).await; |
| 406 | 403 | ||
| 407 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 404 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 408 | { | 405 | { |
| 409 | if let Mode::Master = self.mode { | 406 | if let Mode::Master = self.mode { |
| 410 | regs.cr1().modify(|w| { | 407 | regs.cr1().modify(|w| { |
| @@ -492,103 +489,98 @@ impl<'d, W: Word> I2S<'d, W> { | |||
| 492 | 489 | ||
| 493 | let (odd, div) = compute_baud_rate(pclk, config.frequency, config.master_clock, config.format); | 490 | let (odd, div) = compute_baud_rate(pclk, config.frequency, config.master_clock, config.format); |
| 494 | 491 | ||
| 495 | #[cfg(any(spi_v1, spi_v3, spi_f1))] | 492 | #[cfg(any(spi_v4, spi_v5))] |
| 496 | { | 493 | { |
| 497 | #[cfg(spi_v3)] | 494 | regs.cr1().modify(|w| w.set_spe(false)); |
| 498 | { | ||
| 499 | regs.cr1().modify(|w| w.set_spe(false)); | ||
| 500 | 495 | ||
| 501 | reset_incompatible_bitfields::<T>(); | 496 | reset_incompatible_bitfields::<T>(); |
| 502 | } | 497 | } |
| 503 | 498 | ||
| 504 | use stm32_metapac::spi::vals::{I2scfg, Odd}; | 499 | use stm32_metapac::spi::vals::{I2scfg, Odd}; |
| 505 | 500 | ||
| 506 | // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR/SPI_I2SCFGR register to define the serial clock baud | 501 | // 1. Select the I2SDIV[7:0] bits in the SPI_I2SPR/SPI_I2SCFGR register to define the serial clock baud |
| 507 | // rate to reach the proper audio sample frequency. The ODD bit in the | 502 | // rate to reach the proper audio sample frequency. The ODD bit in the |
| 508 | // SPI_I2SPR/SPI_I2SCFGR register also has to be defined. | 503 | // SPI_I2SPR/SPI_I2SCFGR register also has to be defined. |
| 509 | |||
| 510 | // 2. Select the CKPOL bit to define the steady level for the communication clock. Set the | ||
| 511 | // MCKOE bit in the SPI_I2SPR/SPI_I2SCFGR register if the master clock MCK needs to be provided to | ||
| 512 | // the external DAC/ADC audio component (the I2SDIV and ODD values should be | ||
| 513 | // computed depending on the state of the MCK output, for more details refer to | ||
| 514 | // Section 28.4.4: Clock generator). | ||
| 515 | |||
| 516 | // 3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the | ||
| 517 | // I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the | ||
| 518 | // DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit. | ||
| 519 | // Select also the I2S master mode and direction (Transmitter or Receiver) through the | ||
| 520 | // I2SCFG[1:0] bits in the SPI_I2SCFGR register. | ||
| 521 | |||
| 522 | // 4. If needed, select all the potential interruption sources and the DMA capabilities by | ||
| 523 | // writing the SPI_CR2 register. | ||
| 524 | |||
| 525 | // 5. The I2SE bit in SPI_I2SCFGR register must be set. | ||
| 526 | |||
| 527 | let clk_reg = { | ||
| 528 | #[cfg(any(spi_v1, spi_f1))] | ||
| 529 | { | ||
| 530 | regs.i2spr() | ||
| 531 | } | ||
| 532 | #[cfg(spi_v3)] | ||
| 533 | { | ||
| 534 | regs.i2scfgr() | ||
| 535 | } | ||
| 536 | }; | ||
| 537 | |||
| 538 | clk_reg.modify(|w| { | ||
| 539 | w.set_i2sdiv(div); | ||
| 540 | w.set_odd(match odd { | ||
| 541 | true => Odd::ODD, | ||
| 542 | false => Odd::EVEN, | ||
| 543 | }); | ||
| 544 | 504 | ||
| 545 | w.set_mckoe(config.master_clock); | 505 | // 2. Select the CKPOL bit to define the steady level for the communication clock. Set the |
| 506 | // MCKOE bit in the SPI_I2SPR/SPI_I2SCFGR register if the master clock MCK needs to be provided to | ||
| 507 | // the external DAC/ADC audio component (the I2SDIV and ODD values should be | ||
| 508 | // computed depending on the state of the MCK output, for more details refer to | ||
| 509 | // Section 28.4.4: Clock generator). | ||
| 510 | |||
| 511 | // 3. Set the I2SMOD bit in SPI_I2SCFGR to activate the I2S functionalities and choose the | ||
| 512 | // I2S standard through the I2SSTD[1:0] and PCMSYNC bits, the data length through the | ||
| 513 | // DATLEN[1:0] bits and the number of bits per channel by configuring the CHLEN bit. | ||
| 514 | // Select also the I2S master mode and direction (Transmitter or Receiver) through the | ||
| 515 | // I2SCFG[1:0] bits in the SPI_I2SCFGR register. | ||
| 516 | |||
| 517 | // 4. If needed, select all the potential interruption sources and the DMA capabilities by | ||
| 518 | // writing the SPI_CR2 register. | ||
| 519 | |||
| 520 | // 5. The I2SE bit in SPI_I2SCFGR register must be set. | ||
| 521 | |||
| 522 | let clk_reg = { | ||
| 523 | #[cfg(any(spi_v1, spi_v2, spi_v3))] | ||
| 524 | { | ||
| 525 | regs.i2spr() | ||
| 526 | } | ||
| 527 | #[cfg(any(spi_v4, spi_v5))] | ||
| 528 | { | ||
| 529 | regs.i2scfgr() | ||
| 530 | } | ||
| 531 | }; | ||
| 532 | |||
| 533 | clk_reg.modify(|w| { | ||
| 534 | w.set_i2sdiv(div); | ||
| 535 | w.set_odd(match odd { | ||
| 536 | true => Odd::ODD, | ||
| 537 | false => Odd::EVEN, | ||
| 546 | }); | 538 | }); |
| 547 | 539 | ||
| 548 | regs.i2scfgr().modify(|w| { | 540 | w.set_mckoe(config.master_clock); |
| 549 | w.set_ckpol(config.clock_polarity.ckpol()); | 541 | }); |
| 550 | 542 | ||
| 551 | w.set_i2smod(true); | 543 | regs.i2scfgr().modify(|w| { |
| 544 | w.set_ckpol(config.clock_polarity.ckpol()); | ||
| 552 | 545 | ||
| 553 | w.set_i2sstd(config.standard.i2sstd()); | 546 | w.set_i2smod(true); |
| 554 | w.set_pcmsync(config.standard.pcmsync()); | ||
| 555 | 547 | ||
| 556 | w.set_datlen(config.format.datlen()); | 548 | w.set_i2sstd(config.standard.i2sstd()); |
| 557 | w.set_chlen(config.format.chlen()); | 549 | w.set_pcmsync(config.standard.pcmsync()); |
| 558 | 550 | ||
| 559 | w.set_i2scfg(match (config.mode, function) { | 551 | w.set_datlen(config.format.datlen()); |
| 560 | (Mode::Master, Function::Transmit) => I2scfg::MASTER_TX, | 552 | w.set_chlen(config.format.chlen()); |
| 561 | (Mode::Master, Function::Receive) => I2scfg::MASTER_RX, | ||
| 562 | #[cfg(spi_v3)] | ||
| 563 | (Mode::Master, Function::FullDuplex) => I2scfg::MASTER_FULL_DUPLEX, | ||
| 564 | (Mode::Slave, Function::Transmit) => I2scfg::SLAVE_TX, | ||
| 565 | (Mode::Slave, Function::Receive) => I2scfg::SLAVE_RX, | ||
| 566 | #[cfg(spi_v3)] | ||
| 567 | (Mode::Slave, Function::FullDuplex) => I2scfg::SLAVE_FULL_DUPLEX, | ||
| 568 | }); | ||
| 569 | 553 | ||
| 570 | #[cfg(any(spi_v1, spi_f1))] | 554 | w.set_i2scfg(match (config.mode, function) { |
| 571 | w.set_i2se(true); | 555 | (Mode::Master, Function::Transmit) => I2scfg::MASTER_TX, |
| 556 | (Mode::Master, Function::Receive) => I2scfg::MASTER_RX, | ||
| 557 | #[cfg(any(spi_v4, spi_v5))] | ||
| 558 | (Mode::Master, Function::FullDuplex) => I2scfg::MASTER_FULL_DUPLEX, | ||
| 559 | (Mode::Slave, Function::Transmit) => I2scfg::SLAVE_TX, | ||
| 560 | (Mode::Slave, Function::Receive) => I2scfg::SLAVE_RX, | ||
| 561 | #[cfg(any(spi_v4, spi_v5))] | ||
| 562 | (Mode::Slave, Function::FullDuplex) => I2scfg::SLAVE_FULL_DUPLEX, | ||
| 572 | }); | 563 | }); |
| 573 | 564 | ||
| 574 | let mut opts = TransferOptions::default(); | 565 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 575 | opts.half_transfer_ir = true; | 566 | w.set_i2se(true); |
| 576 | 567 | }); | |
| 577 | Self { | 568 | |
| 578 | mode: config.mode, | 569 | let mut opts = TransferOptions::default(); |
| 579 | spi, | 570 | opts.half_transfer_ir = true; |
| 580 | txsd: txsd.map(|w| w.into()), | 571 | |
| 581 | rxsd: rxsd.map(|w| w.into()), | 572 | Self { |
| 582 | ws: Some(ws.into()), | 573 | mode: config.mode, |
| 583 | ck: Some(ck.into()), | 574 | spi, |
| 584 | mck: mck.map(|w| w.into()), | 575 | txsd: txsd.map(|w| w.into()), |
| 585 | tx_ring_buffer: txdma.map(|(ch, buf)| unsafe { | 576 | rxsd: rxsd.map(|w| w.into()), |
| 586 | WritableRingBuffer::new(ch.channel, ch.request, regs.tx_ptr(), buf, opts) | 577 | ws: Some(ws.into()), |
| 587 | }), | 578 | ck: Some(ck.into()), |
| 588 | rx_ring_buffer: rxdma.map(|(ch, buf)| unsafe { | 579 | mck: mck.map(|w| w.into()), |
| 589 | ReadableRingBuffer::new(ch.channel, ch.request, regs.rx_ptr(), buf, opts) | 580 | tx_ring_buffer: txdma |
| 590 | }), | 581 | .map(|(ch, buf)| unsafe { WritableRingBuffer::new(ch.channel, ch.request, regs.tx_ptr(), buf, opts) }), |
| 591 | } | 582 | rx_ring_buffer: rxdma |
| 583 | .map(|(ch, buf)| unsafe { ReadableRingBuffer::new(ch.channel, ch.request, regs.rx_ptr(), buf, opts) }), | ||
| 592 | } | 584 | } |
| 593 | } | 585 | } |
| 594 | } | 586 | } |
| @@ -639,7 +631,8 @@ fn compute_baud_rate(i2s_clock: Hertz, request_freq: Hertz, mclk: bool, data_for | |||
| 639 | } | 631 | } |
| 640 | } | 632 | } |
| 641 | 633 | ||
| 642 | #[cfg(spi_v3)] | 634 | #[cfg(any(spi_v4, spi_v5))] |
| 635 | |||
| 643 | // The STM32H7 reference manual specifies that any incompatible bitfields should be reset | 636 | // The STM32H7 reference manual specifies that any incompatible bitfields should be reset |
| 644 | // to their reset values while operating in I2S mode. | 637 | // to their reset values while operating in I2S mode. |
| 645 | fn reset_incompatible_bitfields<T: Instance>() { | 638 | fn reset_incompatible_bitfields<T: Instance>() { |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 3be98c462..7e0f7884e 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -87,7 +87,7 @@ pub mod hsem; | |||
| 87 | pub mod hspi; | 87 | pub mod hspi; |
| 88 | #[cfg(i2c)] | 88 | #[cfg(i2c)] |
| 89 | pub mod i2c; | 89 | pub mod i2c; |
| 90 | #[cfg(any(all(spi_v1, rcc_f4), spi_v3))] | 90 | #[cfg(any(spi_v1_i2s, spi_v2_i2s, spi_v3_i2s, spi_v4_i2s, spi_v5_i2s))] |
| 91 | pub mod i2s; | 91 | pub mod i2s; |
| 92 | #[cfg(stm32wb)] | 92 | #[cfg(stm32wb)] |
| 93 | pub mod ipcc; | 93 | pub mod ipcc; |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 4c5308eba..a49ebcbee 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -174,7 +174,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 174 | self.info.rcc.enable_and_reset(); | 174 | self.info.rcc.enable_and_reset(); |
| 175 | 175 | ||
| 176 | let regs = self.info.regs; | 176 | let regs = self.info.regs; |
| 177 | #[cfg(any(spi_v1, spi_f1))] | 177 | #[cfg(any(spi_v1, spi_v2))] |
| 178 | { | 178 | { |
| 179 | regs.cr2().modify(|w| { | 179 | regs.cr2().modify(|w| { |
| 180 | w.set_ssoe(false); | 180 | w.set_ssoe(false); |
| @@ -198,7 +198,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 198 | w.set_dff(<u8 as SealedWord>::CONFIG) | 198 | w.set_dff(<u8 as SealedWord>::CONFIG) |
| 199 | }); | 199 | }); |
| 200 | } | 200 | } |
| 201 | #[cfg(spi_v2)] | 201 | #[cfg(spi_v3)] |
| 202 | { | 202 | { |
| 203 | regs.cr2().modify(|w| { | 203 | regs.cr2().modify(|w| { |
| 204 | let (ds, frxth) = <u8 as SealedWord>::CONFIG; | 204 | let (ds, frxth) = <u8 as SealedWord>::CONFIG; |
| @@ -220,7 +220,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 220 | w.set_spe(true); | 220 | w.set_spe(true); |
| 221 | }); | 221 | }); |
| 222 | } | 222 | } |
| 223 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 223 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 224 | { | 224 | { |
| 225 | regs.ifcr().write(|w| w.0 = 0xffff_ffff); | 225 | regs.ifcr().write(|w| w.0 = 0xffff_ffff); |
| 226 | regs.cfg2().modify(|w| { | 226 | regs.cfg2().modify(|w| { |
| @@ -274,7 +274,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 274 | } | 274 | } |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 277 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 278 | self.info.regs.cr1().modify(|w| { | 278 | self.info.regs.cr1().modify(|w| { |
| 279 | w.set_cpha(cpha); | 279 | w.set_cpha(cpha); |
| 280 | w.set_cpol(cpol); | 280 | w.set_cpol(cpol); |
| @@ -282,7 +282,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 282 | w.set_lsbfirst(lsbfirst); | 282 | w.set_lsbfirst(lsbfirst); |
| 283 | }); | 283 | }); |
| 284 | 284 | ||
| 285 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 285 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 286 | { | 286 | { |
| 287 | self.info.regs.cr1().modify(|w| { | 287 | self.info.regs.cr1().modify(|w| { |
| 288 | w.set_spe(false); | 288 | w.set_spe(false); |
| @@ -306,11 +306,11 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 306 | 306 | ||
| 307 | /// Get current SPI configuration. | 307 | /// Get current SPI configuration. |
| 308 | pub fn get_current_config(&self) -> Config { | 308 | pub fn get_current_config(&self) -> Config { |
| 309 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 309 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 310 | let cfg = self.info.regs.cr1().read(); | 310 | let cfg = self.info.regs.cr1().read(); |
| 311 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 311 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 312 | let cfg = self.info.regs.cfg2().read(); | 312 | let cfg = self.info.regs.cfg2().read(); |
| 313 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 313 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 314 | let cfg1 = self.info.regs.cfg1().read(); | 314 | let cfg1 = self.info.regs.cfg1().read(); |
| 315 | 315 | ||
| 316 | let polarity = if cfg.cpol() == vals::Cpol::IDLE_LOW { | 316 | let polarity = if cfg.cpol() == vals::Cpol::IDLE_LOW { |
| @@ -335,9 +335,9 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 335 | Some(pin) => pin.pull(), | 335 | Some(pin) => pin.pull(), |
| 336 | }; | 336 | }; |
| 337 | 337 | ||
| 338 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 338 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 339 | let br = cfg.br(); | 339 | let br = cfg.br(); |
| 340 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 340 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 341 | let br = cfg1.mbr(); | 341 | let br = cfg1.mbr(); |
| 342 | 342 | ||
| 343 | let frequency = compute_frequency(self.kernel_clock, br); | 343 | let frequency = compute_frequency(self.kernel_clock, br); |
| @@ -360,16 +360,16 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 360 | w.set_spe(false); | 360 | w.set_spe(false); |
| 361 | }); | 361 | }); |
| 362 | 362 | ||
| 363 | #[cfg(any(spi_v1, spi_f1))] | 363 | #[cfg(any(spi_v1, spi_v2))] |
| 364 | self.info.regs.cr1().modify(|reg| { | 364 | self.info.regs.cr1().modify(|reg| { |
| 365 | reg.set_dff(word_size); | 365 | reg.set_dff(word_size); |
| 366 | }); | 366 | }); |
| 367 | #[cfg(spi_v2)] | 367 | #[cfg(spi_v3)] |
| 368 | self.info.regs.cr2().modify(|w| { | 368 | self.info.regs.cr2().modify(|w| { |
| 369 | w.set_frxth(word_size.1); | 369 | w.set_frxth(word_size.1); |
| 370 | w.set_ds(word_size.0); | 370 | w.set_ds(word_size.0); |
| 371 | }); | 371 | }); |
| 372 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 372 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 373 | self.info.regs.cfg1().modify(|w| { | 373 | self.info.regs.cfg1().modify(|w| { |
| 374 | w.set_dsize(word_size); | 374 | w.set_dsize(word_size); |
| 375 | }); | 375 | }); |
| @@ -380,7 +380,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 380 | /// Blocking write. | 380 | /// Blocking write. |
| 381 | pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { | 381 | pub fn blocking_write<W: Word>(&mut self, words: &[W]) -> Result<(), Error> { |
| 382 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? | 382 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? |
| 383 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 383 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 384 | self.info.regs.cr1().modify(|w| w.set_spe(false)); | 384 | self.info.regs.cr1().modify(|w| w.set_spe(false)); |
| 385 | self.set_word_size(W::CONFIG); | 385 | self.set_word_size(W::CONFIG); |
| 386 | self.info.regs.cr1().modify(|w| w.set_spe(true)); | 386 | self.info.regs.cr1().modify(|w| w.set_spe(true)); |
| @@ -391,7 +391,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 391 | // This is the case when the SPI has been created with `new_(blocking_?)txonly_nosck`. | 391 | // This is the case when the SPI has been created with `new_(blocking_?)txonly_nosck`. |
| 392 | // See https://github.com/embassy-rs/embassy/issues/2902 | 392 | // See https://github.com/embassy-rs/embassy/issues/2902 |
| 393 | // This is not documented as an errata by ST, and I've been unable to find anything online... | 393 | // This is not documented as an errata by ST, and I've been unable to find anything online... |
| 394 | #[cfg(not(any(spi_v1, spi_f1)))] | 394 | #[cfg(not(any(spi_v1, spi_v2)))] |
| 395 | write_word(self.info.regs, *word)?; | 395 | write_word(self.info.regs, *word)?; |
| 396 | 396 | ||
| 397 | // if we're doing tx only, after writing the last byte to FIFO we have to wait | 397 | // if we're doing tx only, after writing the last byte to FIFO we have to wait |
| @@ -401,14 +401,14 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 401 | // Luckily this doesn't affect SPIv2+. | 401 | // Luckily this doesn't affect SPIv2+. |
| 402 | // See http://efton.sk/STM32/gotcha/g68.html | 402 | // See http://efton.sk/STM32/gotcha/g68.html |
| 403 | // ST doesn't seem to document this in errata sheets (?) | 403 | // ST doesn't seem to document this in errata sheets (?) |
| 404 | #[cfg(any(spi_v1, spi_f1))] | 404 | #[cfg(any(spi_v1, spi_v2))] |
| 405 | transfer_word(self.info.regs, *word)?; | 405 | transfer_word(self.info.regs, *word)?; |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | // wait until last word is transmitted. (except on v1, see above) | 408 | // wait until last word is transmitted. (except on v1, see above) |
| 409 | #[cfg(not(any(spi_v1, spi_f1, spi_v2)))] | 409 | #[cfg(not(any(spi_v1, spi_v2, spi_v3)))] |
| 410 | while !self.info.regs.sr().read().txc() {} | 410 | while !self.info.regs.sr().read().txc() {} |
| 411 | #[cfg(spi_v2)] | 411 | #[cfg(spi_v3)] |
| 412 | while self.info.regs.sr().read().bsy() {} | 412 | while self.info.regs.sr().read().bsy() {} |
| 413 | 413 | ||
| 414 | Ok(()) | 414 | Ok(()) |
| @@ -417,7 +417,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 417 | /// Blocking read. | 417 | /// Blocking read. |
| 418 | pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { | 418 | pub fn blocking_read<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { |
| 419 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? | 419 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? |
| 420 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 420 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 421 | self.info.regs.cr1().modify(|w| w.set_spe(false)); | 421 | self.info.regs.cr1().modify(|w| w.set_spe(false)); |
| 422 | self.set_word_size(W::CONFIG); | 422 | self.set_word_size(W::CONFIG); |
| 423 | self.info.regs.cr1().modify(|w| w.set_spe(true)); | 423 | self.info.regs.cr1().modify(|w| w.set_spe(true)); |
| @@ -433,7 +433,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 433 | /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time. | 433 | /// This writes the contents of `data` on MOSI, and puts the received data on MISO in `data`, at the same time. |
| 434 | pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { | 434 | pub fn blocking_transfer_in_place<W: Word>(&mut self, words: &mut [W]) -> Result<(), Error> { |
| 435 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? | 435 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? |
| 436 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 436 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 437 | self.info.regs.cr1().modify(|w| w.set_spe(false)); | 437 | self.info.regs.cr1().modify(|w| w.set_spe(false)); |
| 438 | self.set_word_size(W::CONFIG); | 438 | self.set_word_size(W::CONFIG); |
| 439 | self.info.regs.cr1().modify(|w| w.set_spe(true)); | 439 | self.info.regs.cr1().modify(|w| w.set_spe(true)); |
| @@ -452,7 +452,7 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 452 | /// If `write` is shorter it is padded with zero bytes. | 452 | /// If `write` is shorter it is padded with zero bytes. |
| 453 | pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { | 453 | pub fn blocking_transfer<W: Word>(&mut self, read: &mut [W], write: &[W]) -> Result<(), Error> { |
| 454 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? | 454 | // needed in v3+ to avoid overrun causing the SPI RX state machine to get stuck...? |
| 455 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 455 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 456 | self.info.regs.cr1().modify(|w| w.set_spe(false)); | 456 | self.info.regs.cr1().modify(|w| w.set_spe(false)); |
| 457 | self.set_word_size(W::CONFIG); | 457 | self.set_word_size(W::CONFIG); |
| 458 | self.info.regs.cr1().modify(|w| w.set_spe(true)); | 458 | self.info.regs.cr1().modify(|w| w.set_spe(true)); |
| @@ -572,7 +572,7 @@ impl<'d> Spi<'d, Async> { | |||
| 572 | peri: Peri<'d, T>, | 572 | peri: Peri<'d, T>, |
| 573 | sck: Peri<'d, impl SckPin<T>>, | 573 | sck: Peri<'d, impl SckPin<T>>, |
| 574 | miso: Peri<'d, impl MisoPin<T>>, | 574 | miso: Peri<'d, impl MisoPin<T>>, |
| 575 | #[cfg(any(spi_v1, spi_f1, spi_v2))] tx_dma: Peri<'d, impl TxDma<T>>, | 575 | #[cfg(any(spi_v1, spi_v2, spi_v3))] tx_dma: Peri<'d, impl TxDma<T>>, |
| 576 | rx_dma: Peri<'d, impl RxDma<T>>, | 576 | rx_dma: Peri<'d, impl RxDma<T>>, |
| 577 | config: Config, | 577 | config: Config, |
| 578 | ) -> Self { | 578 | ) -> Self { |
| @@ -581,9 +581,9 @@ impl<'d> Spi<'d, Async> { | |||
| 581 | new_pin!(sck, config.sck_af()), | 581 | new_pin!(sck, config.sck_af()), |
| 582 | None, | 582 | None, |
| 583 | new_pin!(miso, AfType::input(config.miso_pull)), | 583 | new_pin!(miso, AfType::input(config.miso_pull)), |
| 584 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 584 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 585 | new_dma!(tx_dma), | 585 | new_dma!(tx_dma), |
| 586 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 586 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 587 | None, | 587 | None, |
| 588 | new_dma!(rx_dma), | 588 | new_dma!(rx_dma), |
| 589 | config, | 589 | config, |
| @@ -677,7 +677,7 @@ impl<'d> Spi<'d, Async> { | |||
| 677 | self.info.regs.cr1().modify(|w| { | 677 | self.info.regs.cr1().modify(|w| { |
| 678 | w.set_spe(true); | 678 | w.set_spe(true); |
| 679 | }); | 679 | }); |
| 680 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 680 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 681 | self.info.regs.cr1().modify(|w| { | 681 | self.info.regs.cr1().modify(|w| { |
| 682 | w.set_cstart(true); | 682 | w.set_cstart(true); |
| 683 | }); | 683 | }); |
| @@ -690,7 +690,7 @@ impl<'d> Spi<'d, Async> { | |||
| 690 | } | 690 | } |
| 691 | 691 | ||
| 692 | /// SPI read, using DMA. | 692 | /// SPI read, using DMA. |
| 693 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 693 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 694 | pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { | 694 | pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { |
| 695 | if data.is_empty() { | 695 | if data.is_empty() { |
| 696 | return Ok(()); | 696 | return Ok(()); |
| @@ -710,7 +710,7 @@ impl<'d> Spi<'d, Async> { | |||
| 710 | prev | 710 | prev |
| 711 | }); | 711 | }); |
| 712 | 712 | ||
| 713 | #[cfg(spi_v3)] | 713 | #[cfg(spi_v4)] |
| 714 | let i2scfg = regs.i2scfgr().modify(|w| { | 714 | let i2scfg = regs.i2scfgr().modify(|w| { |
| 715 | w.i2smod().then(|| { | 715 | w.i2smod().then(|| { |
| 716 | let prev = w.i2scfg(); | 716 | let prev = w.i2scfg(); |
| @@ -766,7 +766,7 @@ impl<'d> Spi<'d, Async> { | |||
| 766 | w.set_tsize(0); | 766 | w.set_tsize(0); |
| 767 | }); | 767 | }); |
| 768 | 768 | ||
| 769 | #[cfg(spi_v3)] | 769 | #[cfg(spi_v4)] |
| 770 | if let Some(i2scfg) = i2scfg { | 770 | if let Some(i2scfg) = i2scfg { |
| 771 | regs.i2scfgr().modify(|w| { | 771 | regs.i2scfgr().modify(|w| { |
| 772 | w.set_i2scfg(i2scfg); | 772 | w.set_i2scfg(i2scfg); |
| @@ -777,7 +777,7 @@ impl<'d> Spi<'d, Async> { | |||
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | /// SPI read, using DMA. | 779 | /// SPI read, using DMA. |
| 780 | #[cfg(any(spi_v1, spi_f1, spi_v2))] | 780 | #[cfg(any(spi_v1, spi_v2, spi_v3))] |
| 781 | pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { | 781 | pub async fn read<W: Word>(&mut self, data: &mut [W]) -> Result<(), Error> { |
| 782 | if data.is_empty() { | 782 | if data.is_empty() { |
| 783 | return Ok(()); | 783 | return Ok(()); |
| @@ -790,7 +790,7 @@ impl<'d> Spi<'d, Async> { | |||
| 790 | self.set_word_size(W::CONFIG); | 790 | self.set_word_size(W::CONFIG); |
| 791 | 791 | ||
| 792 | // SPIv3 clears rxfifo on SPE=0 | 792 | // SPIv3 clears rxfifo on SPE=0 |
| 793 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 793 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 794 | flush_rx_fifo(self.info.regs); | 794 | flush_rx_fifo(self.info.regs); |
| 795 | 795 | ||
| 796 | set_rxdmaen(self.info.regs, true); | 796 | set_rxdmaen(self.info.regs, true); |
| @@ -813,7 +813,7 @@ impl<'d> Spi<'d, Async> { | |||
| 813 | self.info.regs.cr1().modify(|w| { | 813 | self.info.regs.cr1().modify(|w| { |
| 814 | w.set_spe(true); | 814 | w.set_spe(true); |
| 815 | }); | 815 | }); |
| 816 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 816 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 817 | self.info.regs.cr1().modify(|w| { | 817 | self.info.regs.cr1().modify(|w| { |
| 818 | w.set_cstart(true); | 818 | w.set_cstart(true); |
| 819 | }); | 819 | }); |
| @@ -838,7 +838,7 @@ impl<'d> Spi<'d, Async> { | |||
| 838 | self.set_word_size(W::CONFIG); | 838 | self.set_word_size(W::CONFIG); |
| 839 | 839 | ||
| 840 | // SPIv3 clears rxfifo on SPE=0 | 840 | // SPIv3 clears rxfifo on SPE=0 |
| 841 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 841 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 842 | flush_rx_fifo(self.info.regs); | 842 | flush_rx_fifo(self.info.regs); |
| 843 | 843 | ||
| 844 | set_rxdmaen(self.info.regs, true); | 844 | set_rxdmaen(self.info.regs, true); |
| @@ -858,7 +858,7 @@ impl<'d> Spi<'d, Async> { | |||
| 858 | self.info.regs.cr1().modify(|w| { | 858 | self.info.regs.cr1().modify(|w| { |
| 859 | w.set_spe(true); | 859 | w.set_spe(true); |
| 860 | }); | 860 | }); |
| 861 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 861 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 862 | self.info.regs.cr1().modify(|w| { | 862 | self.info.regs.cr1().modify(|w| { |
| 863 | w.set_cstart(true); | 863 | w.set_cstart(true); |
| 864 | }); | 864 | }); |
| @@ -898,9 +898,9 @@ impl<'d, M: PeriMode> Drop for Spi<'d, M> { | |||
| 898 | } | 898 | } |
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 901 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 902 | use vals::Br; | 902 | use vals::Br; |
| 903 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 903 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 904 | use vals::Mbr as Br; | 904 | use vals::Mbr as Br; |
| 905 | 905 | ||
| 906 | fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br { | 906 | fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br { |
| @@ -941,21 +941,21 @@ pub(crate) trait RegsExt { | |||
| 941 | 941 | ||
| 942 | impl RegsExt for Regs { | 942 | impl RegsExt for Regs { |
| 943 | fn tx_ptr<W>(&self) -> *mut W { | 943 | fn tx_ptr<W>(&self) -> *mut W { |
| 944 | #[cfg(any(spi_v1, spi_f1))] | 944 | #[cfg(any(spi_v1, spi_v2))] |
| 945 | let dr = self.dr(); | 945 | let dr = self.dr(); |
| 946 | #[cfg(spi_v2)] | 946 | #[cfg(spi_v3)] |
| 947 | let dr = self.dr16(); | 947 | let dr = self.dr16(); |
| 948 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 948 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 949 | let dr = self.txdr32(); | 949 | let dr = self.txdr32(); |
| 950 | dr.as_ptr() as *mut W | 950 | dr.as_ptr() as *mut W |
| 951 | } | 951 | } |
| 952 | 952 | ||
| 953 | fn rx_ptr<W>(&self) -> *mut W { | 953 | fn rx_ptr<W>(&self) -> *mut W { |
| 954 | #[cfg(any(spi_v1, spi_f1))] | 954 | #[cfg(any(spi_v1, spi_v2))] |
| 955 | let dr = self.dr(); | 955 | let dr = self.dr(); |
| 956 | #[cfg(spi_v2)] | 956 | #[cfg(spi_v3)] |
| 957 | let dr = self.dr16(); | 957 | let dr = self.dr16(); |
| 958 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 958 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 959 | let dr = self.rxdr32(); | 959 | let dr = self.rxdr32(); |
| 960 | dr.as_ptr() as *mut W | 960 | dr.as_ptr() as *mut W |
| 961 | } | 961 | } |
| @@ -965,22 +965,22 @@ fn check_error_flags(sr: regs::Sr, ovr: bool) -> Result<(), Error> { | |||
| 965 | if sr.ovr() && ovr { | 965 | if sr.ovr() && ovr { |
| 966 | return Err(Error::Overrun); | 966 | return Err(Error::Overrun); |
| 967 | } | 967 | } |
| 968 | #[cfg(not(any(spi_f1, spi_v3, spi_v4, spi_v5)))] | 968 | #[cfg(not(any(spi_v1, spi_v4, spi_v5, spi_v6)))] |
| 969 | if sr.fre() { | 969 | if sr.fre() { |
| 970 | return Err(Error::Framing); | 970 | return Err(Error::Framing); |
| 971 | } | 971 | } |
| 972 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 972 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 973 | if sr.tifre() { | 973 | if sr.tifre() { |
| 974 | return Err(Error::Framing); | 974 | return Err(Error::Framing); |
| 975 | } | 975 | } |
| 976 | if sr.modf() { | 976 | if sr.modf() { |
| 977 | return Err(Error::ModeFault); | 977 | return Err(Error::ModeFault); |
| 978 | } | 978 | } |
| 979 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 979 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 980 | if sr.crcerr() { | 980 | if sr.crcerr() { |
| 981 | return Err(Error::Crc); | 981 | return Err(Error::Crc); |
| 982 | } | 982 | } |
| 983 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 983 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 984 | if sr.crce() { | 984 | if sr.crce() { |
| 985 | return Err(Error::Crc); | 985 | return Err(Error::Crc); |
| 986 | } | 986 | } |
| @@ -994,11 +994,11 @@ fn spin_until_tx_ready(regs: Regs, ovr: bool) -> Result<(), Error> { | |||
| 994 | 994 | ||
| 995 | check_error_flags(sr, ovr)?; | 995 | check_error_flags(sr, ovr)?; |
| 996 | 996 | ||
| 997 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 997 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 998 | if sr.txe() { | 998 | if sr.txe() { |
| 999 | return Ok(()); | 999 | return Ok(()); |
| 1000 | } | 1000 | } |
| 1001 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1001 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1002 | if sr.txp() { | 1002 | if sr.txp() { |
| 1003 | return Ok(()); | 1003 | return Ok(()); |
| 1004 | } | 1004 | } |
| @@ -1011,11 +1011,11 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { | |||
| 1011 | 1011 | ||
| 1012 | check_error_flags(sr, true)?; | 1012 | check_error_flags(sr, true)?; |
| 1013 | 1013 | ||
| 1014 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 1014 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 1015 | if sr.rxne() { | 1015 | if sr.rxne() { |
| 1016 | return Ok(()); | 1016 | return Ok(()); |
| 1017 | } | 1017 | } |
| 1018 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1018 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1019 | if sr.rxp() { | 1019 | if sr.rxp() { |
| 1020 | return Ok(()); | 1020 | return Ok(()); |
| 1021 | } | 1021 | } |
| @@ -1023,46 +1023,46 @@ fn spin_until_rx_ready(regs: Regs) -> Result<(), Error> { | |||
| 1023 | } | 1023 | } |
| 1024 | 1024 | ||
| 1025 | pub(crate) fn flush_rx_fifo(regs: Regs) { | 1025 | pub(crate) fn flush_rx_fifo(regs: Regs) { |
| 1026 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 1026 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 1027 | while regs.sr().read().rxne() { | 1027 | while regs.sr().read().rxne() { |
| 1028 | #[cfg(not(spi_v2))] | 1028 | #[cfg(not(spi_v3))] |
| 1029 | let _ = regs.dr().read(); | 1029 | let _ = regs.dr().read(); |
| 1030 | #[cfg(spi_v2)] | 1030 | #[cfg(spi_v3)] |
| 1031 | let _ = regs.dr16().read(); | 1031 | let _ = regs.dr16().read(); |
| 1032 | } | 1032 | } |
| 1033 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1033 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1034 | while regs.sr().read().rxp() { | 1034 | while regs.sr().read().rxp() { |
| 1035 | let _ = regs.rxdr32().read(); | 1035 | let _ = regs.rxdr32().read(); |
| 1036 | } | 1036 | } |
| 1037 | } | 1037 | } |
| 1038 | 1038 | ||
| 1039 | pub(crate) fn set_txdmaen(regs: Regs, val: bool) { | 1039 | pub(crate) fn set_txdmaen(regs: Regs, val: bool) { |
| 1040 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 1040 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 1041 | regs.cr2().modify(|reg| { | 1041 | regs.cr2().modify(|reg| { |
| 1042 | reg.set_txdmaen(val); | 1042 | reg.set_txdmaen(val); |
| 1043 | }); | 1043 | }); |
| 1044 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1044 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1045 | regs.cfg1().modify(|reg| { | 1045 | regs.cfg1().modify(|reg| { |
| 1046 | reg.set_txdmaen(val); | 1046 | reg.set_txdmaen(val); |
| 1047 | }); | 1047 | }); |
| 1048 | } | 1048 | } |
| 1049 | 1049 | ||
| 1050 | pub(crate) fn set_rxdmaen(regs: Regs, val: bool) { | 1050 | pub(crate) fn set_rxdmaen(regs: Regs, val: bool) { |
| 1051 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 1051 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 1052 | regs.cr2().modify(|reg| { | 1052 | regs.cr2().modify(|reg| { |
| 1053 | reg.set_rxdmaen(val); | 1053 | reg.set_rxdmaen(val); |
| 1054 | }); | 1054 | }); |
| 1055 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1055 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1056 | regs.cfg1().modify(|reg| { | 1056 | regs.cfg1().modify(|reg| { |
| 1057 | reg.set_rxdmaen(val); | 1057 | reg.set_rxdmaen(val); |
| 1058 | }); | 1058 | }); |
| 1059 | } | 1059 | } |
| 1060 | 1060 | ||
| 1061 | fn finish_dma(regs: Regs) { | 1061 | fn finish_dma(regs: Regs) { |
| 1062 | #[cfg(spi_v2)] | 1062 | #[cfg(spi_v3)] |
| 1063 | while regs.sr().read().ftlvl().to_bits() > 0 {} | 1063 | while regs.sr().read().ftlvl().to_bits() > 0 {} |
| 1064 | 1064 | ||
| 1065 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1065 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1066 | { | 1066 | { |
| 1067 | if regs.cr2().read().tsize() == 0 { | 1067 | if regs.cr2().read().tsize() == 0 { |
| 1068 | while !regs.sr().read().txc() {} | 1068 | while !regs.sr().read().txc() {} |
| @@ -1070,7 +1070,7 @@ fn finish_dma(regs: Regs) { | |||
| 1070 | while !regs.sr().read().eot() {} | 1070 | while !regs.sr().read().eot() {} |
| 1071 | } | 1071 | } |
| 1072 | } | 1072 | } |
| 1073 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 1073 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 1074 | while regs.sr().read().bsy() {} | 1074 | while regs.sr().read().bsy() {} |
| 1075 | 1075 | ||
| 1076 | // Disable the spi peripheral | 1076 | // Disable the spi peripheral |
| @@ -1080,12 +1080,12 @@ fn finish_dma(regs: Regs) { | |||
| 1080 | 1080 | ||
| 1081 | // The peripheral automatically disables the DMA stream on completion without error, | 1081 | // The peripheral automatically disables the DMA stream on completion without error, |
| 1082 | // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. | 1082 | // but it does not clear the RXDMAEN/TXDMAEN flag in CR2. |
| 1083 | #[cfg(not(any(spi_v3, spi_v4, spi_v5)))] | 1083 | #[cfg(not(any(spi_v4, spi_v5, spi_v6)))] |
| 1084 | regs.cr2().modify(|reg| { | 1084 | regs.cr2().modify(|reg| { |
| 1085 | reg.set_txdmaen(false); | 1085 | reg.set_txdmaen(false); |
| 1086 | reg.set_rxdmaen(false); | 1086 | reg.set_rxdmaen(false); |
| 1087 | }); | 1087 | }); |
| 1088 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1088 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1089 | regs.cfg1().modify(|reg| { | 1089 | regs.cfg1().modify(|reg| { |
| 1090 | reg.set_txdmaen(false); | 1090 | reg.set_txdmaen(false); |
| 1091 | reg.set_rxdmaen(false); | 1091 | reg.set_rxdmaen(false); |
| @@ -1098,7 +1098,7 @@ fn transfer_word<W: Word>(regs: Regs, tx_word: W) -> Result<W, Error> { | |||
| 1098 | unsafe { | 1098 | unsafe { |
| 1099 | ptr::write_volatile(regs.tx_ptr(), tx_word); | 1099 | ptr::write_volatile(regs.tx_ptr(), tx_word); |
| 1100 | 1100 | ||
| 1101 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1101 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1102 | regs.cr1().modify(|reg| reg.set_cstart(true)); | 1102 | regs.cr1().modify(|reg| reg.set_cstart(true)); |
| 1103 | } | 1103 | } |
| 1104 | 1104 | ||
| @@ -1117,7 +1117,7 @@ fn write_word<W: Word>(regs: Regs, tx_word: W) -> Result<(), Error> { | |||
| 1117 | unsafe { | 1117 | unsafe { |
| 1118 | ptr::write_volatile(regs.tx_ptr(), tx_word); | 1118 | ptr::write_volatile(regs.tx_ptr(), tx_word); |
| 1119 | 1119 | ||
| 1120 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1120 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1121 | regs.cr1().modify(|reg| reg.set_cstart(true)); | 1121 | regs.cr1().modify(|reg| reg.set_cstart(true)); |
| 1122 | } | 1122 | } |
| 1123 | Ok(()) | 1123 | Ok(()) |
| @@ -1225,7 +1225,7 @@ macro_rules! impl_word { | |||
| 1225 | }; | 1225 | }; |
| 1226 | } | 1226 | } |
| 1227 | 1227 | ||
| 1228 | #[cfg(any(spi_v1, spi_f1))] | 1228 | #[cfg(any(spi_v1, spi_v2))] |
| 1229 | mod word_impl { | 1229 | mod word_impl { |
| 1230 | use super::*; | 1230 | use super::*; |
| 1231 | 1231 | ||
| @@ -1235,7 +1235,7 @@ mod word_impl { | |||
| 1235 | impl_word!(u16, vals::Dff::BITS16); | 1235 | impl_word!(u16, vals::Dff::BITS16); |
| 1236 | } | 1236 | } |
| 1237 | 1237 | ||
| 1238 | #[cfg(spi_v2)] | 1238 | #[cfg(spi_v3)] |
| 1239 | mod word_impl { | 1239 | mod word_impl { |
| 1240 | use super::*; | 1240 | use super::*; |
| 1241 | 1241 | ||
| @@ -1256,7 +1256,7 @@ mod word_impl { | |||
| 1256 | impl_word!(u16, (vals::Ds::BITS16, vals::Frxth::HALF)); | 1256 | impl_word!(u16, (vals::Ds::BITS16, vals::Frxth::HALF)); |
| 1257 | } | 1257 | } |
| 1258 | 1258 | ||
| 1259 | #[cfg(any(spi_v3, spi_v4, spi_v5))] | 1259 | #[cfg(any(spi_v4, spi_v5, spi_v6))] |
| 1260 | mod word_impl { | 1260 | mod word_impl { |
| 1261 | use super::*; | 1261 | use super::*; |
| 1262 | 1262 | ||
