* Implement I2S type erasure

* Clean up
This commit is contained in:
Dániel Buga 2024-10-22 08:33:27 +02:00 committed by GitHub
parent a754e411b1
commit d914a0301f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 204 additions and 50 deletions

View File

@ -14,11 +14,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add burst transfer support to DMA buffers (#2336) - Add burst transfer support to DMA buffers (#2336)
- `AnyPin` now implements `From<GpioPin<N>>`. (#2326) - `AnyPin` now implements `From<GpioPin<N>>`. (#2326)
- Added `AnySpi` and `AnySpiDmaChannel`. (#2334) - Added `AnySpi` and `AnySpiDmaChannel`. (#2334)
- Added `AnyI2s` and `AnyI2sDmaChannel`. (#2367)
- `Pins::steal()` to unsafely obtain GPIO. (#2335) - `Pins::steal()` to unsafely obtain GPIO. (#2335)
### Changed ### Changed
- Peripheral type erasure for SPI (#2334) - Peripheral type erasure for SPI (#2334)
- Peripheral type erasure for I2S (#2367)
### Fixed ### Fixed

View File

@ -29,6 +29,7 @@ You no longer have to specify the peripheral instance in the driver's type for t
peripherals: peripherals:
- SPI (both master and slave) - SPI (both master and slave)
- I2S
```diff ```diff
-Spi<'static, SPI2, FullDuplexMode> -Spi<'static, SPI2, FullDuplexMode>
@ -36,6 +37,9 @@ peripherals:
-SpiDma<'static, SPI2, HalfDuplexMode, Blocking> -SpiDma<'static, SPI2, HalfDuplexMode, Blocking>
+SpiDma<'static, HalfDuplexMode, Blocking> +SpiDma<'static, HalfDuplexMode, Blocking>
-I2sTx<'static, I2S0, Async>
+I2sTx<'static, Async>
``` ```
Note that you may still specify the instance if you need to. To do this, we provide `_typed` Note that you may still specify the instance if you need to. To do this, we provide `_typed`

View File

@ -787,6 +787,15 @@ macro_rules! ImplI2sChannel {
} }
} }
impl DmaChannelConvert<AnyI2sDmaChannel> for [<I2s $num DmaChannel>] {
fn degrade_rx(rx: I2sDmaRxChannelImpl<Self>) -> I2sDmaRxChannelImpl<AnyI2sDmaChannelInner> {
I2sDmaRxChannelImpl(rx.0.into())
}
fn degrade_tx(tx: I2sDmaTxChannelImpl<Self>) -> I2sDmaTxChannelImpl<AnyI2sDmaChannelInner> {
I2sDmaTxChannelImpl(tx.0.into())
}
}
#[doc = concat!("Creates a channel for I2S", $num)] #[doc = concat!("Creates a channel for I2S", $num)]
pub struct [<I2s $num DmaChannelCreator>] {} pub struct [<I2s $num DmaChannelCreator>] {}
@ -942,3 +951,41 @@ impl PdmaChannel for AnySpiDmaChannelInner {
} }
} }
} }
/// A marker for I2S-compatible type-erased DMA channels.
pub struct AnyI2sDmaChannel;
impl crate::private::Sealed for AnyI2sDmaChannel {}
impl DmaChannel for AnyI2sDmaChannel {
type Rx = I2sDmaRxChannelImpl<AnyI2sDmaChannelInner>;
type Tx = I2sDmaTxChannelImpl<AnyI2sDmaChannelInner>;
}
crate::any_enum! {
#[doc(hidden)]
pub enum AnyI2sDmaChannelInner {
I2s0(I2s0DmaChannel),
#[cfg(i2s1)]
I2s1(I2s1DmaChannel),
}
}
impl crate::private::Sealed for AnyI2sDmaChannelInner {}
impl PdmaChannel for AnyI2sDmaChannelInner {
type RegisterBlock = I2sRegisterBlock;
delegate::delegate! {
to match self {
AnyI2sDmaChannelInner::I2s0(channel) => channel,
#[cfg(i2s1)]
AnyI2sDmaChannelInner::I2s1(channel) => channel,
} {
fn register_block(&self) -> &I2sRegisterBlock;
fn tx_waker(&self) -> &'static AtomicWaker;
fn rx_waker(&self) -> &'static AtomicWaker;
fn is_compatible_with(&self, peripheral: &impl PeripheralMarker) -> bool;
}
}
}

View File

@ -92,6 +92,7 @@ use crate::{
DescriptorChain, DescriptorChain,
DmaChannelConvert, DmaChannelConvert,
DmaDescriptor, DmaDescriptor,
DmaEligible,
DmaError, DmaError,
DmaTransferRx, DmaTransferRx,
DmaTransferRxCircular, DmaTransferRxCircular,
@ -252,26 +253,26 @@ impl DataFormat {
} }
/// Instance of the I2S peripheral driver /// Instance of the I2S peripheral driver
pub struct I2s<'d, T, DmaMode> pub struct I2s<'d, DmaMode, T = AnyI2s>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
{ {
/// Handles the reception (RX) side of the I2S peripheral. /// Handles the reception (RX) side of the I2S peripheral.
pub i2s_rx: RxCreator<'d, T, DmaMode>, pub i2s_rx: RxCreator<'d, DmaMode, T>,
/// Handles the transmission (TX) side of the I2S peripheral. /// Handles the transmission (TX) side of the I2S peripheral.
pub i2s_tx: TxCreator<'d, T, DmaMode>, pub i2s_tx: TxCreator<'d, DmaMode, T>,
phantom: PhantomData<DmaMode>, phantom: PhantomData<DmaMode>,
} }
impl<'d, T, DmaMode> I2s<'d, T, DmaMode> impl<'d, DmaMode, T> I2s<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
{ {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn new_internal<CH>( fn new_internal<CH>(
i2s: impl Peripheral<P = T> + 'd, i2s: PeripheralRef<'d, T>,
standard: Standard, standard: Standard,
data_format: DataFormat, data_format: DataFormat,
sample_rate: impl Into<fugit::HertzU32>, sample_rate: impl Into<fugit::HertzU32>,
@ -282,7 +283,6 @@ where
where where
CH: DmaChannelConvert<T::Dma>, CH: DmaChannelConvert<T::Dma>,
{ {
crate::into_ref!(i2s);
channel.runtime_ensure_compatible(&i2s); channel.runtime_ensure_compatible(&i2s);
// on ESP32-C3 / ESP32-S3 and later RX and TX are independent and // on ESP32-C3 / ESP32-S3 and later RX and TX are independent and
// could be configured totally independently but for now handle all // could be configured totally independently but for now handle all
@ -314,7 +314,7 @@ where
} }
} }
impl<'d, T, DmaMode> I2s<'d, T, DmaMode> impl<'d, DmaMode, T> I2s<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -352,14 +352,14 @@ where
} }
} }
impl<'d, I, DmaMode> crate::private::Sealed for I2s<'d, I, DmaMode> impl<'d, DmaMode, I> crate::private::Sealed for I2s<'d, DmaMode, I>
where where
I: RegisterAccess, I: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
{ {
} }
impl<'d, I, DmaMode> InterruptConfigurable for I2s<'d, I, DmaMode> impl<'d, DmaMode, I> InterruptConfigurable for I2s<'d, DmaMode, I>
where where
I: RegisterAccess, I: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -369,7 +369,38 @@ where
} }
} }
impl<'d, T, DmaMode> I2s<'d, T, DmaMode> impl<'d, DmaMode> I2s<'d, DmaMode>
where
DmaMode: Mode,
{
/// Construct a new I2S peripheral driver instance for the first I2S
/// peripheral
#[allow(clippy::too_many_arguments)]
pub fn new<CH>(
i2s: impl Peripheral<P = impl RegisterAccess> + 'd,
standard: Standard,
data_format: DataFormat,
sample_rate: impl Into<fugit::HertzU32>,
channel: Channel<'d, CH, DmaMode>,
rx_descriptors: &'static mut [DmaDescriptor],
tx_descriptors: &'static mut [DmaDescriptor],
) -> Self
where
CH: DmaChannelConvert<<AnyI2s as DmaEligible>::Dma>,
{
Self::new_typed(
i2s.map_into(),
standard,
data_format,
sample_rate,
channel,
rx_descriptors,
tx_descriptors,
)
}
}
impl<'d, DmaMode, T> I2s<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -377,7 +408,7 @@ where
/// Construct a new I2S peripheral driver instance for the first I2S /// Construct a new I2S peripheral driver instance for the first I2S
/// peripheral /// peripheral
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new<CH>( pub fn new_typed<CH>(
i2s: impl Peripheral<P = T> + 'd, i2s: impl Peripheral<P = T> + 'd,
standard: Standard, standard: Standard,
data_format: DataFormat, data_format: DataFormat,
@ -388,8 +419,8 @@ where
) -> Self ) -> Self
where where
CH: DmaChannelConvert<T::Dma>, CH: DmaChannelConvert<T::Dma>,
DmaMode: Mode,
{ {
crate::into_ref!(i2s);
Self::new_internal( Self::new_internal(
i2s, i2s,
standard, standard,
@ -412,7 +443,7 @@ where
} }
/// I2S TX channel /// I2S TX channel
pub struct I2sTx<'d, T, DmaMode> pub struct I2sTx<'d, DmaMode, T = AnyI2s>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
@ -422,7 +453,7 @@ where
phantom: PhantomData<DmaMode>, phantom: PhantomData<DmaMode>,
} }
impl<'d, T, DmaMode> core::fmt::Debug for I2sTx<'d, T, DmaMode> impl<'d, DmaMode, T> core::fmt::Debug for I2sTx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -432,7 +463,7 @@ where
} }
} }
impl<'d, T, DmaMode> DmaSupport for I2sTx<'d, T, DmaMode> impl<'d, DmaMode, T> DmaSupport for I2sTx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -446,7 +477,7 @@ where
} }
} }
impl<'d, T, DmaMode> DmaSupportTx for I2sTx<'d, T, DmaMode> impl<'d, DmaMode, T> DmaSupportTx for I2sTx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -462,7 +493,7 @@ where
} }
} }
impl<'d, T, DmaMode> I2sTx<'d, T, DmaMode> impl<'d, DmaMode, T> I2sTx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -544,7 +575,7 @@ where
} }
/// I2S RX channel /// I2S RX channel
pub struct I2sRx<'d, T, DmaMode> pub struct I2sRx<'d, DmaMode, T = AnyI2s>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -555,7 +586,7 @@ where
phantom: PhantomData<DmaMode>, phantom: PhantomData<DmaMode>,
} }
impl<'d, T, DmaMode> core::fmt::Debug for I2sRx<'d, T, DmaMode> impl<'d, DmaMode, T> core::fmt::Debug for I2sRx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -565,7 +596,7 @@ where
} }
} }
impl<'d, T, DmaMode> DmaSupport for I2sRx<'d, T, DmaMode> impl<'d, DmaMode, T> DmaSupport for I2sRx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -579,7 +610,7 @@ where
} }
} }
impl<'d, T, DmaMode> DmaSupportRx for I2sRx<'d, T, DmaMode> impl<'d, DmaMode, T> DmaSupportRx for I2sRx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -595,7 +626,7 @@ where
} }
} }
impl<'d, T, DmaMode> I2sRx<'d, T, DmaMode> impl<'d, DmaMode, T> I2sRx<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -728,7 +759,7 @@ mod private {
Mode, Mode,
}; };
pub struct TxCreator<'d, T, DmaMode> pub struct TxCreator<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -739,12 +770,12 @@ mod private {
pub(crate) phantom: PhantomData<DmaMode>, pub(crate) phantom: PhantomData<DmaMode>,
} }
impl<'d, T, DmaMode> TxCreator<'d, T, DmaMode> impl<'d, DmaMode, T> TxCreator<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
{ {
pub fn build(self) -> I2sTx<'d, T, DmaMode> { pub fn build(self) -> I2sTx<'d, DmaMode, T> {
I2sTx { I2sTx {
i2s: self.i2s, i2s: self.i2s,
tx_channel: self.tx_channel, tx_channel: self.tx_channel,
@ -787,7 +818,7 @@ mod private {
} }
} }
pub struct RxCreator<'d, T, DmaMode> pub struct RxCreator<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
@ -798,12 +829,12 @@ mod private {
pub(crate) phantom: PhantomData<DmaMode>, pub(crate) phantom: PhantomData<DmaMode>,
} }
impl<'d, T, DmaMode> RxCreator<'d, T, DmaMode> impl<'d, DmaMode, T> RxCreator<'d, DmaMode, T>
where where
T: RegisterAccess, T: RegisterAccess,
DmaMode: Mode, DmaMode: Mode,
{ {
pub fn build(self) -> I2sRx<'d, T, DmaMode> { pub fn build(self) -> I2sRx<'d, DmaMode, T> {
I2sRx { I2sRx {
i2s: self.i2s, i2s: self.i2s,
rx_channel: self.rx_channel, rx_channel: self.rx_channel,
@ -847,7 +878,11 @@ mod private {
} }
pub trait RegBlock: pub trait RegBlock:
crate::peripheral::Peripheral<P = Self> + PeripheralMarker + DmaEligible crate::peripheral::Peripheral<P = Self>
+ PeripheralMarker
+ DmaEligible
+ Into<super::AnyI2s>
+ 'static
{ {
fn register_block(&self) -> &RegisterBlock; fn register_block(&self) -> &RegisterBlock;
} }
@ -1559,7 +1594,6 @@ mod private {
} }
} }
#[cfg(i2s0)]
impl Signals for crate::peripherals::I2S0 { impl Signals for crate::peripherals::I2S0 {
fn mclk_signal(&self) -> OutputSignal { fn mclk_signal(&self) -> OutputSignal {
cfg_if::cfg_if! { cfg_if::cfg_if! {
@ -1709,6 +1743,48 @@ mod private {
} }
} }
impl RegBlock for super::AnyI2s {
delegate::delegate! {
to match &self.0 {
super::AnyI2sInner::I2s0(i2s) => i2s,
#[cfg(i2s1)]
super::AnyI2sInner::I2s1(i2s) => i2s,
} {
fn register_block(&self) -> &RegisterBlock;
}
}
}
impl RegisterAccessPrivate for super::AnyI2s {
delegate::delegate! {
to match &self.0 {
super::AnyI2sInner::I2s0(i2s) => i2s,
#[cfg(i2s1)]
super::AnyI2sInner::I2s1(i2s) => i2s,
} {
fn set_interrupt_handler(&self, handler: InterruptHandler);
}
}
}
impl Signals for super::AnyI2s {
delegate::delegate! {
to match &self.0 {
super::AnyI2sInner::I2s0(i2s) => i2s,
#[cfg(i2s1)]
super::AnyI2sInner::I2s1(i2s) => i2s,
} {
fn mclk_signal(&self) -> OutputSignal;
fn bclk_signal(&self) -> OutputSignal;
fn ws_signal(&self) -> OutputSignal;
fn dout_signal(&self) -> OutputSignal;
fn bclk_rx_signal(&self) -> OutputSignal;
fn ws_rx_signal(&self) -> OutputSignal;
fn din_signal(&self) -> InputSignal;
}
}
}
pub struct I2sClockDividers { pub struct I2sClockDividers {
mclk_divider: u32, mclk_divider: u32,
bclk_divider: u32, bclk_divider: u32,
@ -1801,7 +1877,7 @@ pub mod asynch {
Async, Async,
}; };
impl<'d, T> I2sTx<'d, T, Async> impl<'d, T> I2sTx<'d, Async, T>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
@ -1831,7 +1907,7 @@ pub mod asynch {
pub fn write_dma_circular_async<TXBUF: ReadBuffer>( pub fn write_dma_circular_async<TXBUF: ReadBuffer>(
mut self, mut self,
words: TXBUF, words: TXBUF,
) -> Result<I2sWriteDmaTransferAsync<'d, T, TXBUF>, Error> { ) -> Result<I2sWriteDmaTransferAsync<'d, TXBUF, T>, Error> {
let (ptr, len) = unsafe { words.read_buffer() }; let (ptr, len) = unsafe { words.read_buffer() };
// Reset TX unit and TX FIFO // Reset TX unit and TX FIFO
@ -1862,16 +1938,16 @@ pub mod asynch {
} }
/// An in-progress async circular DMA write transfer. /// An in-progress async circular DMA write transfer.
pub struct I2sWriteDmaTransferAsync<'d, T, BUFFER> pub struct I2sWriteDmaTransferAsync<'d, BUFFER, T = super::AnyI2s>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
i2s_tx: I2sTx<'d, T, Async>, i2s_tx: I2sTx<'d, Async, T>,
state: TxCircularState, state: TxCircularState,
_buffer: BUFFER, _buffer: BUFFER,
} }
impl<'d, T, BUFFER> I2sWriteDmaTransferAsync<'d, T, BUFFER> impl<'d, T, BUFFER> I2sWriteDmaTransferAsync<'d, BUFFER, T>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
@ -1911,7 +1987,7 @@ pub mod asynch {
} }
} }
impl<'d, T> I2sRx<'d, T, Async> impl<'d, T> I2sRx<'d, Async, T>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
@ -1949,7 +2025,7 @@ pub mod asynch {
pub fn read_dma_circular_async<RXBUF>( pub fn read_dma_circular_async<RXBUF>(
mut self, mut self,
mut words: RXBUF, mut words: RXBUF,
) -> Result<I2sReadDmaTransferAsync<'d, T, RXBUF>, Error> ) -> Result<I2sReadDmaTransferAsync<'d, RXBUF, T>, Error>
where where
RXBUF: WriteBuffer, RXBUF: WriteBuffer,
{ {
@ -1985,16 +2061,16 @@ pub mod asynch {
} }
/// An in-progress async circular DMA read transfer. /// An in-progress async circular DMA read transfer.
pub struct I2sReadDmaTransferAsync<'d, T, BUFFER> pub struct I2sReadDmaTransferAsync<'d, BUFFER, T = super::AnyI2s>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
i2s_rx: I2sRx<'d, T, Async>, i2s_rx: I2sRx<'d, Async, T>,
state: RxCircularState, state: RxCircularState,
_buffer: BUFFER, _buffer: BUFFER,
} }
impl<'d, T, BUFFER> I2sReadDmaTransferAsync<'d, T, BUFFER> impl<'d, T, BUFFER> I2sReadDmaTransferAsync<'d, BUFFER, T>
where where
T: RegisterAccess, T: RegisterAccess,
{ {
@ -2022,3 +2098,28 @@ pub mod asynch {
} }
} }
} }
crate::any_peripheral! {
/// Any SPI peripheral.
pub peripheral AnyI2s {
#[cfg(i2s0)]
I2s0(crate::peripherals::I2S0),
#[cfg(i2s1)]
I2s1(crate::peripherals::I2S1),
}
}
impl DmaEligible for AnyI2s {
#[cfg(gdma)]
type Dma = crate::dma::AnyGdmaChannel;
#[cfg(pdma)]
type Dma = crate::dma::AnyI2sDmaChannel;
fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
match &self.0 {
AnyI2sInner::I2s0(_) => crate::dma::DmaPeripheral::I2s0,
#[cfg(i2s1)]
AnyI2sInner::I2s1(_) => crate::dma::DmaPeripheral::I2s1,
}
}
}

View File

@ -463,14 +463,14 @@ where
T: Instance, T: Instance,
{ {
fn new_internal( fn new_internal(
spi: impl Peripheral<P = impl Into<T> + 'd> + 'd, spi: impl Peripheral<P = T> + 'd,
frequency: HertzU32, frequency: HertzU32,
mode: SpiMode, mode: SpiMode,
) -> Spi<'d, M, T> { ) -> Spi<'d, M, T> {
crate::into_ref!(spi); crate::into_ref!(spi);
let mut spi = Spi { let mut spi = Spi {
spi: spi.map_into(), spi,
_mode: PhantomData, _mode: PhantomData,
}; };
spi.spi.reset_peripheral(); spi.spi.reset_peripheral();
@ -571,11 +571,11 @@ impl<'d> Spi<'d, FullDuplexMode> {
/// All pins are optional. Setup these pins using /// All pins are optional. Setup these pins using
/// [with_pins](Self::with_pins) or individual methods for each pin. /// [with_pins](Self::with_pins) or individual methods for each pin.
pub fn new( pub fn new(
spi: impl Peripheral<P = impl Into<AnySpi> + 'd> + 'd, spi: impl Peripheral<P = impl Instance> + 'd,
frequency: HertzU32, frequency: HertzU32,
mode: SpiMode, mode: SpiMode,
) -> Spi<'d, FullDuplexMode> { ) -> Spi<'d, FullDuplexMode> {
Self::new_typed(spi, frequency, mode) Self::new_typed(spi.map_into(), frequency, mode)
} }
} }
@ -588,7 +588,7 @@ where
/// All pins are optional. Setup these pins using /// All pins are optional. Setup these pins using
/// [with_pins](Self::with_pins) or individual methods for each pin. /// [with_pins](Self::with_pins) or individual methods for each pin.
pub fn new_typed( pub fn new_typed(
spi: impl Peripheral<P = impl Into<T> + 'd> + 'd, spi: impl Peripheral<P = T> + 'd,
frequency: HertzU32, frequency: HertzU32,
mode: SpiMode, mode: SpiMode,
) -> Spi<'d, FullDuplexMode, T> { ) -> Spi<'d, FullDuplexMode, T> {
@ -666,11 +666,11 @@ impl<'d> Spi<'d, HalfDuplexMode> {
/// All pins are optional. Setup these pins using /// All pins are optional. Setup these pins using
/// [with_pins](Self::with_pins) or individual methods for each pin. /// [with_pins](Self::with_pins) or individual methods for each pin.
pub fn new_half_duplex( pub fn new_half_duplex(
spi: impl Peripheral<P = impl Into<AnySpi> + 'd> + 'd, spi: impl Peripheral<P = impl Instance> + 'd,
frequency: HertzU32, frequency: HertzU32,
mode: SpiMode, mode: SpiMode,
) -> Spi<'d, HalfDuplexMode> { ) -> Spi<'d, HalfDuplexMode> {
Self::new_half_duplex_typed(spi, frequency, mode) Self::new_half_duplex_typed(spi.map_into(), frequency, mode)
} }
} }
@ -683,7 +683,7 @@ where
/// All pins are optional. Setup these pins using /// All pins are optional. Setup these pins using
/// [with_pins](Self::with_pins) or individual methods for each pin. /// [with_pins](Self::with_pins) or individual methods for each pin.
pub fn new_half_duplex_typed( pub fn new_half_duplex_typed(
spi: impl Peripheral<P = impl Into<T> + 'd> + 'd, spi: impl Peripheral<P = T> + 'd,
frequency: HertzU32, frequency: HertzU32,
mode: SpiMode, mode: SpiMode,
) -> Spi<'d, HalfDuplexMode, T> { ) -> Spi<'d, HalfDuplexMode, T> {
@ -2372,7 +2372,7 @@ pub trait ExtendedInstance: Instance {
} }
#[doc(hidden)] #[doc(hidden)]
pub trait Instance: private::Sealed + PeripheralMarker { pub trait Instance: private::Sealed + PeripheralMarker + Into<AnySpi> + 'static {
fn register_block(&self) -> &RegisterBlock; fn register_block(&self) -> &RegisterBlock;
fn sclk_signal(&self) -> OutputSignal; fn sclk_signal(&self) -> OutputSignal;

View File

@ -57,7 +57,7 @@ impl Iterator for SampleSource {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn writer(tx_buffer: &'static mut [u8], i2s_tx: I2sTx<'static, I2S0, Async>) { async fn writer(tx_buffer: &'static mut [u8], i2s_tx: I2sTx<'static, Async>) {
let mut samples = SampleSource::new(); let mut samples = SampleSource::new();
for b in tx_buffer.iter_mut() { for b in tx_buffer.iter_mut() {
*b = samples.next().unwrap(); *b = samples.next().unwrap();