aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-09-01 00:05:20 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-05 16:01:29 +0200
commit683ca6595ff7f4c6f0e70e90d3cdeab13d0b1c07 (patch)
tree7c2d714f4ae66d12e66742f7b316b14d5451514f
parent90d403fd0a33ac7a3cde4fe9c417b5976b924020 (diff)
stm32/spi: update for new version numbering, add i2s support for all versions.
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/Cargo.toml8
-rw-r--r--embassy-stm32/src/adc/mod.rs68
-rw-r--r--embassy-stm32/src/i2s.rs183
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/spi/mod.rs134
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"
173futures-util = { version = "0.3.30", default-features = false } 173futures-util = { version = "0.3.30", default-features = false }
174sdio-host = "0.9.0" 174sdio-host = "0.9.0"
175critical-section = "1.1" 175critical-section = "1.1"
176stm32-metapac = { version = "18" } 176#stm32-metapac = { version = "18" }
177#stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ecb93d42a6cbcd9e09cab74873908a2ca22327f7" } 177stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d8432edd0406495adec19d31923584e80b8e03cb" }
178 178
179vcell = "0.1.3" 179vcell = "0.1.3"
180nb = "1.0.0" 180nb = "1.0.0"
@@ -202,8 +202,8 @@ proptest-state-machine = "0.3.0"
202proc-macro2 = "1.0.36" 202proc-macro2 = "1.0.36"
203quote = "1.0.15" 203quote = "1.0.15"
204 204
205stm32-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"] } 206stm32-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]
209default = ["rt"] 209default = ["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;
20use core::marker::PhantomData; 20use 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)))]
24pub use _version::*; 24pub use _version::*;
25use embassy_hal_internal::{impl_peripheral, PeripheralType}; 25use 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))]
27use embassy_sync::waitqueue::AtomicWaker; 27use 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;
31pub mod adc4; 31pub mod adc4;
32 32
33pub use crate::pac::adc::vals; 33pub use crate::pac::adc::vals;
34#[cfg(not(any(adc_f1, adc_f3_v2)))] 34#[cfg(not(any(adc_f1, adc_f3v3)))]
35pub use crate::pac::adc::vals::Res as Resolution; 35pub use crate::pac::adc::vals::Res as Resolution;
36pub use crate::pac::adc::vals::SampleTime; 36pub use crate::pac::adc::vals::SampleTime;
37use crate::peripherals; 37use crate::peripherals;
@@ -47,16 +47,16 @@ dma_trait!(RxDma4, adc4::Instance);
47pub struct Adc<'d, T: Instance> { 47pub 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))]
55pub struct State { 55pub 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))]
60impl State { 60impl 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)]
121pub trait Instance: SealedInstance + crate::PeripheralType { 107pub 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)]
144pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { 116pub 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)))]
299pub const fn resolution_to_max_count(res: Resolution) -> u32 { 271pub 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
74impl Standard { 75impl 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
108impl Format { 107impl 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
139impl ClockPolarity { 136impl 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.
645fn reset_incompatible_bitfields<T: Instance>() { 638fn 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;
87pub mod hspi; 87pub mod hspi;
88#[cfg(i2c)] 88#[cfg(i2c)]
89pub mod i2c; 89pub 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))]
91pub mod i2s; 91pub mod i2s;
92#[cfg(stm32wb)] 92#[cfg(stm32wb)]
93pub mod ipcc; 93pub 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)))]
902use vals::Br; 902use vals::Br;
903#[cfg(any(spi_v3, spi_v4, spi_v5))] 903#[cfg(any(spi_v4, spi_v5, spi_v6))]
904use vals::Mbr as Br; 904use vals::Mbr as Br;
905 905
906fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br { 906fn compute_baud_rate(kernel_clock: Hertz, freq: Hertz) -> Br {
@@ -941,21 +941,21 @@ pub(crate) trait RegsExt {
941 941
942impl RegsExt for Regs { 942impl 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
1025pub(crate) fn flush_rx_fifo(regs: Regs) { 1025pub(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
1039pub(crate) fn set_txdmaen(regs: Regs, val: bool) { 1039pub(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
1050pub(crate) fn set_rxdmaen(regs: Regs, val: bool) { 1050pub(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
1061fn finish_dma(regs: Regs) { 1061fn 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))]
1229mod word_impl { 1229mod 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)]
1239mod word_impl { 1239mod 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))]
1260mod word_impl { 1260mod word_impl {
1261 use super::*; 1261 use super::*;
1262 1262