@@ -449,8 +449,12 @@ dual_i2s!(pac::SPI3, pac::I2S3EXT, DualI2s3, i2s3, i2s_apb1_clk);
449
449
mod dma {
450
450
use super :: * ;
451
451
use crate :: dma:: traits:: { DMASet , PeriAddress } ;
452
+ use crate :: pac:: spi1:: RegisterBlock ;
453
+ use core:: marker:: PhantomData ;
452
454
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 ;
454
458
455
459
/// I2S DMA reads from and writes to the data register
456
460
unsafe impl < SPI : Instance , MS , TR , STD > PeriAddress for I2sDriver < I2s < SPI > , MS , TR , STD >
@@ -474,4 +478,68 @@ mod dma {
474
478
SPI : DMASet < STREAM , CHANNEL , DIR > ,
475
479
{
476
480
}
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
+ }
477
542
}
543
+
544
+ #[ cfg( feature = "stm32_i2s_v12x" ) ]
545
+ pub use dma:: { DualI2sDmaTarget , DualI2sDmaTargetExt } ;
0 commit comments