Skip to content

Commit cefc3f8

Browse files
algestenburrbull
authored andcommitted
Enable DMA for DualI2sDriver main() and ext() respectively
1 parent 24534da commit cefc3f8

File tree

1 file changed

+69
-1
lines changed

1 file changed

+69
-1
lines changed

src/i2s.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,12 @@ dual_i2s!(pac::SPI3, pac::I2S3EXT, DualI2s3, i2s3, i2s_apb1_clk);
449449
mod dma {
450450
use super::*;
451451
use crate::dma::traits::{DMASet, PeriAddress};
452+
use crate::pac::spi1::RegisterBlock;
453+
use core::marker::PhantomData;
452454
use core::ops::Deref;
453-
use stm32_i2s_v12x::driver::I2sDriver;
455+
use stm32_i2s_v12x::driver::{I2sCore, I2sDriver};
456+
use stm32_i2s_v12x::transfer::{Ext, Main};
457+
use stm32_i2s_v12x::DualI2sPeripheral;
454458

455459
/// I2S DMA reads from and writes to the data register
456460
unsafe impl<SPI: Instance, MS, TR, STD> PeriAddress for I2sDriver<I2s<SPI>, MS, TR, STD>
@@ -474,4 +478,68 @@ mod dma {
474478
SPI: DMASet<STREAM, CHANNEL, DIR>,
475479
{
476480
}
481+
482+
pub trait DualI2sDmaTargetExt<I, PART, MS, DIR, STD> {
483+
fn dma_target(&self) -> DualI2sDmaTarget<I, PART, MS, DIR, STD>;
484+
}
485+
impl<I, PART, MS, DIR, STD> DualI2sDmaTargetExt<I, PART, MS, DIR, STD>
486+
for I2sCore<I, PART, MS, DIR, STD>
487+
{
488+
fn dma_target(&self) -> DualI2sDmaTarget<I, PART, MS, DIR, STD> {
489+
DualI2sDmaTarget {
490+
_dual_i2s_peripheral: PhantomData,
491+
_part: PhantomData,
492+
_ms: PhantomData,
493+
_dir: PhantomData,
494+
_std: PhantomData,
495+
}
496+
}
497+
}
498+
499+
/// - `I`: The [DualI2sPeripheral] controlled by the I2sCore.
500+
/// - `PART`: `Main` or `Ext`. The part of [DualI2sPeripheral] controlled by I2sCore.
501+
/// - `MS`: `Master` or `Slave`. The role of the I2sCore. Only a `Main` I2sCore can be Master.
502+
/// - `DIR` : `Transmit` or `Receive`. Communication direction.
503+
/// - `STD`: I2S standard, eg `Philips`
504+
pub struct DualI2sDmaTarget<I, PART, MS, DIR, STD> {
505+
_dual_i2s_peripheral: PhantomData<I>,
506+
_part: PhantomData<PART>,
507+
_ms: PhantomData<MS>,
508+
_dir: PhantomData<DIR>,
509+
_std: PhantomData<STD>,
510+
}
511+
512+
macro_rules! dual_dma {
513+
($ext: ty, $reg: ident) => {
514+
/// I2S DMA reads from and writes to the data register
515+
unsafe impl<SPIext: DualInstance, MS, TR, STD> PeriAddress
516+
for DualI2sDmaTarget<DualI2s<SPIext>, $ext, MS, TR, STD>
517+
where
518+
DualI2s<SPIext>: DualI2sPeripheral,
519+
{
520+
/// SPI_DR is only 16 bits. Multiple transfers are needed for a 24-bit or 32-bit sample,
521+
/// as explained in the reference manual.
522+
type MemSize = u16;
523+
524+
fn address(&self) -> u32 {
525+
let reg = unsafe { &*(DualI2s::$reg as *const RegisterBlock) };
526+
(&reg.dr) as *const _ as u32
527+
}
528+
}
529+
};
530+
}
531+
532+
dual_dma!(Main, MAIN_REGISTERS);
533+
dual_dma!(Ext, EXT_REGISTERS);
534+
535+
/// DMA is available for I2S based on the underlying implementations for SPI
536+
unsafe impl<SPIext: DualInstance, PART, MS, TR, STD, STREAM, const CHANNEL: u8, DIR>
537+
DMASet<STREAM, CHANNEL, DIR> for DualI2sDmaTarget<DualI2s<SPIext>, PART, MS, TR, STD>
538+
where
539+
SPIext: DMASet<STREAM, CHANNEL, DIR>,
540+
{
541+
}
477542
}
543+
544+
#[cfg(feature = "stm32_i2s_v12x")]
545+
pub use dma::{DualI2sDmaTarget, DualI2sDmaTargetExt};

0 commit comments

Comments
 (0)