aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/lib.rs6
-rw-r--r--embassy-stm32/build.rs20
-rw-r--r--embassy-stm32/src/adc/mod.rs3
-rw-r--r--embassy-stm32/src/can/mod.rs1
-rw-r--r--embassy-stm32/src/crc/mod.rs1
-rw-r--r--embassy-stm32/src/dac/mod.rs2
-rw-r--r--embassy-stm32/src/dcmi.rs1
-rw-r--r--embassy-stm32/src/eth/mod.rs1
-rw-r--r--embassy-stm32/src/exti.rs1
-rw-r--r--embassy-stm32/src/flash/mod.rs1
-rw-r--r--embassy-stm32/src/fmc.rs1
-rw-r--r--embassy-stm32/src/hrtim/mod.rs2
-rw-r--r--embassy-stm32/src/i2c/mod.rs1
-rw-r--r--embassy-stm32/src/i2s.rs1
-rw-r--r--embassy-stm32/src/lib.rs24
-rw-r--r--embassy-stm32/src/qspi/mod.rs2
-rw-r--r--embassy-stm32/src/rng.rs1
-rw-r--r--embassy-stm32/src/rtc/mod.rs4
-rw-r--r--embassy-stm32/src/sai/mod.rs536
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs1
-rw-r--r--embassy-stm32/src/spi/mod.rs1
-rw-r--r--embassy-stm32/src/traits.rs26
-rw-r--r--embassy-stm32/src/uid.rs2
-rw-r--r--embassy-stm32/src/usart/mod.rs1
-rw-r--r--embassy-stm32/src/usb_otg/mod.rs2
-rw-r--r--embassy-stm32/src/wdg/mod.rs1
26 files changed, 291 insertions, 352 deletions
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 9093ad919..e3458e2de 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -354,7 +354,11 @@ unsafe fn uicr_write_masked(address: *mut u32, value: u32, mask: u32) -> WriteRe
354 WriteResult::Written 354 WriteResult::Written
355} 355}
356 356
357/// Initialize peripherals with the provided configuration. This should only be called once at startup. 357/// Initialize the `embassy-nrf` HAL with the provided configuration.
358///
359/// This returns the peripheral singletons that can be used for creating drivers.
360///
361/// This should only be called once at startup, otherwise it panics.
358pub fn init(config: config::Config) -> Peripherals { 362pub fn init(config: config::Config) -> Peripherals {
359 // Do this first, so that it panics if user is calling `init` a second time 363 // Do this first, so that it panics if user is calling `init` a second time
360 // before doing anything important. 364 // before doing anything important.
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index bb60d244f..058b8a0fc 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -672,14 +672,14 @@ fn main() {
672 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), 672 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
673 (("lpuart", "CK"), quote!(crate::usart::CkPin)), 673 (("lpuart", "CK"), quote!(crate::usart::CkPin)),
674 (("lpuart", "DE"), quote!(crate::usart::DePin)), 674 (("lpuart", "DE"), quote!(crate::usart::DePin)),
675 (("sai", "SCK_A"), quote!(crate::sai::SckAPin)), 675 (("sai", "SCK_A"), quote!(crate::sai::SckPin<A>)),
676 (("sai", "SCK_B"), quote!(crate::sai::SckBPin)), 676 (("sai", "SCK_B"), quote!(crate::sai::SckPin<B>)),
677 (("sai", "FS_A"), quote!(crate::sai::FsAPin)), 677 (("sai", "FS_A"), quote!(crate::sai::FsPin<A>)),
678 (("sai", "FS_B"), quote!(crate::sai::FsBPin)), 678 (("sai", "FS_B"), quote!(crate::sai::FsPin<B>)),
679 (("sai", "SD_A"), quote!(crate::sai::SdAPin)), 679 (("sai", "SD_A"), quote!(crate::sai::SdPin<A>)),
680 (("sai", "SD_B"), quote!(crate::sai::SdBPin)), 680 (("sai", "SD_B"), quote!(crate::sai::SdPin<B>)),
681 (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)), 681 (("sai", "MCLK_A"), quote!(crate::sai::MclkPin<A>)),
682 (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)), 682 (("sai", "MCLK_B"), quote!(crate::sai::MclkPin<B>)),
683 (("sai", "WS"), quote!(crate::sai::WsPin)), 683 (("sai", "WS"), quote!(crate::sai::WsPin)),
684 (("spi", "SCK"), quote!(crate::spi::SckPin)), 684 (("spi", "SCK"), quote!(crate::spi::SckPin)),
685 (("spi", "MOSI"), quote!(crate::spi::MosiPin)), 685 (("spi", "MOSI"), quote!(crate::spi::MosiPin)),
@@ -995,8 +995,8 @@ fn main() {
995 (("usart", "TX"), quote!(crate::usart::TxDma)), 995 (("usart", "TX"), quote!(crate::usart::TxDma)),
996 (("lpuart", "RX"), quote!(crate::usart::RxDma)), 996 (("lpuart", "RX"), quote!(crate::usart::RxDma)),
997 (("lpuart", "TX"), quote!(crate::usart::TxDma)), 997 (("lpuart", "TX"), quote!(crate::usart::TxDma)),
998 (("sai", "A"), quote!(crate::sai::DmaA)), 998 (("sai", "A"), quote!(crate::sai::Dma<A>)),
999 (("sai", "B"), quote!(crate::sai::DmaB)), 999 (("sai", "B"), quote!(crate::sai::Dma<B>)),
1000 (("spi", "RX"), quote!(crate::spi::RxDma)), 1000 (("spi", "RX"), quote!(crate::spi::RxDma)),
1001 (("spi", "TX"), quote!(crate::spi::TxDma)), 1001 (("spi", "TX"), quote!(crate::spi::TxDma)),
1002 (("i2c", "RX"), quote!(crate::i2c::RxDma)), 1002 (("i2c", "RX"), quote!(crate::i2c::RxDma)),
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index ff523ca3b..e4dd35c34 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -1,4 +1,5 @@
1//! Analog to Digital (ADC) converter driver. 1//! Analog to Digital Converter (ADC)
2
2#![macro_use] 3#![macro_use]
3#![allow(missing_docs)] // TODO 4#![allow(missing_docs)] // TODO
4 5
diff --git a/embassy-stm32/src/can/mod.rs b/embassy-stm32/src/can/mod.rs
index 425f9ac2e..915edb3a6 100644
--- a/embassy-stm32/src/can/mod.rs
+++ b/embassy-stm32/src/can/mod.rs
@@ -1,3 +1,4 @@
1//! Controller Area Network (CAN)
1#![macro_use] 2#![macro_use]
2 3
3#[cfg_attr(can_bxcan, path = "bxcan.rs")] 4#[cfg_attr(can_bxcan, path = "bxcan.rs")]
diff --git a/embassy-stm32/src/crc/mod.rs b/embassy-stm32/src/crc/mod.rs
index 63f7ad9ba..29523b92d 100644
--- a/embassy-stm32/src/crc/mod.rs
+++ b/embassy-stm32/src/crc/mod.rs
@@ -1,3 +1,4 @@
1//! Cyclic Redundancy Check (CRC)
1#[cfg_attr(crc_v1, path = "v1.rs")] 2#[cfg_attr(crc_v1, path = "v1.rs")]
2#[cfg_attr(crc_v2, path = "v2v3.rs")] 3#[cfg_attr(crc_v2, path = "v2v3.rs")]
3#[cfg_attr(crc_v3, path = "v2v3.rs")] 4#[cfg_attr(crc_v3, path = "v2v3.rs")]
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 9c670195d..31dedf06e 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -1,4 +1,4 @@
1//! Provide access to the STM32 digital-to-analog converter (DAC). 1//! Digital to Analog Converter (DAC)
2#![macro_use] 2#![macro_use]
3 3
4use core::marker::PhantomData; 4use core::marker::PhantomData;
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index 139d8fd1b..4d02284b2 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -1,3 +1,4 @@
1//! Digital Camera Interface (DCMI)
1use core::future::poll_fn; 2use core::future::poll_fn;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use core::task::Poll; 4use core::task::Poll;
diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs
index dbf91eedc..448405507 100644
--- a/embassy-stm32/src/eth/mod.rs
+++ b/embassy-stm32/src/eth/mod.rs
@@ -1,3 +1,4 @@
1//! Ethernet (ETH)
1#![macro_use] 2#![macro_use]
2 3
3#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")] 4#[cfg_attr(any(eth_v1a, eth_v1b, eth_v1c), path = "v1/mod.rs")]
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 371be913e..f83bae3ff 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -1,3 +1,4 @@
1//! External Interrupts (EXTI)
1use core::convert::Infallible; 2use core::convert::Infallible;
2use core::future::Future; 3use core::future::Future;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 6b6b4d41c..cbf5c25b2 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -1,3 +1,4 @@
1//! Flash memory (FLASH)
1use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind}; 2use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind};
2 3
3#[cfg(flash_f4)] 4#[cfg(flash_f4)]
diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs
index 23ac82f63..873c8a70c 100644
--- a/embassy-stm32/src/fmc.rs
+++ b/embassy-stm32/src/fmc.rs
@@ -1,3 +1,4 @@
1//! Flexible Memory Controller (FMC) / Flexible Static Memory Controller (FSMC)
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3use embassy_hal_internal::into_ref; 4use embassy_hal_internal::into_ref;
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 17096d48c..6539326b4 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -1,3 +1,5 @@
1//! High Resolution Timer (HRTIM)
2
1mod traits; 3mod traits;
2 4
3use core::marker::PhantomData; 5use core::marker::PhantomData;
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 0af291e9c..9b0b35eca 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -1,3 +1,4 @@
1//! Inter-Integrated-Circuit (I2C)
1#![macro_use] 2#![macro_use]
2 3
3#[cfg_attr(i2c_v1, path = "v1.rs")] 4#[cfg_attr(i2c_v1, path = "v1.rs")]
diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs
index 372c86db3..1f85c0bc5 100644
--- a/embassy-stm32/src/i2s.rs
+++ b/embassy-stm32/src/i2s.rs
@@ -1,3 +1,4 @@
1//! Inter-IC Sound (I2S)
1use embassy_hal_internal::into_ref; 2use embassy_hal_internal::into_ref;
2 3
3use crate::gpio::sealed::{AFType, Pin as _}; 4use crate::gpio::sealed::{AFType, Pin as _};
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 5d9b4e6a0..fd691a732 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -149,15 +149,33 @@ use crate::interrupt::Priority;
149pub use crate::pac::NVIC_PRIO_BITS; 149pub use crate::pac::NVIC_PRIO_BITS;
150use crate::rcc::sealed::RccPeripheral; 150use crate::rcc::sealed::RccPeripheral;
151 151
152/// `embassy-stm32` global configuration.
152#[non_exhaustive] 153#[non_exhaustive]
153pub struct Config { 154pub struct Config {
155 /// RCC config.
154 pub rcc: rcc::Config, 156 pub rcc: rcc::Config,
157
158 /// Enable debug during sleep.
159 ///
160 /// May incrase power consumption. Defaults to true.
155 #[cfg(dbgmcu)] 161 #[cfg(dbgmcu)]
156 pub enable_debug_during_sleep: bool, 162 pub enable_debug_during_sleep: bool,
163
164 /// BDMA interrupt priority.
165 ///
166 /// Defaults to P0 (highest).
157 #[cfg(bdma)] 167 #[cfg(bdma)]
158 pub bdma_interrupt_priority: Priority, 168 pub bdma_interrupt_priority: Priority,
169
170 /// DMA interrupt priority.
171 ///
172 /// Defaults to P0 (highest).
159 #[cfg(dma)] 173 #[cfg(dma)]
160 pub dma_interrupt_priority: Priority, 174 pub dma_interrupt_priority: Priority,
175
176 /// GPDMA interrupt priority.
177 ///
178 /// Defaults to P0 (highest).
161 #[cfg(gpdma)] 179 #[cfg(gpdma)]
162 pub gpdma_interrupt_priority: Priority, 180 pub gpdma_interrupt_priority: Priority,
163} 181}
@@ -178,7 +196,11 @@ impl Default for Config {
178 } 196 }
179} 197}
180 198
181/// Initialize embassy. 199/// Initialize the `embassy-stm32` HAL with the provided configuration.
200///
201/// This returns the peripheral singletons that can be used for creating drivers.
202///
203/// This should only be called once at startup, otherwise it panics.
182pub fn init(config: Config) -> Peripherals { 204pub fn init(config: Config) -> Peripherals {
183 critical_section::with(|cs| { 205 critical_section::with(|cs| {
184 let p = Peripherals::take_with_cs(cs); 206 let p = Peripherals::take_with_cs(cs);
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index bac91f300..9ea0a726c 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -1,3 +1,5 @@
1//! Quad Serial Peripheral Interface (QSPI)
2
1#![macro_use] 3#![macro_use]
2 4
3pub mod enums; 5pub mod enums;
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index b2196b0d5..6ee89a922 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -1,3 +1,4 @@
1//! Random Number Generator (RNG)
1#![macro_use] 2#![macro_use]
2 3
3use core::future::poll_fn; 4use core::future::poll_fn;
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index fa359cdae..11b252139 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -1,4 +1,4 @@
1//! RTC peripheral abstraction 1//! Real Time Clock (RTC)
2mod datetime; 2mod datetime;
3 3
4#[cfg(feature = "low-power")] 4#[cfg(feature = "low-power")]
@@ -163,7 +163,7 @@ impl RtcTimeProvider {
163 } 163 }
164} 164}
165 165
166/// RTC Abstraction 166/// RTC driver.
167pub struct Rtc { 167pub struct Rtc {
168 #[cfg(feature = "low-power")] 168 #[cfg(feature = "low-power")]
169 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>, 169 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>,
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
index 3d7f65996..ef8802184 100644
--- a/embassy-stm32/src/sai/mod.rs
+++ b/embassy-stm32/src/sai/mod.rs
@@ -1,8 +1,11 @@
1//! Serial Audio Interface (SAI)
1#![macro_use] 2#![macro_use]
2 3
3use embassy_embedded_hal::SetConfig; 4use core::marker::PhantomData;
5
4use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::{into_ref, PeripheralRef};
5 7
8use self::sealed::WhichSubBlock;
6pub use crate::dma::word; 9pub use crate::dma::word;
7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; 10use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer};
8use crate::gpio::sealed::{AFType, Pin as _}; 11use crate::gpio::sealed::{AFType, Pin as _};
@@ -11,48 +14,32 @@ use crate::pac::sai::{vals, Sai as Regs};
11use crate::rcc::RccPeripheral; 14use crate::rcc::RccPeripheral;
12use crate::{peripherals, Peripheral}; 15use crate::{peripherals, Peripheral};
13 16
17/// SAI error
14#[derive(Debug, PartialEq, Eq)] 18#[derive(Debug, PartialEq, Eq)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))] 19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum Error { 20pub enum Error {
21 /// `write` called on a SAI in receive mode.
17 NotATransmitter, 22 NotATransmitter,
23 /// `read` called on a SAI in transmit mode.
18 NotAReceiver, 24 NotAReceiver,
19 OverrunError, 25 /// Overrun
26 Overrun,
20} 27}
21 28
22impl From<ringbuffer::OverrunError> for Error { 29impl From<ringbuffer::OverrunError> for Error {
23 fn from(_: ringbuffer::OverrunError) -> Self { 30 fn from(_: ringbuffer::OverrunError) -> Self {
24 Self::OverrunError 31 Self::Overrun
25 } 32 }
26} 33}
27 34
35/// Master/slave mode.
28#[derive(Copy, Clone)] 36#[derive(Copy, Clone)]
29pub enum SyncBlock { 37#[allow(missing_docs)]
30 None,
31 Sai1BlockA,
32 Sai1BlockB,
33 Sai2BlockA,
34 Sai2BlockB,
35}
36
37#[derive(Copy, Clone)]
38pub enum SyncIn {
39 None,
40 ChannelZero,
41 ChannelOne,
42}
43
44#[derive(Copy, Clone)]
45pub enum Mode { 38pub enum Mode {
46 Master, 39 Master,
47 Slave, 40 Slave,
48} 41}
49 42
50#[derive(Copy, Clone)]
51pub enum TxRx {
52 Transmitter,
53 Receiver,
54}
55
56impl Mode { 43impl Mode {
57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 44 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode { 45 const fn mode(&self, tx_rx: TxRx) -> vals::Mode {
@@ -69,7 +56,17 @@ impl Mode {
69 } 56 }
70} 57}
71 58
59/// Direction: transmit or receive
72#[derive(Copy, Clone)] 60#[derive(Copy, Clone)]
61#[allow(missing_docs)]
62pub enum TxRx {
63 Transmitter,
64 Receiver,
65}
66
67/// Data slot size.
68#[derive(Copy, Clone)]
69#[allow(missing_docs)]
73pub enum SlotSize { 70pub enum SlotSize {
74 DataSize, 71 DataSize,
75 /// 16 bit data length on 16 bit wide channel 72 /// 16 bit data length on 16 bit wide channel
@@ -80,7 +77,7 @@ pub enum SlotSize {
80 77
81impl SlotSize { 78impl SlotSize {
82 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 79 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
83 pub const fn slotsz(&self) -> vals::Slotsz { 80 const fn slotsz(&self) -> vals::Slotsz {
84 match self { 81 match self {
85 SlotSize::DataSize => vals::Slotsz::DATASIZE, 82 SlotSize::DataSize => vals::Slotsz::DATASIZE,
86 SlotSize::Channel16 => vals::Slotsz::BIT16, 83 SlotSize::Channel16 => vals::Slotsz::BIT16,
@@ -89,7 +86,9 @@ impl SlotSize {
89 } 86 }
90} 87}
91 88
89/// Data size.
92#[derive(Copy, Clone)] 90#[derive(Copy, Clone)]
91#[allow(missing_docs)]
93pub enum DataSize { 92pub enum DataSize {
94 Data8, 93 Data8,
95 Data10, 94 Data10,
@@ -101,7 +100,7 @@ pub enum DataSize {
101 100
102impl DataSize { 101impl DataSize {
103 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 102 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
104 pub const fn ds(&self) -> vals::Ds { 103 const fn ds(&self) -> vals::Ds {
105 match self { 104 match self {
106 DataSize::Data8 => vals::Ds::BIT8, 105 DataSize::Data8 => vals::Ds::BIT8,
107 DataSize::Data10 => vals::Ds::BIT10, 106 DataSize::Data10 => vals::Ds::BIT10,
@@ -113,7 +112,9 @@ impl DataSize {
113 } 112 }
114} 113}
115 114
115/// FIFO threshold level.
116#[derive(Copy, Clone)] 116#[derive(Copy, Clone)]
117#[allow(missing_docs)]
117pub enum FifoThreshold { 118pub enum FifoThreshold {
118 Empty, 119 Empty,
119 Quarter, 120 Quarter,
@@ -124,7 +125,7 @@ pub enum FifoThreshold {
124 125
125impl FifoThreshold { 126impl FifoThreshold {
126 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 127 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
127 pub const fn fth(&self) -> vals::Fth { 128 const fn fth(&self) -> vals::Fth {
128 match self { 129 match self {
129 FifoThreshold::Empty => vals::Fth::EMPTY, 130 FifoThreshold::Empty => vals::Fth::EMPTY,
130 FifoThreshold::Quarter => vals::Fth::QUARTER1, 131 FifoThreshold::Quarter => vals::Fth::QUARTER1,
@@ -135,38 +136,9 @@ impl FifoThreshold {
135 } 136 }
136} 137}
137 138
139/// Output value on mute.
138#[derive(Copy, Clone)] 140#[derive(Copy, Clone)]
139pub enum FifoLevel { 141#[allow(missing_docs)]
140 Empty,
141 FirstQuarter,
142 SecondQuarter,
143 ThirdQuarter,
144 FourthQuarter,
145 Full,
146}
147
148#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
149impl From<vals::Flvl> for FifoLevel {
150 fn from(flvl: vals::Flvl) -> Self {
151 match flvl {
152 vals::Flvl::EMPTY => FifoLevel::Empty,
153 vals::Flvl::QUARTER1 => FifoLevel::FirstQuarter,
154 vals::Flvl::QUARTER2 => FifoLevel::SecondQuarter,
155 vals::Flvl::QUARTER3 => FifoLevel::ThirdQuarter,
156 vals::Flvl::QUARTER4 => FifoLevel::FourthQuarter,
157 vals::Flvl::FULL => FifoLevel::Full,
158 _ => FifoLevel::Empty,
159 }
160 }
161}
162
163#[derive(Copy, Clone)]
164pub enum MuteDetection {
165 NoMute,
166 Mute,
167}
168
169#[derive(Copy, Clone)]
170pub enum MuteValue { 142pub enum MuteValue {
171 Zero, 143 Zero,
172 LastValue, 144 LastValue,
@@ -174,7 +146,7 @@ pub enum MuteValue {
174 146
175impl MuteValue { 147impl MuteValue {
176 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 148 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
177 pub const fn muteval(&self) -> vals::Muteval { 149 const fn muteval(&self) -> vals::Muteval {
178 match self { 150 match self {
179 MuteValue::Zero => vals::Muteval::SENDZERO, 151 MuteValue::Zero => vals::Muteval::SENDZERO,
180 MuteValue::LastValue => vals::Muteval::SENDLAST, 152 MuteValue::LastValue => vals::Muteval::SENDLAST,
@@ -182,13 +154,9 @@ impl MuteValue {
182 } 154 }
183} 155}
184 156
157/// Protocol variant to use.
185#[derive(Copy, Clone)] 158#[derive(Copy, Clone)]
186pub enum OverUnderStatus { 159#[allow(missing_docs)]
187 NoError,
188 OverUnderRunDetected,
189}
190
191#[derive(Copy, Clone)]
192pub enum Protocol { 160pub enum Protocol {
193 Free, 161 Free,
194 Spdif, 162 Spdif,
@@ -197,7 +165,7 @@ pub enum Protocol {
197 165
198impl Protocol { 166impl Protocol {
199 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 167 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
200 pub const fn prtcfg(&self) -> vals::Prtcfg { 168 const fn prtcfg(&self) -> vals::Prtcfg {
201 match self { 169 match self {
202 Protocol::Free => vals::Prtcfg::FREE, 170 Protocol::Free => vals::Prtcfg::FREE,
203 Protocol::Spdif => vals::Prtcfg::SPDIF, 171 Protocol::Spdif => vals::Prtcfg::SPDIF,
@@ -206,7 +174,9 @@ impl Protocol {
206 } 174 }
207} 175}
208 176
177/// Sync input between SAI units/blocks.
209#[derive(Copy, Clone, PartialEq)] 178#[derive(Copy, Clone, PartialEq)]
179#[allow(missing_docs)]
210pub enum SyncInput { 180pub enum SyncInput {
211 /// Not synced to any other SAI unit. 181 /// Not synced to any other SAI unit.
212 None, 182 None,
@@ -218,7 +188,7 @@ pub enum SyncInput {
218} 188}
219 189
220impl SyncInput { 190impl SyncInput {
221 pub const fn syncen(&self) -> vals::Syncen { 191 const fn syncen(&self) -> vals::Syncen {
222 match self { 192 match self {
223 SyncInput::None => vals::Syncen::ASYNCHRONOUS, 193 SyncInput::None => vals::Syncen::ASYNCHRONOUS,
224 SyncInput::Internal => vals::Syncen::INTERNAL, 194 SyncInput::Internal => vals::Syncen::INTERNAL,
@@ -228,8 +198,10 @@ impl SyncInput {
228 } 198 }
229} 199}
230 200
201/// SAI instance to sync from.
231#[cfg(sai_v4)] 202#[cfg(sai_v4)]
232#[derive(Copy, Clone, PartialEq)] 203#[derive(Copy, Clone, PartialEq)]
204#[allow(missing_docs)]
233pub enum SyncInputInstance { 205pub enum SyncInputInstance {
234 #[cfg(peri_sai1)] 206 #[cfg(peri_sai1)]
235 Sai1 = 0, 207 Sai1 = 0,
@@ -241,7 +213,9 @@ pub enum SyncInputInstance {
241 Sai4 = 3, 213 Sai4 = 3,
242} 214}
243 215
216/// Channels (stereo or mono).
244#[derive(Copy, Clone, PartialEq)] 217#[derive(Copy, Clone, PartialEq)]
218#[allow(missing_docs)]
245pub enum StereoMono { 219pub enum StereoMono {
246 Stereo, 220 Stereo,
247 Mono, 221 Mono,
@@ -249,7 +223,7 @@ pub enum StereoMono {
249 223
250impl StereoMono { 224impl StereoMono {
251 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 225 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
252 pub const fn mono(&self) -> vals::Mono { 226 const fn mono(&self) -> vals::Mono {
253 match self { 227 match self {
254 StereoMono::Stereo => vals::Mono::STEREO, 228 StereoMono::Stereo => vals::Mono::STEREO,
255 StereoMono::Mono => vals::Mono::MONO, 229 StereoMono::Mono => vals::Mono::MONO,
@@ -257,15 +231,18 @@ impl StereoMono {
257 } 231 }
258} 232}
259 233
234/// Bit order
260#[derive(Copy, Clone)] 235#[derive(Copy, Clone)]
261pub enum BitOrder { 236pub enum BitOrder {
237 /// Least significant bit first.
262 LsbFirst, 238 LsbFirst,
239 /// Most significant bit first.
263 MsbFirst, 240 MsbFirst,
264} 241}
265 242
266impl BitOrder { 243impl BitOrder {
267 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 244 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
268 pub const fn lsbfirst(&self) -> vals::Lsbfirst { 245 const fn lsbfirst(&self) -> vals::Lsbfirst {
269 match self { 246 match self {
270 BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, 247 BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST,
271 BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, 248 BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST,
@@ -273,6 +250,7 @@ impl BitOrder {
273 } 250 }
274} 251}
275 252
253/// Frame sync offset.
276#[derive(Copy, Clone)] 254#[derive(Copy, Clone)]
277pub enum FrameSyncOffset { 255pub enum FrameSyncOffset {
278 /// This is used in modes other than standard I2S phillips mode 256 /// This is used in modes other than standard I2S phillips mode
@@ -283,7 +261,7 @@ pub enum FrameSyncOffset {
283 261
284impl FrameSyncOffset { 262impl FrameSyncOffset {
285 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 263 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
286 pub const fn fsoff(&self) -> vals::Fsoff { 264 const fn fsoff(&self) -> vals::Fsoff {
287 match self { 265 match self {
288 FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST, 266 FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST,
289 FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST, 267 FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST,
@@ -291,15 +269,18 @@ impl FrameSyncOffset {
291 } 269 }
292} 270}
293 271
272/// Frame sync polarity
294#[derive(Copy, Clone)] 273#[derive(Copy, Clone)]
295pub enum FrameSyncPolarity { 274pub enum FrameSyncPolarity {
275 /// Sync signal is active low.
296 ActiveLow, 276 ActiveLow,
277 /// Sync signal is active high
297 ActiveHigh, 278 ActiveHigh,
298} 279}
299 280
300impl FrameSyncPolarity { 281impl FrameSyncPolarity {
301 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 282 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
302 pub const fn fspol(&self) -> vals::Fspol { 283 const fn fspol(&self) -> vals::Fspol {
303 match self { 284 match self {
304 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE, 285 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE,
305 FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE, 286 FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE,
@@ -307,7 +288,9 @@ impl FrameSyncPolarity {
307 } 288 }
308} 289}
309 290
291/// Sync definition.
310#[derive(Copy, Clone)] 292#[derive(Copy, Clone)]
293#[allow(missing_docs)]
311pub enum FrameSyncDefinition { 294pub enum FrameSyncDefinition {
312 StartOfFrame, 295 StartOfFrame,
313 ChannelIdentification, 296 ChannelIdentification,
@@ -315,7 +298,7 @@ pub enum FrameSyncDefinition {
315 298
316impl FrameSyncDefinition { 299impl FrameSyncDefinition {
317 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 300 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
318 pub const fn fsdef(&self) -> bool { 301 const fn fsdef(&self) -> bool {
319 match self { 302 match self {
320 FrameSyncDefinition::StartOfFrame => false, 303 FrameSyncDefinition::StartOfFrame => false,
321 FrameSyncDefinition::ChannelIdentification => true, 304 FrameSyncDefinition::ChannelIdentification => true,
@@ -323,7 +306,9 @@ impl FrameSyncDefinition {
323 } 306 }
324} 307}
325 308
309/// Clock strobe.
326#[derive(Copy, Clone)] 310#[derive(Copy, Clone)]
311#[allow(missing_docs)]
327pub enum ClockStrobe { 312pub enum ClockStrobe {
328 Falling, 313 Falling,
329 Rising, 314 Rising,
@@ -331,7 +316,7 @@ pub enum ClockStrobe {
331 316
332impl ClockStrobe { 317impl ClockStrobe {
333 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 318 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
334 pub const fn ckstr(&self) -> vals::Ckstr { 319 const fn ckstr(&self) -> vals::Ckstr {
335 match self { 320 match self {
336 ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE, 321 ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE,
337 ClockStrobe::Rising => vals::Ckstr::RISINGEDGE, 322 ClockStrobe::Rising => vals::Ckstr::RISINGEDGE,
@@ -339,7 +324,9 @@ impl ClockStrobe {
339 } 324 }
340} 325}
341 326
327/// Complements format for negative samples.
342#[derive(Copy, Clone)] 328#[derive(Copy, Clone)]
329#[allow(missing_docs)]
343pub enum ComplementFormat { 330pub enum ComplementFormat {
344 OnesComplement, 331 OnesComplement,
345 TwosComplement, 332 TwosComplement,
@@ -347,7 +334,7 @@ pub enum ComplementFormat {
347 334
348impl ComplementFormat { 335impl ComplementFormat {
349 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 336 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
350 pub const fn cpl(&self) -> vals::Cpl { 337 const fn cpl(&self) -> vals::Cpl {
351 match self { 338 match self {
352 ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT, 339 ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT,
353 ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT, 340 ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT,
@@ -355,7 +342,9 @@ impl ComplementFormat {
355 } 342 }
356} 343}
357 344
345/// Companding setting.
358#[derive(Copy, Clone)] 346#[derive(Copy, Clone)]
347#[allow(missing_docs)]
359pub enum Companding { 348pub enum Companding {
360 None, 349 None,
361 MuLaw, 350 MuLaw,
@@ -364,7 +353,7 @@ pub enum Companding {
364 353
365impl Companding { 354impl Companding {
366 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 355 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
367 pub const fn comp(&self) -> vals::Comp { 356 const fn comp(&self) -> vals::Comp {
368 match self { 357 match self {
369 Companding::None => vals::Comp::NOCOMPANDING, 358 Companding::None => vals::Comp::NOCOMPANDING,
370 Companding::MuLaw => vals::Comp::MULAW, 359 Companding::MuLaw => vals::Comp::MULAW,
@@ -373,7 +362,9 @@ impl Companding {
373 } 362 }
374} 363}
375 364
365/// Output drive
376#[derive(Copy, Clone)] 366#[derive(Copy, Clone)]
367#[allow(missing_docs)]
377pub enum OutputDrive { 368pub enum OutputDrive {
378 OnStart, 369 OnStart,
379 Immediately, 370 Immediately,
@@ -381,7 +372,7 @@ pub enum OutputDrive {
381 372
382impl OutputDrive { 373impl OutputDrive {
383 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 374 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
384 pub const fn outdriv(&self) -> vals::Outdriv { 375 const fn outdriv(&self) -> vals::Outdriv {
385 match self { 376 match self {
386 OutputDrive::OnStart => vals::Outdriv::ONSTART, 377 OutputDrive::OnStart => vals::Outdriv::ONSTART,
387 OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY, 378 OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY,
@@ -389,7 +380,9 @@ impl OutputDrive {
389 } 380 }
390} 381}
391 382
383/// Master clock divider.
392#[derive(Copy, Clone, PartialEq)] 384#[derive(Copy, Clone, PartialEq)]
385#[allow(missing_docs)]
393pub enum MasterClockDivider { 386pub enum MasterClockDivider {
394 MasterClockDisabled, 387 MasterClockDisabled,
395 Div1, 388 Div1,
@@ -412,7 +405,7 @@ pub enum MasterClockDivider {
412 405
413impl MasterClockDivider { 406impl MasterClockDivider {
414 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] 407 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
415 pub const fn mckdiv(&self) -> u8 { 408 const fn mckdiv(&self) -> u8 {
416 match self { 409 match self {
417 MasterClockDivider::MasterClockDisabled => 0, 410 MasterClockDivider::MasterClockDisabled => 0,
418 MasterClockDivider::Div1 => 0, 411 MasterClockDivider::Div1 => 0,
@@ -436,6 +429,7 @@ impl MasterClockDivider {
436} 429}
437 430
438/// [`SAI`] configuration. 431/// [`SAI`] configuration.
432#[allow(missing_docs)]
439#[non_exhaustive] 433#[non_exhaustive]
440#[derive(Copy, Clone)] 434#[derive(Copy, Clone)]
441pub struct Config { 435pub struct Config {
@@ -459,7 +453,7 @@ pub struct Config {
459 pub clock_strobe: ClockStrobe, 453 pub clock_strobe: ClockStrobe,
460 pub output_drive: OutputDrive, 454 pub output_drive: OutputDrive,
461 pub master_clock_divider: MasterClockDivider, 455 pub master_clock_divider: MasterClockDivider,
462 pub is_high_impedenane_on_inactive_slot: bool, 456 pub is_high_impedance_on_inactive_slot: bool,
463 pub fifo_threshold: FifoThreshold, 457 pub fifo_threshold: FifoThreshold,
464 pub companding: Companding, 458 pub companding: Companding,
465 pub complement_format: ComplementFormat, 459 pub complement_format: ComplementFormat,
@@ -490,7 +484,7 @@ impl Default for Config {
490 master_clock_divider: MasterClockDivider::MasterClockDisabled, 484 master_clock_divider: MasterClockDivider::MasterClockDisabled,
491 clock_strobe: ClockStrobe::Rising, 485 clock_strobe: ClockStrobe::Rising,
492 output_drive: OutputDrive::Immediately, 486 output_drive: OutputDrive::Immediately,
493 is_high_impedenane_on_inactive_slot: false, 487 is_high_impedance_on_inactive_slot: false,
494 fifo_threshold: FifoThreshold::ThreeQuarters, 488 fifo_threshold: FifoThreshold::ThreeQuarters,
495 companding: Companding::None, 489 companding: Companding::None,
496 complement_format: ComplementFormat::TwosComplement, 490 complement_format: ComplementFormat::TwosComplement,
@@ -501,23 +495,10 @@ impl Default for Config {
501} 495}
502 496
503impl Config { 497impl Config {
504 pub fn new_i2s() -> Self { 498 /// Create a new config with all default values.
499 pub fn new() -> Self {
505 return Default::default(); 500 return Default::default();
506 } 501 }
507
508 pub fn new_msb_first() -> Self {
509 Self {
510 bit_order: BitOrder::MsbFirst,
511 frame_sync_offset: FrameSyncOffset::OnFirstBit,
512 ..Default::default()
513 }
514 }
515}
516
517#[derive(Copy, Clone)]
518enum WhichSubBlock {
519 A = 0,
520 B = 1,
521} 502}
522 503
523enum RingBuffer<'d, C: Channel, W: word::Word> { 504enum RingBuffer<'d, C: Channel, W: word::Word> {
@@ -531,28 +512,6 @@ fn dr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: WhichSubBlock) -> *mut
531 ch.dr().as_ptr() as _ 512 ch.dr().as_ptr() as _
532} 513}
533 514
534pub struct SubBlock<'d, T: Instance, C: Channel, W: word::Word> {
535 _peri: PeripheralRef<'d, T>,
536 sd: Option<PeripheralRef<'d, AnyPin>>,
537 fs: Option<PeripheralRef<'d, AnyPin>>,
538 sck: Option<PeripheralRef<'d, AnyPin>>,
539 mclk: Option<PeripheralRef<'d, AnyPin>>,
540 ring_buffer: RingBuffer<'d, C, W>,
541 sub_block: WhichSubBlock,
542}
543
544pub struct SubBlockA {}
545pub struct SubBlockB {}
546
547pub struct SubBlockAPeripheral<'d, T>(PeripheralRef<'d, T>);
548pub struct SubBlockBPeripheral<'d, T>(PeripheralRef<'d, T>);
549
550pub struct Sai<'d, T: Instance> {
551 _peri: PeripheralRef<'d, T>,
552 sub_block_a_peri: Option<SubBlockAPeripheral<'d, T>>,
553 sub_block_b_peri: Option<SubBlockBPeripheral<'d, T>>,
554}
555
556// return the type for (sd, sck) 515// return the type for (sd, sck)
557fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) { 516fn get_af_types(mode: Mode, tx_rx: TxRx) -> (AFType, AFType) {
558 ( 517 (
@@ -591,34 +550,6 @@ fn get_ring_buffer<'d, T: Instance, C: Channel, W: word::Word>(
591 } 550 }
592} 551}
593 552
594impl<'d, T: Instance> Sai<'d, T> {
595 pub fn new(peri: impl Peripheral<P = T> + 'd) -> Self {
596 T::enable_and_reset();
597
598 Self {
599 _peri: unsafe { peri.clone_unchecked().into_ref() },
600 sub_block_a_peri: Some(SubBlockAPeripheral(unsafe { peri.clone_unchecked().into_ref() })),
601 sub_block_b_peri: Some(SubBlockBPeripheral(peri.into_ref())),
602 }
603 }
604
605 pub fn take_sub_block_a(self: &mut Self) -> Option<SubBlockAPeripheral<'d, T>> {
606 if self.sub_block_a_peri.is_some() {
607 self.sub_block_a_peri.take()
608 } else {
609 None
610 }
611 }
612
613 pub fn take_sub_block_b(self: &mut Self) -> Option<SubBlockBPeripheral<'d, T>> {
614 if self.sub_block_b_peri.is_some() {
615 self.sub_block_b_peri.take()
616 } else {
617 None
618 }
619 }
620}
621
622fn update_synchronous_config(config: &mut Config) { 553fn update_synchronous_config(config: &mut Config) {
623 config.mode = Mode::Slave; 554 config.mode = Mode::Slave;
624 config.sync_output = false; 555 config.sync_output = false;
@@ -636,122 +567,58 @@ fn update_synchronous_config(config: &mut Config) {
636 } 567 }
637} 568}
638 569
639impl SubBlockA { 570/// SAI subblock instance.
640 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( 571pub struct SubBlock<'d, T, S: SubBlockInstance> {
641 peri: SubBlockAPeripheral<'d, T>, 572 peri: PeripheralRef<'d, T>,
642 sck: impl Peripheral<P = impl SckAPin<T>> + 'd, 573 _phantom: PhantomData<S>,
643 sd: impl Peripheral<P = impl SdAPin<T>> + 'd, 574}
644 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
645 mclk: impl Peripheral<P = impl MclkAPin<T>> + 'd,
646 dma: impl Peripheral<P = C> + 'd,
647 dma_buf: &'d mut [W],
648 mut config: Config,
649 ) -> SubBlock<'d, T, C, W>
650 where
651 C: Channel + DmaA<T>,
652 {
653 into_ref!(mclk);
654
655 let (_sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
656
657 mclk.set_as_af(mclk.af_num(), ck_af_type);
658 mclk.set_speed(crate::gpio::Speed::VeryHigh);
659
660 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
661 config.master_clock_divider = MasterClockDivider::Div1;
662 }
663
664 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
665 }
666
667 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>(
668 peri: SubBlockAPeripheral<'d, T>,
669 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
670 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
671 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
672 dma: impl Peripheral<P = C> + 'd,
673 dma_buf: &'d mut [W],
674 config: Config,
675 ) -> SubBlock<'d, T, C, W>
676 where
677 C: Channel + DmaA<T>,
678 {
679 let peri = peri.0;
680 into_ref!(peri, dma, sck, sd, fs);
681
682 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
683 sd.set_as_af(sd.af_num(), sd_af_type);
684 sd.set_speed(crate::gpio::Speed::VeryHigh);
685
686 sck.set_as_af(sck.af_num(), ck_af_type);
687 sck.set_speed(crate::gpio::Speed::VeryHigh);
688 fs.set_as_af(fs.af_num(), ck_af_type);
689 fs.set_speed(crate::gpio::Speed::VeryHigh);
690 575
691 let sub_block = WhichSubBlock::A; 576/// Split the main SAIx peripheral into the two subblocks.
692 let request = dma.request(); 577///
578/// You can then create a [`Sai`] driver for each each half.
579pub fn split_subblocks<'d, T: Instance>(peri: impl Peripheral<P = T> + 'd) -> (SubBlock<'d, T, A>, SubBlock<'d, T, B>) {
580 into_ref!(peri);
581 T::enable_and_reset();
693 582
694 SubBlock::new_inner( 583 (
584 SubBlock {
585 peri: unsafe { peri.clone_unchecked() },
586 _phantom: PhantomData,
587 },
588 SubBlock {
695 peri, 589 peri,
696 sub_block, 590 _phantom: PhantomData,
697 Some(sck.map_into()), 591 },
698 None, 592 )
699 Some(sd.map_into()), 593}
700 Some(fs.map_into()),
701 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx),
702 config,
703 )
704 }
705
706 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>(
707 peri: SubBlockAPeripheral<'d, T>,
708 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
709 dma: impl Peripheral<P = C> + 'd,
710 dma_buf: &'d mut [W],
711 mut config: Config,
712 ) -> SubBlock<'d, T, C, W>
713 where
714 C: Channel + DmaA<T>,
715 {
716 update_synchronous_config(&mut config);
717
718 let peri = peri.0;
719 into_ref!(dma, peri, sd);
720
721 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
722
723 sd.set_as_af(sd.af_num(), sd_af_type);
724 sd.set_speed(crate::gpio::Speed::VeryHigh);
725
726 let sub_block = WhichSubBlock::A;
727 let request = dma.request();
728 594
729 SubBlock::new_inner( 595/// SAI sub-block driver.
730 peri, 596pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> {
731 sub_block, 597 _peri: PeripheralRef<'d, T>,
732 None, 598 sd: Option<PeripheralRef<'d, AnyPin>>,
733 None, 599 fs: Option<PeripheralRef<'d, AnyPin>>,
734 Some(sd.map_into()), 600 sck: Option<PeripheralRef<'d, AnyPin>>,
735 None, 601 mclk: Option<PeripheralRef<'d, AnyPin>>,
736 get_ring_buffer::<T, C, W>(dma, dma_buf, request, sub_block, config.tx_rx), 602 ring_buffer: RingBuffer<'d, C, W>,
737 config, 603 sub_block: WhichSubBlock,
738 )
739 }
740} 604}
741 605
742impl SubBlockB { 606impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
743 pub fn new_asynchronous_with_mclk<'d, T: Instance, C: Channel, W: word::Word>( 607 /// Create a new SAI driver in asynchronous mode with MCLK.
744 peri: SubBlockBPeripheral<'d, T>, 608 ///
745 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 609 /// You can obtain the [`SubBlock`] with [`split_subblocks`].
746 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 610 pub fn new_asynchronous_with_mclk<S: SubBlockInstance>(
747 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 611 peri: SubBlock<'d, T, S>,
748 mclk: impl Peripheral<P = impl MclkBPin<T>> + 'd, 612 sck: impl Peripheral<P = impl SckPin<T, S>> + 'd,
613 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
614 fs: impl Peripheral<P = impl FsPin<T, S>> + 'd,
615 mclk: impl Peripheral<P = impl MclkPin<T, S>> + 'd,
749 dma: impl Peripheral<P = C> + 'd, 616 dma: impl Peripheral<P = C> + 'd,
750 dma_buf: &'d mut [W], 617 dma_buf: &'d mut [W],
751 mut config: Config, 618 mut config: Config,
752 ) -> SubBlock<'d, T, C, W> 619 ) -> Self
753 where 620 where
754 C: Channel + DmaB<T>, 621 C: Channel + Dma<T, S>,
755 { 622 {
756 into_ref!(mclk); 623 into_ref!(mclk);
757 624
@@ -767,23 +634,25 @@ impl SubBlockB {
767 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config) 634 Self::new_asynchronous(peri, sck, sd, fs, dma, dma_buf, config)
768 } 635 }
769 636
770 pub fn new_asynchronous<'d, T: Instance, C: Channel, W: word::Word>( 637 /// Create a new SAI driver in asynchronous mode without MCLK.
771 peri: SubBlockBPeripheral<'d, T>, 638 ///
772 sck: impl Peripheral<P = impl SckBPin<T>> + 'd, 639 /// You can obtain the [`SubBlock`] with [`split_subblocks`].
773 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 640 pub fn new_asynchronous<S: SubBlockInstance>(
774 fs: impl Peripheral<P = impl FsBPin<T>> + 'd, 641 peri: SubBlock<'d, T, S>,
642 sck: impl Peripheral<P = impl SckPin<T, S>> + 'd,
643 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
644 fs: impl Peripheral<P = impl FsPin<T, S>> + 'd,
775 dma: impl Peripheral<P = C> + 'd, 645 dma: impl Peripheral<P = C> + 'd,
776 dma_buf: &'d mut [W], 646 dma_buf: &'d mut [W],
777 config: Config, 647 config: Config,
778 ) -> SubBlock<'d, T, C, W> 648 ) -> Self
779 where 649 where
780 C: Channel + DmaB<T>, 650 C: Channel + Dma<T, S>,
781 { 651 {
782 let peri = peri.0; 652 let peri = peri.peri;
783 into_ref!(dma, peri, sck, sd, fs); 653 into_ref!(peri, dma, sck, sd, fs);
784 654
785 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx); 655 let (sd_af_type, ck_af_type) = get_af_types(config.mode, config.tx_rx);
786
787 sd.set_as_af(sd.af_num(), sd_af_type); 656 sd.set_as_af(sd.af_num(), sd_af_type);
788 sd.set_speed(crate::gpio::Speed::VeryHigh); 657 sd.set_speed(crate::gpio::Speed::VeryHigh);
789 658
@@ -792,10 +661,10 @@ impl SubBlockB {
792 fs.set_as_af(fs.af_num(), ck_af_type); 661 fs.set_as_af(fs.af_num(), ck_af_type);
793 fs.set_speed(crate::gpio::Speed::VeryHigh); 662 fs.set_speed(crate::gpio::Speed::VeryHigh);
794 663
795 let sub_block = WhichSubBlock::B; 664 let sub_block = S::WHICH;
796 let request = dma.request(); 665 let request = dma.request();
797 666
798 SubBlock::new_inner( 667 Self::new_inner(
799 peri, 668 peri,
800 sub_block, 669 sub_block,
801 Some(sck.map_into()), 670 Some(sck.map_into()),
@@ -807,18 +676,22 @@ impl SubBlockB {
807 ) 676 )
808 } 677 }
809 678
810 pub fn new_synchronous<'d, T: Instance, C: Channel, W: word::Word>( 679 /// Create a new SAI driver in synchronous mode.
811 peri: SubBlockBPeripheral<'d, T>, 680 ///
812 sd: impl Peripheral<P = impl SdBPin<T>> + 'd, 681 /// You can obtain the [`SubBlock`] with [`split_subblocks`].
682 pub fn new_synchronous<S: SubBlockInstance>(
683 peri: SubBlock<'d, T, S>,
684 sd: impl Peripheral<P = impl SdPin<T, S>> + 'd,
813 dma: impl Peripheral<P = C> + 'd, 685 dma: impl Peripheral<P = C> + 'd,
814 dma_buf: &'d mut [W], 686 dma_buf: &'d mut [W],
815 mut config: Config, 687 mut config: Config,
816 ) -> SubBlock<'d, T, C, W> 688 ) -> Self
817 where 689 where
818 C: Channel + DmaB<T>, 690 C: Channel + Dma<T, S>,
819 { 691 {
820 update_synchronous_config(&mut config); 692 update_synchronous_config(&mut config);
821 let peri = peri.0; 693
694 let peri = peri.peri;
822 into_ref!(dma, peri, sd); 695 into_ref!(dma, peri, sd);
823 696
824 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx); 697 let (sd_af_type, _ck_af_type) = get_af_types(config.mode, config.tx_rx);
@@ -826,10 +699,10 @@ impl SubBlockB {
826 sd.set_as_af(sd.af_num(), sd_af_type); 699 sd.set_as_af(sd.af_num(), sd_af_type);
827 sd.set_speed(crate::gpio::Speed::VeryHigh); 700 sd.set_speed(crate::gpio::Speed::VeryHigh);
828 701
829 let sub_block = WhichSubBlock::B; 702 let sub_block = S::WHICH;
830 let request = dma.request(); 703 let request = dma.request();
831 704
832 SubBlock::new_inner( 705 Self::new_inner(
833 peri, 706 peri,
834 sub_block, 707 sub_block,
835 None, 708 None,
@@ -840,26 +713,6 @@ impl SubBlockB {
840 config, 713 config,
841 ) 714 )
842 } 715 }
843}
844
845impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
846 pub fn start(self: &mut Self) {
847 match self.ring_buffer {
848 RingBuffer::Writable(ref mut rb) => {
849 rb.start();
850 }
851 RingBuffer::Readable(ref mut rb) => {
852 rb.start();
853 }
854 }
855 }
856
857 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
858 match ring_buffer {
859 RingBuffer::Writable(_) => true,
860 _ => false,
861 }
862 }
863 716
864 fn new_inner( 717 fn new_inner(
865 peri: impl Peripheral<P = T> + 'd, 718 peri: impl Peripheral<P = T> + 'd,
@@ -929,7 +782,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
929 w.set_cpl(config.complement_format.cpl()); 782 w.set_cpl(config.complement_format.cpl());
930 w.set_muteval(config.mute_value.muteval()); 783 w.set_muteval(config.mute_value.muteval());
931 w.set_mutecnt(config.mute_detection_counter.0 as u8); 784 w.set_mutecnt(config.mute_detection_counter.0 as u8);
932 w.set_tris(config.is_high_impedenane_on_inactive_slot); 785 w.set_tris(config.is_high_impedance_on_inactive_slot);
933 }); 786 });
934 787
935 ch.frcr().modify(|w| { 788 ch.frcr().modify(|w| {
@@ -965,10 +818,31 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
965 } 818 }
966 } 819 }
967 820
821 /// Start the SAI driver.
822 pub fn start(&mut self) {
823 match self.ring_buffer {
824 RingBuffer::Writable(ref mut rb) => {
825 rb.start();
826 }
827 RingBuffer::Readable(ref mut rb) => {
828 rb.start();
829 }
830 }
831 }
832
833 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
834 match ring_buffer {
835 RingBuffer::Writable(_) => true,
836 _ => false,
837 }
838 }
839
840 /// Reset SAI operation.
968 pub fn reset() { 841 pub fn reset() {
969 T::enable_and_reset(); 842 T::enable_and_reset();
970 } 843 }
971 844
845 /// Flush.
972 pub fn flush(&mut self) { 846 pub fn flush(&mut self) {
973 let ch = T::REGS.ch(self.sub_block as usize); 847 let ch = T::REGS.ch(self.sub_block as usize);
974 ch.cr1().modify(|w| w.set_saien(false)); 848 ch.cr1().modify(|w| w.set_saien(false));
@@ -983,19 +857,18 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
983 ch.cr1().modify(|w| w.set_saien(true)); 857 ch.cr1().modify(|w| w.set_saien(true));
984 } 858 }
985 859
860 /// Enable or disable mute.
986 pub fn set_mute(&mut self, value: bool) { 861 pub fn set_mute(&mut self, value: bool) {
987 let ch = T::REGS.ch(self.sub_block as usize); 862 let ch = T::REGS.ch(self.sub_block as usize);
988 ch.cr2().modify(|w| w.set_mute(value)); 863 ch.cr2().modify(|w| w.set_mute(value));
989 } 864 }
990 865
991 #[allow(dead_code)] 866 /// Write data to the SAI ringbuffer.
992 /// Reconfigures it with the supplied config. 867 ///
993 fn reconfigure(&mut self, _config: Config) {} 868 /// This appends the data to the buffer and returns immediately. The
994 869 /// data will be transmitted in the background.
995 pub fn get_current_config(&self) -> Config { 870 ///
996 Config::default() 871 /// If there's no space in the buffer, this waits until there is.
997 }
998
999 pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { 872 pub async fn write(&mut self, data: &[W]) -> Result<(), Error> {
1000 match &mut self.ring_buffer { 873 match &mut self.ring_buffer {
1001 RingBuffer::Writable(buffer) => { 874 RingBuffer::Writable(buffer) => {
@@ -1006,6 +879,12 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
1006 } 879 }
1007 } 880 }
1008 881
882 /// Read data from the SAI ringbuffer.
883 ///
884 /// SAI is always receiving data in the background. This function pops already-received
885 /// data from the buffer.
886 ///
887 /// If there's less than `data.len()` data in the buffer, this waits until there is.
1009 pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { 888 pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> {
1010 match &mut self.ring_buffer { 889 match &mut self.ring_buffer {
1011 RingBuffer::Readable(buffer) => { 890 RingBuffer::Readable(buffer) => {
@@ -1017,7 +896,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> SubBlock<'d, T, C, W> {
1017 } 896 }
1018} 897}
1019 898
1020impl<'d, T: Instance, C: Channel, W: word::Word> Drop for SubBlock<'d, T, C, W> { 899impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> {
1021 fn drop(&mut self) { 900 fn drop(&mut self) {
1022 let ch = T::REGS.ch(self.sub_block as usize); 901 let ch = T::REGS.ch(self.sub_block as usize);
1023 ch.cr1().modify(|w| w.set_saien(false)); 902 ch.cr1().modify(|w| w.set_saien(false));
@@ -1034,22 +913,43 @@ pub(crate) mod sealed {
1034 pub trait Instance { 913 pub trait Instance {
1035 const REGS: Regs; 914 const REGS: Regs;
1036 } 915 }
916
917 #[derive(Copy, Clone)]
918 pub enum WhichSubBlock {
919 A = 0,
920 B = 1,
921 }
922
923 pub trait SubBlock {
924 const WHICH: WhichSubBlock;
925 }
1037} 926}
1038 927
1039pub trait Word: word::Word {} 928/// Sub-block instance trait.
929pub trait SubBlockInstance: sealed::SubBlock {}
1040 930
931/// Sub-block A.
932pub enum A {}
933impl sealed::SubBlock for A {
934 const WHICH: WhichSubBlock = WhichSubBlock::A;
935}
936impl SubBlockInstance for A {}
937
938/// Sub-block B.
939pub enum B {}
940impl sealed::SubBlock for B {
941 const WHICH: WhichSubBlock = WhichSubBlock::B;
942}
943impl SubBlockInstance for B {}
944
945/// SAI instance trait.
1041pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 946pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
1042pin_trait!(SckAPin, Instance); 947pin_trait!(SckPin, Instance, SubBlockInstance);
1043pin_trait!(SckBPin, Instance); 948pin_trait!(FsPin, Instance, SubBlockInstance);
1044pin_trait!(FsAPin, Instance); 949pin_trait!(SdPin, Instance, SubBlockInstance);
1045pin_trait!(FsBPin, Instance); 950pin_trait!(MclkPin, Instance, SubBlockInstance);
1046pin_trait!(SdAPin, Instance); 951
1047pin_trait!(SdBPin, Instance); 952dma_trait!(Dma, Instance, SubBlockInstance);
1048pin_trait!(MclkAPin, Instance);
1049pin_trait!(MclkBPin, Instance);
1050
1051dma_trait!(DmaA, Instance);
1052dma_trait!(DmaB, Instance);
1053 953
1054foreach_peripheral!( 954foreach_peripheral!(
1055 (sai, $inst:ident) => { 955 (sai, $inst:ident) => {
@@ -1060,13 +960,3 @@ foreach_peripheral!(
1060 impl Instance for peripherals::$inst {} 960 impl Instance for peripherals::$inst {}
1061 }; 961 };
1062); 962);
1063
1064impl<'d, T: Instance> SetConfig for Sai<'d, T> {
1065 type Config = Config;
1066 type ConfigError = ();
1067 fn set_config(&mut self, _config: &Self::Config) -> Result<(), ()> {
1068 // self.reconfigure(*config);
1069
1070 Ok(())
1071 }
1072}
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 27a12062c..6099b9f43 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -1,3 +1,4 @@
1//! Secure Digital / MultiMedia Card (SDMMC)
1#![macro_use] 2#![macro_use]
2 3
3use core::default::Default; 4use core::default::Default;
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 92599c75e..5a1ad3e91 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -1,3 +1,4 @@
1//! Serial Peripheral Interface (SPI)
1#![macro_use] 2#![macro_use]
2 3
3use core::ptr; 4use core::ptr;
diff --git a/embassy-stm32/src/traits.rs b/embassy-stm32/src/traits.rs
index b4166e71a..13f695821 100644
--- a/embassy-stm32/src/traits.rs
+++ b/embassy-stm32/src/traits.rs
@@ -1,18 +1,18 @@
1#![macro_use] 1#![macro_use]
2 2
3macro_rules! pin_trait { 3macro_rules! pin_trait {
4 ($signal:ident, $instance:path) => { 4 ($signal:ident, $instance:path $(, $mode:path)?) => {
5 #[doc = concat!(stringify!($signal), " pin trait")] 5 #[doc = concat!(stringify!($signal), " pin trait")]
6 pub trait $signal<T: $instance>: crate::gpio::Pin { 6 pub trait $signal<T: $instance $(, M: $mode)?>: crate::gpio::Pin {
7 #[doc = concat!("Get the AF number needed to use this pin as", stringify!($signal))] 7 #[doc = concat!("Get the AF number needed to use this pin as ", stringify!($signal))]
8 fn af_num(&self) -> u8; 8 fn af_num(&self) -> u8;
9 } 9 }
10 }; 10 };
11} 11}
12 12
13macro_rules! pin_trait_impl { 13macro_rules! pin_trait_impl {
14 (crate::$mod:ident::$trait:ident, $instance:ident, $pin:ident, $af:expr) => { 14 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, $pin:ident, $af:expr) => {
15 impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$pin { 15 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$pin {
16 fn af_num(&self) -> u8 { 16 fn af_num(&self) -> u8 {
17 $af 17 $af
18 } 18 }
@@ -23,9 +23,9 @@ macro_rules! pin_trait_impl {
23// ==================== 23// ====================
24 24
25macro_rules! dma_trait { 25macro_rules! dma_trait {
26 ($signal:ident, $instance:path) => { 26 ($signal:ident, $instance:path$(, $mode:path)?) => {
27 #[doc = concat!(stringify!($signal), " DMA request trait")] 27 #[doc = concat!(stringify!($signal), " DMA request trait")]
28 pub trait $signal<T: $instance>: crate::dma::Channel { 28 pub trait $signal<T: $instance $(, M: $mode)?>: crate::dma::Channel {
29 #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))] 29 #[doc = concat!("Get the DMA request number needed to use this channel as", stringify!($signal))]
30 /// Note: in some chips, ST calls this the "channel", and calls channels "streams". 30 /// Note: in some chips, ST calls this the "channel", and calls channels "streams".
31 /// `embassy-stm32` always uses the "channel" and "request number" names. 31 /// `embassy-stm32` always uses the "channel" and "request number" names.
@@ -37,8 +37,8 @@ macro_rules! dma_trait {
37#[allow(unused)] 37#[allow(unused)]
38macro_rules! dma_trait_impl { 38macro_rules! dma_trait_impl {
39 // DMAMUX 39 // DMAMUX
40 (crate::$mod:ident::$trait:ident, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => { 40 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dmamux: $dmamux:ident}, $request:expr) => {
41 impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T 41 impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T
42 where 42 where
43 T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>, 43 T: crate::dma::Channel + crate::dma::MuxChannel<Mux = crate::dma::$dmamux>,
44 { 44 {
@@ -49,8 +49,8 @@ macro_rules! dma_trait_impl {
49 }; 49 };
50 50
51 // DMAMUX 51 // DMAMUX
52 (crate::$mod:ident::$trait:ident, $instance:ident, {dma: $dma:ident}, $request:expr) => { 52 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {dma: $dma:ident}, $request:expr) => {
53 impl<T> crate::$mod::$trait<crate::peripherals::$instance> for T 53 impl<T> crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for T
54 where 54 where
55 T: crate::dma::Channel, 55 T: crate::dma::Channel,
56 { 56 {
@@ -61,8 +61,8 @@ macro_rules! dma_trait_impl {
61 }; 61 };
62 62
63 // DMA/GPDMA, without DMAMUX 63 // DMA/GPDMA, without DMAMUX
64 (crate::$mod:ident::$trait:ident, $instance:ident, {channel: $channel:ident}, $request:expr) => { 64 (crate::$mod:ident::$trait:ident$(<$mode:ident>)?, $instance:ident, {channel: $channel:ident}, $request:expr) => {
65 impl crate::$mod::$trait<crate::peripherals::$instance> for crate::peripherals::$channel { 65 impl crate::$mod::$trait<crate::peripherals::$instance $(, crate::$mod::$mode)?> for crate::peripherals::$channel {
66 fn request(&self) -> crate::dma::Request { 66 fn request(&self) -> crate::dma::Request {
67 $request 67 $request
68 } 68 }
diff --git a/embassy-stm32/src/uid.rs b/embassy-stm32/src/uid.rs
index 6dcfcb96e..aa13586f8 100644
--- a/embassy-stm32/src/uid.rs
+++ b/embassy-stm32/src/uid.rs
@@ -1,3 +1,5 @@
1//! Unique ID (UID)
2
1/// Get this device's unique 96-bit ID. 3/// Get this device's unique 96-bit ID.
2pub fn uid() -> &'static [u8; 12] { 4pub fn uid() -> &'static [u8; 12] {
3 unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() } 5 unsafe { &*crate::pac::UID.uid(0).as_ptr().cast::<[u8; 12]>() }
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index dfa1f3a6a..e2e3bd3eb 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,3 +1,4 @@
1//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART)
1#![macro_use] 2#![macro_use]
2 3
3use core::future::poll_fn; 4use core::future::poll_fn;
diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs
index be54a3d10..1abd031dd 100644
--- a/embassy-stm32/src/usb_otg/mod.rs
+++ b/embassy-stm32/src/usb_otg/mod.rs
@@ -1,3 +1,5 @@
1//! USB On The Go (OTG)
2
1use crate::rcc::RccPeripheral; 3use crate::rcc::RccPeripheral;
2use crate::{interrupt, peripherals}; 4use crate::{interrupt, peripherals};
3 5
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index c7c2694e0..5751a9ff3 100644
--- a/embassy-stm32/src/wdg/mod.rs
+++ b/embassy-stm32/src/wdg/mod.rs
@@ -1,3 +1,4 @@
1//! Watchdog Timer (IWDG, WWDG)
1use core::marker::PhantomData; 2use core::marker::PhantomData;
2 3
3use embassy_hal_internal::{into_ref, Peripheral}; 4use embassy_hal_internal::{into_ref, Peripheral};