@@ -93,7 +93,13 @@ use core::{
93
93
ptr,
94
94
sync:: atomic:: { fence, Ordering } ,
95
95
} ;
96
- use embedded_dma:: { ReadBuffer , StaticWriteBuffer , WriteBuffer } ;
96
+
97
+ use embedded_dma:: { StaticReadBuffer , StaticWriteBuffer , WriteBuffer } ;
98
+
99
+ use traits:: {
100
+ sealed:: Bits , Direction , DoubleBufferedConfig , DoubleBufferedStream ,
101
+ MasterStream , Stream , TargetAddress ,
102
+ } ;
97
103
98
104
#[ macro_use]
99
105
mod macros;
@@ -106,10 +112,6 @@ pub mod bdma;
106
112
pub mod mdma;
107
113
108
114
pub mod traits;
109
- use traits:: {
110
- sealed:: Bits , Direction , DoubleBufferedConfig , DoubleBufferedStream ,
111
- MasterStream , Stream , TargetAddress ,
112
- } ;
113
115
114
116
/// Errors.
115
117
#[ derive( PartialEq , Debug , Copy , Clone ) ]
@@ -374,7 +376,7 @@ where
374
376
}
375
377
376
378
macro_rules! db_transfer_def {
377
- ( $Marker: ident, $init: ident, $Buffer: tt, $rw_buffer: ident $( , $mut: tt) * ;
379
+ ( $( [ $prepend : ident ] , ) ?$ Marker: ident, $init: ident, $Buffer: tt, $rw_buffer: ident $( , $mut: tt) * ;
378
380
$( $constraint: stmt) * ) => {
379
381
impl <STREAM , CONFIG , PERIPHERAL , DIR , BUF >
380
382
Transfer <STREAM , PERIPHERAL , DIR , BUF , $Marker>
@@ -415,7 +417,40 @@ macro_rules! db_transfer_def {
415
417
/// * When double buffering is enabled but the `double_buf` argument is
416
418
/// `None`.
417
419
/// * When the transfer length is greater than (2^16 - 1)
418
- pub fn $init(
420
+ ///
421
+ /// # Safety
422
+ ///
423
+ /// * If using an unsafe variant of this function (i.e., [Transfer::init_unsafe]),
424
+ /// the buffer must live as long as the
425
+ /// hardware DMA transfer. A case where this **wouldn't be true** is demonstrated below:
426
+ /// ```
427
+ /// use stm32h7xx_hal::dma::{PeripheralToMemory, Transfer};
428
+ ///
429
+ /// let spi = spi.disable();
430
+ /// let mut short_buffer = [0u8; 1024];
431
+ /// let streams = StreamsTuple::new(dp.DMA1, ccdr.peripheral.DMA1);
432
+ /// let config = DmaConfig::default().memory_increment(true);
433
+ /// let mut transfer: Transfer<_, _, PeripheralToMemory, _, _> = unsafe {
434
+ /// Transfer::init_unsafe(streams.0, spi, &mut short_buffer[..], None, config)
435
+ /// };
436
+ ///
437
+ /// transfer.start(|spi| {
438
+ /// spi.enable_dma_tx();
439
+ /// spi.inner_mut()
440
+ /// .cr1
441
+ /// .write(|w| w.ssi().slave_not_selected().spe().enabled());
442
+ /// spi.inner_mut().cr1.modify(|_, w| w.cstart().started());
443
+ /// });
444
+ ///
445
+ /// mem::forget(transfer); // <<<<<<<<
446
+ ///
447
+ /// loop {
448
+ /// // &ref to buffer while DMA transfer is still writing to buffer
449
+ /// info!("short_buffer = {:?}", short_buffer);
450
+ /// }
451
+ /// ```
452
+ #[ allow( unused_unsafe) ]
453
+ pub $( $prepend) ? fn $init(
419
454
mut stream: STREAM ,
420
455
peripheral: PERIPHERAL ,
421
456
$( $mut) * memory: BUF ,
@@ -743,8 +778,46 @@ macro_rules! db_transfer_def {
743
778
} ;
744
779
}
745
780
746
- db_transfer_def ! ( DBTransfer , init, WriteBuffer , write_buffer, mut ; ) ;
747
- db_transfer_def ! ( ConstDBTransfer , init_const, ReadBuffer , read_buffer;
781
+ impl < STREAM , CONFIG , PERIPHERAL , DIR , BUF >
782
+ Transfer < STREAM , PERIPHERAL , DIR , BUF , DBTransfer >
783
+ where
784
+ STREAM : DoubleBufferedStream + Stream < Config = CONFIG > ,
785
+ CONFIG : DoubleBufferedConfig ,
786
+ DIR : Direction ,
787
+ PERIPHERAL : TargetAddress < DIR > ,
788
+ BUF : StaticWriteBuffer < Word = <PERIPHERAL as TargetAddress < DIR > >:: MemSize > ,
789
+ BUF : WriteBuffer < Word = <PERIPHERAL as TargetAddress < DIR > >:: MemSize > ,
790
+ {
791
+
792
+ /// Configures the DMA source and destination and applies supplied
793
+ /// configuration. In a memory to memory transfer, the `double_buf` argument
794
+ /// is the source of the data. If double buffering is enabled, the number of
795
+ /// transfers will be the minimum length of `memory` and `double_buf`.
796
+ ///
797
+ /// # Panics
798
+ ///
799
+ /// * When the FIFO is disabled or double buffering is enabled in
800
+ /// `DmaConfig` while initializing a memory to memory transfer.
801
+ /// * When double buffering is enabled but the `double_buf` argument is
802
+ /// `None`.
803
+ /// * When the transfer length is greater than (2^16 - 1)
804
+ pub fn init (
805
+ stream : STREAM ,
806
+ peripheral : PERIPHERAL ,
807
+ memory : BUF ,
808
+ double_buf : Option < BUF > ,
809
+ config : CONFIG ,
810
+ ) -> Self {
811
+ unsafe {
812
+ Transfer :: init_unsafe (
813
+ stream, peripheral, memory, double_buf, config,
814
+ )
815
+ }
816
+ }
817
+ }
818
+
819
+ db_transfer_def ! ( [ unsafe ] , DBTransfer , init_unsafe, WriteBuffer , write_buffer, mut ; ) ;
820
+ db_transfer_def ! ( ConstDBTransfer , init_const, StaticReadBuffer , read_buffer;
748
821
assert!( DIR :: direction( ) != DmaDirection :: PeripheralToMemory ) ) ;
749
822
750
823
impl < STREAM , CONFIG , PERIPHERAL , DIR , BUF , TXFRT >
0 commit comments