stm32f4xx_hal/dma/
mod.rs

1//! Direct Memory Access.
2//!
3//! [Transfer::init](struct.Transfer.html#method.init) is only implemented for valid combinations of
4//! peripheral-stream-channel-direction, providing compile time checking.
5//!
6//! This module implements Memory To Memory, Peripheral To Memory and Memory to Peripheral
7//! transfers, double buffering is supported only for Peripheral To Memory and Memory to Peripheral
8//! transfers.
9
10use core::{
11    fmt::{self, Debug, Formatter},
12    marker::PhantomData,
13    mem,
14    ops::Not,
15    ptr,
16    sync::atomic::{compiler_fence, Ordering},
17};
18use embedded_dma::{ReadBuffer, WriteBuffer};
19use enumflags2::BitFlags;
20
21use crate::pac::RCC;
22use crate::{pac, rcc};
23
24pub mod traits;
25use crate::serial::RxISR;
26use traits::{
27    sealed::Bits, Channel, DMASet, Direction, DmaEventExt, DmaFlagExt, Instance, PeriAddress,
28    SafePeripheralRead, Stream, StreamISR,
29};
30
31/// Errors.
32#[derive(PartialEq, Eq)]
33pub enum DMAError<T> {
34    /// DMA not ready to change buffers.
35    NotReady(T),
36    /// The user provided a buffer that is not big enough while double buffering.
37    SmallBuffer(T),
38    /// Overrun during a double buffering or circular transfer.
39    Overrun(T),
40}
41
42// Manually implement `Debug`, so we can have debug information even with a buffer `T` that doesn't
43// implement `Debug`. `T` is always a buffer type chosen by the user, because of that the debug
44// information can be helpful even without knowing the inner type
45impl<T> Debug for DMAError<T> {
46    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
47        match self {
48            DMAError::NotReady(_) => f.debug_tuple("NotReady").finish(),
49            DMAError::SmallBuffer(_) => f.debug_tuple("SmallBuffer").finish(),
50            DMAError::Overrun(_) => f.debug_tuple("Overrun").finish(),
51        }
52    }
53}
54
55// most of STM32F4 have 8 DmaChannel
56#[cfg(not(feature = "gpio-f413"))]
57/// Possible Channel of a DMA Stream.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum DmaChannel {
60    Channel0 = 0,
61    Channel1 = 1,
62    Channel2 = 2,
63    Channel3 = 3,
64    Channel4 = 4,
65    Channel5 = 5,
66    Channel6 = 6,
67    Channel7 = 7,
68}
69
70//  STM32F413 and STM32F423 have 16 DmaChannel
71#[cfg(feature = "gpio-f413")]
72/// Possible Channel of a DMA Stream.
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum DmaChannel {
75    Channel0 = 0,
76    Channel1 = 1,
77    Channel2 = 2,
78    Channel3 = 3,
79    Channel4 = 4,
80    Channel5 = 5,
81    Channel6 = 6,
82    Channel7 = 7,
83    Channel8 = 8,
84    Channel9 = 9,
85    Channel10 = 10,
86    Channel11 = 11,
87    Channel12 = 12,
88    Channel13 = 13,
89    Channel14 = 14,
90    Channel15 = 15,
91}
92
93impl Bits<u8> for DmaChannel {
94    fn bits(self) -> u8 {
95        self as u8
96    }
97}
98
99/// Peripheral increment offset size (pincos)
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum PeripheralIncrementOffset {
102    /// The offset size is linked to the peripheral data size (psize)
103    PeripheralDataSize = 0,
104    /// The offset size is fixed to 4 (32 bits alignement)
105    FixedSize = 1,
106}
107
108impl Bits<bool> for PeripheralIncrementOffset {
109    fn bits(self) -> bool {
110        match self {
111            PeripheralIncrementOffset::PeripheralDataSize => false,
112            PeripheralIncrementOffset::FixedSize => true,
113        }
114    }
115}
116
117/// Size of data transfered during a dma stream request
118#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub enum DmaDataSize {
120    Byte = 0,
121    HalfWord = 1,
122    Word = 2,
123}
124
125impl Bits<u8> for DmaDataSize {
126    fn bits(self) -> u8 {
127        self as u8
128    }
129}
130
131/// Possible DMA's directions.
132#[derive(Debug, Clone, Copy, PartialEq, Eq)]
133pub enum DmaDirection {
134    /// Memory to Memory transfer.
135    MemoryToMemory = 2,
136    /// Peripheral to Memory transfer.
137    PeripheralToMemory = 0,
138    /// Memory to Peripheral transfer.
139    MemoryToPeripheral = 1,
140}
141
142impl Bits<u8> for DmaDirection {
143    fn bits(self) -> u8 {
144        self as u8
145    }
146}
147
148/// Dma flow controller selection
149#[derive(Debug, Clone, Copy, PartialEq, Eq)]
150pub enum DmaFlowController {
151    Dma = 0,
152    Peripheral = 1,
153}
154
155impl Bits<bool> for DmaFlowController {
156    fn bits(self) -> bool {
157        match self {
158            DmaFlowController::Dma => false,
159            DmaFlowController::Peripheral => true,
160        }
161    }
162}
163
164/// DMA from a peripheral to a memory location.
165#[derive(Debug, Clone, Copy)]
166pub struct PeripheralToMemory;
167
168impl Bits<u8> for PeripheralToMemory {
169    #[inline(always)]
170    fn bits(self) -> u8 {
171        0
172    }
173}
174
175impl Direction for PeripheralToMemory {
176    fn new() -> Self {
177        PeripheralToMemory
178    }
179    #[inline(always)]
180    fn direction() -> DmaDirection {
181        DmaDirection::PeripheralToMemory
182    }
183}
184
185/// DMA from one memory location to another memory location.
186#[derive(Debug, Clone, Copy)]
187pub struct MemoryToMemory<T> {
188    _data: PhantomData<T>,
189}
190
191impl<T> Bits<u8> for MemoryToMemory<T> {
192    #[inline(always)]
193    fn bits(self) -> u8 {
194        2
195    }
196}
197
198impl<T> Direction for MemoryToMemory<T> {
199    fn new() -> Self {
200        Self { _data: PhantomData }
201    }
202    #[inline(always)]
203    fn direction() -> DmaDirection {
204        DmaDirection::MemoryToMemory
205    }
206}
207
208/// DMA from a memory location to a peripheral.
209#[derive(Debug, Clone, Copy)]
210pub struct MemoryToPeripheral;
211
212impl Bits<u8> for MemoryToPeripheral {
213    #[inline(always)]
214    fn bits(self) -> u8 {
215        1
216    }
217}
218
219impl Direction for MemoryToPeripheral {
220    fn new() -> Self {
221        MemoryToPeripheral
222    }
223    fn direction() -> DmaDirection {
224        DmaDirection::MemoryToPeripheral
225    }
226}
227
228unsafe impl PeriAddress for MemoryToMemory<u8> {
229    fn address(&self) -> u32 {
230        unimplemented!()
231    }
232    type MemSize = u8;
233}
234
235unsafe impl PeriAddress for MemoryToMemory<u16> {
236    fn address(&self) -> u32 {
237        unimplemented!()
238    }
239    type MemSize = u16;
240}
241
242unsafe impl PeriAddress for MemoryToMemory<u32> {
243    fn address(&self) -> u32 {
244        unimplemented!()
245    }
246    type MemSize = u32;
247}
248
249/// How full the DMA stream's fifo is.
250#[derive(Debug, Clone, Copy)]
251pub enum FifoLevel {
252    /// 0 < fifo_level < 1/4.
253    GtZeroLtQuarter,
254    /// 1/4 <= fifo_level < 1/2.
255    GteQuarterLtHalf,
256    /// 1/2 <= fifo_level < 3/4.
257    GteHalfLtThreeQuarter,
258    /// 3/4 <= fifo_level < full.
259    GteThreeQuarterLtFull,
260    /// Fifo is empty.
261    Empty,
262    /// Fifo is full.
263    Full,
264    /// Invalid value.
265    Invalid,
266}
267
268impl From<u8> for FifoLevel {
269    fn from(value: u8) -> Self {
270        match value {
271            0 => FifoLevel::GtZeroLtQuarter,
272            1 => FifoLevel::GteQuarterLtHalf,
273            2 => FifoLevel::GteHalfLtThreeQuarter,
274            3 => FifoLevel::GteThreeQuarterLtFull,
275            4 => FifoLevel::Empty,
276            5 => FifoLevel::Full,
277            _ => FifoLevel::Invalid,
278        }
279    }
280}
281
282/// Which DMA buffer is in use.
283#[derive(Debug, Clone, Copy, PartialEq, Eq)]
284pub enum CurrentBuffer {
285    /// The first buffer (m0ar) is in use.
286    FirstBuffer,
287    /// The second buffer (m1ar) is in use.
288    SecondBuffer,
289}
290
291impl Not for CurrentBuffer {
292    type Output = CurrentBuffer;
293
294    fn not(self) -> Self::Output {
295        if self == CurrentBuffer::FirstBuffer {
296            CurrentBuffer::SecondBuffer
297        } else {
298            CurrentBuffer::FirstBuffer
299        }
300    }
301}
302
303/// Structure to get or set common interrupts setup
304#[enumflags2::bitflags]
305#[repr(u32)]
306#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
307pub enum DmaEvent {
308    DirectModeError = 1 << 1,
309    TransferError = 1 << 2,
310    HalfTransfer = 1 << 3,
311    TransferComplete = 1 << 4,
312}
313
314impl DmaEventExt for BitFlags<DmaEvent> {
315    #[inline(always)]
316    fn is_listen_transfer_complete(&self) -> bool {
317        self.contains(DmaEvent::TransferComplete)
318    }
319    #[inline(always)]
320    fn is_listen_half_transfer(&self) -> bool {
321        self.contains(DmaEvent::HalfTransfer)
322    }
323    #[inline(always)]
324    fn is_listen_transfer_error(&self) -> bool {
325        self.contains(DmaEvent::TransferError)
326    }
327    #[inline(always)]
328    fn is_listen_direct_mode_error(&self) -> bool {
329        self.contains(DmaEvent::DirectModeError)
330    }
331}
332
333/// Structure returned by Stream or Transfer flags() method.
334#[enumflags2::bitflags]
335#[repr(u32)]
336#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
337pub enum DmaFlag {
338    FifoError = 1 << 0,
339    DirectModeError = 1 << 2,
340    TransferError = 1 << 3,
341    HalfTransfer = 1 << 4,
342    TransferComplete = 1 << 5,
343}
344
345impl DmaFlagExt for BitFlags<DmaFlag> {
346    #[inline(always)]
347    fn is_transfer_complete(&self) -> bool {
348        self.contains(DmaFlag::TransferComplete)
349    }
350
351    #[inline(always)]
352    fn is_half_transfer(&self) -> bool {
353        self.contains(DmaFlag::HalfTransfer)
354    }
355
356    #[inline(always)]
357    fn is_transfer_error(&self) -> bool {
358        self.contains(DmaFlag::TransferError)
359    }
360
361    #[inline(always)]
362    fn is_direct_mode_error(&self) -> bool {
363        self.contains(DmaFlag::DirectModeError)
364    }
365
366    #[inline(always)]
367    fn is_fifo_error(&self) -> bool {
368        self.contains(DmaFlag::FifoError)
369    }
370}
371
372/// Stream on the DMA controller.
373pub struct StreamX<DMA, const S: u8> {
374    _dma: PhantomData<DMA>,
375}
376
377impl<DMA, const S: u8> StreamX<DMA, S> {
378    fn new() -> Self {
379        Self { _dma: PhantomData }
380    }
381}
382
383impl<DMA: Instance, const S: u8> StreamX<DMA, S> {
384    #[cfg(not(any(feature = "gpio-f411", feature = "gpio-f413", feature = "gpio-f410")))]
385    #[inline(always)]
386    unsafe fn st() -> &'static pac::dma2::ST {
387        (*DMA::ptr()).st(S as usize)
388    }
389    #[cfg(any(feature = "gpio-f411", feature = "gpio-f413", feature = "gpio-f410"))]
390    #[inline(always)]
391    unsafe fn st() -> &'static pac::dma1::ST {
392        (*DMA::ptr()).st(S as usize)
393    }
394}
395
396/// Stream 0 on the DMA controller.
397pub type Stream0<DMA> = StreamX<DMA, 0>;
398/// Stream 1 on the DMA controller.
399pub type Stream1<DMA> = StreamX<DMA, 1>;
400/// Stream 2 on the DMA controller.
401pub type Stream2<DMA> = StreamX<DMA, 2>;
402/// Stream 3 on the DMA controller.
403pub type Stream3<DMA> = StreamX<DMA, 3>;
404/// Stream 4 on the DMA controller.
405pub type Stream4<DMA> = StreamX<DMA, 4>;
406/// Stream 5 on the DMA controller.
407pub type Stream5<DMA> = StreamX<DMA, 5>;
408/// Stream 6 on the DMA controller.
409pub type Stream6<DMA> = StreamX<DMA, 6>;
410/// Stream 7 on the DMA controller.
411pub type Stream7<DMA> = StreamX<DMA, 7>;
412
413impl<DMA> crate::Sealed for StreamX<DMA, 0> {}
414impl<DMA> crate::Sealed for StreamX<DMA, 1> {}
415impl<DMA> crate::Sealed for StreamX<DMA, 2> {}
416impl<DMA> crate::Sealed for StreamX<DMA, 3> {}
417impl<DMA> crate::Sealed for StreamX<DMA, 4> {}
418impl<DMA> crate::Sealed for StreamX<DMA, 5> {}
419impl<DMA> crate::Sealed for StreamX<DMA, 6> {}
420impl<DMA> crate::Sealed for StreamX<DMA, 7> {}
421
422/// Alias for a tuple with all DMA streams.
423pub struct StreamsTuple<DMA>(
424    pub StreamX<DMA, 0>,
425    pub StreamX<DMA, 1>,
426    pub StreamX<DMA, 2>,
427    pub StreamX<DMA, 3>,
428    pub StreamX<DMA, 4>,
429    pub StreamX<DMA, 5>,
430    pub StreamX<DMA, 6>,
431    pub StreamX<DMA, 7>,
432);
433
434impl<DMA: rcc::Enable + rcc::Reset> StreamsTuple<DMA> {
435    /// Splits the DMA peripheral into streams.
436    pub fn new(_regs: DMA, rcc: &mut RCC) -> Self {
437        DMA::enable(rcc);
438        DMA::reset(rcc);
439        Self(
440            StreamX::new(),
441            StreamX::new(),
442            StreamX::new(),
443            StreamX::new(),
444            StreamX::new(),
445            StreamX::new(),
446            StreamX::new(),
447            StreamX::new(),
448        )
449    }
450}
451
452impl<I: Instance, const S: u8> crate::Listen for StreamX<I, S>
453where
454    Self: crate::Sealed + StreamISR,
455{
456    type Event = DmaEvent;
457
458    #[inline(always)]
459    fn listen(&mut self, interrupts: impl Into<BitFlags<DmaEvent>>) {
460        self.listen_event(None, Some(interrupts.into()));
461    }
462
463    #[inline(always)]
464    fn listen_only(&mut self, interrupts: impl Into<BitFlags<DmaEvent>>) {
465        self.listen_event(Some(BitFlags::ALL), Some(interrupts.into()));
466    }
467
468    #[inline(always)]
469    fn unlisten(&mut self, interrupts: impl Into<BitFlags<DmaEvent>>) {
470        self.listen_event(Some(interrupts.into()), None);
471    }
472}
473
474impl<I: Instance, const S: u8> Stream for StreamX<I, S>
475where
476    Self: crate::Sealed + StreamISR,
477{
478    const NUMBER: usize = S as usize;
479
480    #[inline(always)]
481    fn set_peripheral_address(&mut self, value: u32) {
482        unsafe { Self::st() }
483            .par()
484            .write(|w| unsafe { w.pa().bits(value) });
485    }
486
487    #[inline(always)]
488    fn set_memory_address(&mut self, value: u32) {
489        unsafe { Self::st() }
490            .m0ar()
491            .write(|w| unsafe { w.m0a().bits(value) });
492    }
493
494    #[inline(always)]
495    fn memory_address(&self) -> u32 {
496        unsafe { Self::st() }.m0ar().read().m0a().bits()
497    }
498
499    #[inline(always)]
500    fn set_alternate_memory_address(&mut self, value: u32) {
501        unsafe { Self::st() }
502            .m1ar()
503            .write(|w| unsafe { w.m1a().bits(value) });
504    }
505
506    #[inline(always)]
507    fn alternate_memory_address(&self) -> u32 {
508        unsafe { Self::st() }.m1ar().read().m1a().bits()
509    }
510
511    #[inline(always)]
512    fn set_number_of_transfers(&mut self, value: u16) {
513        unsafe { Self::st() }.ndtr().write(|w| w.ndt().set(value));
514    }
515
516    #[inline(always)]
517    fn number_of_transfers(&self) -> u16 {
518        unsafe { Self::st() }.ndtr().read().ndt().bits()
519    }
520
521    #[inline(always)]
522    unsafe fn enable(&mut self) {
523        Self::st().cr().modify(|_, w| w.en().set_bit());
524    }
525
526    #[inline(always)]
527    fn is_enabled(&self) -> bool {
528        unsafe { Self::st() }.cr().read().en().bit_is_set()
529    }
530
531    #[inline(always)]
532    unsafe fn disable(&mut self) {
533        unsafe { Self::st() }.cr().modify(|_, w| w.en().clear_bit());
534    }
535
536    #[inline(always)]
537    fn set_channel(&mut self, channel: DmaChannel) {
538        unsafe { Self::st() }
539            .cr()
540            .modify(|_, w| w.chsel().set(channel.bits()));
541    }
542
543    #[inline(always)]
544    fn set_priority(&mut self, priority: config::Priority) {
545        unsafe { Self::st() }
546            .cr()
547            .modify(|_, w| w.pl().set(priority.bits()));
548    }
549
550    #[inline(always)]
551    fn set_peripheral_increment_offset(&mut self, value: PeripheralIncrementOffset) {
552        unsafe { Self::st() }
553            .cr()
554            .modify(|_, w| w.pincos().bit(value.bits()));
555    }
556
557    #[inline(always)]
558    unsafe fn set_memory_size(&mut self, size: DmaDataSize) {
559        Self::st().cr().modify(|_, w| w.msize().bits(size.bits()));
560    }
561
562    #[inline(always)]
563    unsafe fn set_peripheral_size(&mut self, size: DmaDataSize) {
564        Self::st().cr().modify(|_, w| w.psize().bits(size.bits()));
565    }
566
567    #[inline(always)]
568    fn set_memory_increment(&mut self, increment: bool) {
569        unsafe { Self::st() }
570            .cr()
571            .modify(|_, w| w.minc().bit(increment));
572    }
573
574    #[inline(always)]
575    fn set_peripheral_increment(&mut self, increment: bool) {
576        unsafe { Self::st() }
577            .cr()
578            .modify(|_, w| w.pinc().bit(increment));
579    }
580
581    #[inline(always)]
582    fn set_circular_mode(&mut self, value: bool) {
583        unsafe { Self::st() }
584            .cr()
585            .modify(|_, w| w.circ().bit(value));
586    }
587
588    #[inline(always)]
589    fn set_direction(&mut self, direction: DmaDirection) {
590        unsafe { Self::st() }
591            .cr()
592            .modify(|_, w| unsafe { w.dir().bits(direction.bits()) });
593    }
594
595    #[inline(always)]
596    fn set_flow_controller(&mut self, value: DmaFlowController) {
597        unsafe { Self::st() }
598            .cr()
599            .modify(|_, w| w.pfctrl().bit(value.bits()));
600    }
601
602    #[inline(always)]
603    fn events(&self) -> BitFlags<DmaEvent> {
604        BitFlags::from_bits_truncate(unsafe { Self::st() }.cr().read().bits())
605    }
606
607    #[inline(always)]
608    fn listen_fifo_error(&mut self) {
609        unsafe { Self::st() }
610            .fcr()
611            .modify(|_, w| w.feie().set_bit());
612    }
613
614    #[inline(always)]
615    fn unlisten_fifo_error(&mut self) {
616        unsafe { Self::st() }
617            .fcr()
618            .modify(|_, w| w.feie().clear_bit());
619    }
620
621    #[inline(always)]
622    fn set_double_buffer(&mut self, double_buffer: bool) {
623        unsafe { Self::st() }
624            .cr()
625            .modify(|_, w| w.dbm().bit(double_buffer));
626    }
627
628    #[inline(always)]
629    fn set_fifo_threshold(&mut self, fifo_threshold: config::FifoThreshold) {
630        unsafe { Self::st() }
631            .fcr()
632            .modify(|_, w| w.fth().set(fifo_threshold.bits()));
633    }
634
635    #[inline(always)]
636    fn set_fifo_enable(&mut self, fifo_enable: bool) {
637        //Register is actually direct mode disable rather than fifo enable
638        unsafe { Self::st() }
639            .fcr()
640            .modify(|_, w| w.dmdis().bit(fifo_enable));
641    }
642
643    #[inline(always)]
644    fn set_memory_burst(&mut self, memory_burst: config::BurstMode) {
645        unsafe { Self::st() }
646            .cr()
647            .modify(|_, w| w.mburst().set(memory_burst.bits()));
648    }
649
650    #[inline(always)]
651    fn set_peripheral_burst(&mut self, peripheral_burst: config::BurstMode) {
652        unsafe { Self::st() }
653            .cr()
654            .modify(|_, w| w.pburst().set(peripheral_burst.bits()));
655    }
656
657    #[inline(always)]
658    fn fifo_level(&self) -> FifoLevel {
659        unsafe { Self::st() }.fcr().read().fs().bits().into()
660    }
661
662    fn current_buffer(&self) -> CurrentBuffer {
663        if unsafe { Self::st() }.cr().read().ct().bit_is_set() {
664            CurrentBuffer::SecondBuffer
665        } else {
666            CurrentBuffer::FirstBuffer
667        }
668    }
669}
670
671impl<I: Instance, const S: u8> StreamX<I, S>
672where
673    Self: crate::Sealed + StreamISR,
674{
675    fn listen_event(
676        &mut self,
677        disable: Option<BitFlags<DmaEvent>>,
678        enable: Option<BitFlags<DmaEvent>>,
679    ) {
680        unsafe {
681            Self::st().cr().modify(|r, w| {
682                w.bits({
683                    let mut bits = r.bits();
684                    if let Some(d) = disable {
685                        bits &= !d.bits()
686                    }
687                    if let Some(e) = enable {
688                        bits |= e.bits();
689                    }
690                    bits
691                })
692            });
693        }
694    }
695}
696
697// Macro that creates a struct representing a stream on either DMA controller
698// The implementation does the heavy lifting of mapping to the right fields on the stream
699macro_rules! dma_stream {
700    ($(($number:literal, $isr_shift:literal, $ifcr:ident, $isr:ident)),+
701        $(,)*) => {
702        $(
703            impl<I: Instance> crate::ClearFlags for StreamX<I, $number> {
704                type Flag = DmaFlag;
705
706
707                #[inline(always)]
708                fn clear_flags(&mut self, flags: impl Into<BitFlags<DmaFlag>>) {
709                    let dma = unsafe { &*I::ptr() };
710                    dma.$ifcr().write(|w| unsafe { w.bits(flags.into().bits() << $isr_shift) });
711                }
712            }
713
714            impl<I: Instance> crate::ReadFlags for StreamX<I, $number> {
715                type Flag = DmaFlag;
716
717                #[inline(always)]
718                fn flags(&self) -> BitFlags<DmaFlag>
719                {
720                    //NOTE(unsafe) Atomic read with no side effects
721                    let dma = unsafe { &*I::ptr() };
722                    BitFlags::from_bits_truncate(
723                        ((dma.$isr().read().bits() >> $isr_shift))
724                    )
725                }
726            }
727
728            impl<I: Instance> StreamISR for StreamX<I, $number> { }
729        )+
730    };
731}
732
733dma_stream!(
734    (0, 0, lifcr, lisr),
735    (1, 6, lifcr, lisr),
736    (2, 16, lifcr, lisr),
737    (3, 22, lifcr, lisr),
738    (4, 0, hifcr, hisr),
739    (5, 6, hifcr, hisr),
740    (6, 16, hifcr, hisr),
741    (7, 22, hifcr, hisr),
742);
743
744/// A Channel that can be configured on a DMA stream.
745#[derive(Debug, Clone, Copy)]
746pub struct ChannelX<const C: u8>;
747
748macro_rules! dma_channel {
749    ($(($name:ident, $num:literal)),+ $(,)*) => {
750        $(
751            impl Channel for ChannelX<$num> {
752                const VALUE: DmaChannel = DmaChannel::$name ;
753            }
754            pub type $name = ChannelX<$num>;
755        )+
756    };
757}
758
759dma_channel!(
760    (Channel0, 0),
761    (Channel1, 1),
762    (Channel2, 2),
763    (Channel3, 3),
764    (Channel4, 4),
765    (Channel5, 5),
766    (Channel6, 6),
767    (Channel7, 7),
768);
769
770#[cfg(feature = "gpio-f413")]
771dma_channel!((Channel8, 8), (Channel9, 9),);
772
773/// Contains types related to DMA configuration.
774pub mod config {
775    use super::Bits;
776
777    /// Priority of the DMA stream, defaults to `Medium`. If two requests have the same software
778    /// priority level, the stream with the lower number takes priority over the stream with the
779    /// higher number. For example, Stream 2 takes priority over Stream 4.
780    #[derive(Debug, Clone, Copy)]
781    pub enum Priority {
782        /// Low priority.
783        Low,
784        /// Medium priority.
785        Medium,
786        /// High priority.
787        High,
788        /// Very high priority.
789        VeryHigh,
790    }
791
792    impl Bits<u8> for Priority {
793        fn bits(self) -> u8 {
794            match self {
795                Priority::Low => 0,
796                Priority::Medium => 1,
797                Priority::High => 2,
798                Priority::VeryHigh => 3,
799            }
800        }
801    }
802
803    /// The level to fill the fifo to before performing the transaction.
804    #[derive(Debug, Clone, Copy)]
805    pub enum FifoThreshold {
806        /// 1/4 full.
807        QuarterFull,
808        /// 1/2 full.
809        HalfFull,
810        /// 3/4 full.
811        ThreeQuarterFull,
812        /// Full.
813        Full,
814    }
815
816    impl Bits<u8> for FifoThreshold {
817        fn bits(self) -> u8 {
818            match self {
819                FifoThreshold::QuarterFull => 0,
820                FifoThreshold::HalfFull => 1,
821                FifoThreshold::ThreeQuarterFull => 2,
822                FifoThreshold::Full => 3,
823            }
824        }
825    }
826
827    /// How burst transfers are done, requires fifo enabled. Check datasheet for valid combinations.
828    #[derive(Debug, Clone, Copy)]
829    pub enum BurstMode {
830        /// Single transfer, no burst.
831        NoBurst,
832        /// Burst transfer of 4 beats.
833        Burst4,
834        /// Burst transfer of 8 beats.
835        Burst8,
836        /// Burst transfer of 16 beats.
837        Burst16,
838    }
839
840    impl Bits<u8> for BurstMode {
841        fn bits(self) -> u8 {
842            match self {
843                BurstMode::NoBurst => 0,
844                BurstMode::Burst4 => 1,
845                BurstMode::Burst8 => 2,
846                BurstMode::Burst16 => 3,
847            }
848        }
849    }
850
851    /// Contains the complete set of configuration for a DMA stream.
852    #[derive(Debug, Clone, Copy)]
853    pub struct DmaConfig {
854        pub(crate) priority: Priority,
855        pub(crate) memory_increment: bool,
856        pub(crate) peripheral_increment: bool,
857        pub(crate) transfer_complete_interrupt: bool,
858        pub(crate) half_transfer_interrupt: bool,
859        pub(crate) transfer_error_interrupt: bool,
860        pub(crate) direct_mode_error_interrupt: bool,
861        pub(crate) fifo_error_interrupt: bool,
862        pub(crate) double_buffer: bool,
863        pub(crate) fifo_threshold: FifoThreshold,
864        pub(crate) fifo_enable: bool,
865        pub(crate) memory_burst: BurstMode,
866        pub(crate) peripheral_burst: BurstMode,
867    }
868
869    impl Default for DmaConfig {
870        fn default() -> Self {
871            Self {
872                priority: Priority::Medium,
873                memory_increment: false,
874                peripheral_increment: false,
875                transfer_complete_interrupt: false,
876                half_transfer_interrupt: false,
877                transfer_error_interrupt: false,
878                direct_mode_error_interrupt: false,
879                fifo_error_interrupt: false,
880                double_buffer: false,
881                fifo_threshold: FifoThreshold::QuarterFull,
882                fifo_enable: false,
883                memory_burst: BurstMode::NoBurst,
884                peripheral_burst: BurstMode::NoBurst,
885            }
886        }
887    }
888
889    impl DmaConfig {
890        /// Set the priority.
891        #[inline(always)]
892        pub fn priority(mut self, priority: Priority) -> Self {
893            self.priority = priority;
894            self
895        }
896
897        /// Set the memory_increment.
898        #[inline(always)]
899        pub fn memory_increment(mut self, memory_increment: bool) -> Self {
900            self.memory_increment = memory_increment;
901            self
902        }
903        /// Set the peripheral_increment.
904        #[inline(always)]
905        pub fn peripheral_increment(mut self, peripheral_increment: bool) -> Self {
906            self.peripheral_increment = peripheral_increment;
907            self
908        }
909        /// Set the transfer_complete_interrupt.
910        #[inline(always)]
911        pub fn transfer_complete_interrupt(mut self, transfer_complete_interrupt: bool) -> Self {
912            self.transfer_complete_interrupt = transfer_complete_interrupt;
913            self
914        }
915        /// Set the half_transfer_interrupt.
916        #[inline(always)]
917        pub fn half_transfer_interrupt(mut self, half_transfer_interrupt: bool) -> Self {
918            self.half_transfer_interrupt = half_transfer_interrupt;
919            self
920        }
921        /// Set the transfer_error_interrupt.
922        #[inline(always)]
923        pub fn transfer_error_interrupt(mut self, transfer_error_interrupt: bool) -> Self {
924            self.transfer_error_interrupt = transfer_error_interrupt;
925            self
926        }
927        /// Set the direct_mode_error_interrupt.
928        #[inline(always)]
929        pub fn direct_mode_error_interrupt(mut self, direct_mode_error_interrupt: bool) -> Self {
930            self.direct_mode_error_interrupt = direct_mode_error_interrupt;
931            self
932        }
933        /// Set the fifo_error_interrupt.
934        #[inline(always)]
935        pub fn fifo_error_interrupt(mut self, fifo_error_interrupt: bool) -> Self {
936            self.fifo_error_interrupt = fifo_error_interrupt;
937            self
938        }
939        /// Set the double_buffer.
940        #[inline(always)]
941        pub fn double_buffer(mut self, double_buffer: bool) -> Self {
942            self.double_buffer = double_buffer;
943            self
944        }
945        /// Set the fifo_threshold.
946        #[inline(always)]
947        pub fn fifo_threshold(mut self, fifo_threshold: FifoThreshold) -> Self {
948            self.fifo_threshold = fifo_threshold;
949            self
950        }
951        /// Set the fifo_enable.
952        #[inline(always)]
953        pub fn fifo_enable(mut self, fifo_enable: bool) -> Self {
954            self.fifo_enable = fifo_enable;
955            self
956        }
957        /// Set the memory_burst.
958        #[inline(always)]
959        pub fn memory_burst(mut self, memory_burst: BurstMode) -> Self {
960            self.memory_burst = memory_burst;
961            self
962        }
963        /// Set the peripheral_burst.
964        #[inline(always)]
965        pub fn peripheral_burst(mut self, peripheral_burst: BurstMode) -> Self {
966            self.peripheral_burst = peripheral_burst;
967            self
968        }
969    }
970}
971
972/// DMA Transfer.
973pub struct Transfer<STREAM, const CHANNEL: u8, PERIPHERAL, DIRECTION, BUF>
974where
975    STREAM: Stream,
976    PERIPHERAL: PeriAddress,
977{
978    stream: STREAM,
979    peripheral: PERIPHERAL,
980    _direction: PhantomData<DIRECTION>,
981    buf: Option<BUF>,
982    double_buf: Option<BUF>,
983    // Used when double buffering
984    transfer_length: u16,
985}
986
987// utility function to disable gracefully the stream. It disable stream, wait until stream is
988// disabled and prevent during process
989fn stream_disable<T: Stream>(stream: &mut T) {
990    if stream.is_enabled() {
991        // Aborting an on-going transfer might cause interrupts to fire, disable
992        let interrupts = stream.events();
993        stream.unlisten(BitFlags::ALL);
994        unsafe { stream.disable() };
995        while stream.is_enabled() {}
996
997        stream.clear_all_flags();
998        stream.listen(interrupts);
999    }
1000}
1001
1002impl<STREAM, const CHANNEL: u8, PERIPHERAL, BUF>
1003    Transfer<STREAM, CHANNEL, PERIPHERAL, MemoryToPeripheral, BUF>
1004where
1005    STREAM: Stream,
1006    ChannelX<CHANNEL>: Channel,
1007    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, MemoryToPeripheral>,
1008    BUF: ReadBuffer<Word = <PERIPHERAL as PeriAddress>::MemSize>,
1009{
1010    /// Configures the DMA stream to the correct channel for the peripheral, configures source and
1011    /// destination and applies supplied configuration. If double buffering is enabled, the
1012    /// number of transfers will be the minimum length of `memory` and `double_buf`.
1013    ///
1014    /// # Panics
1015    ///
1016    /// * When double buffering is enabled but the `double_buf` argument is `None`.
1017    pub fn init_memory_to_peripheral(
1018        mut stream: STREAM,
1019        peripheral: PERIPHERAL,
1020        buf: BUF,
1021        double_buf: Option<BUF>,
1022        config: config::DmaConfig,
1023    ) -> Self {
1024        let first_buf = {
1025            // NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until the
1026            // end of the DMA transfer
1027            let (buf_ptr, buf_len) = unsafe { buf.read_buffer() };
1028            (buf_ptr as u32, buf_len as u16)
1029        };
1030
1031        let db = double_buf.as_ref().map(|db| {
1032            let (db_ptr, db_len) = unsafe { db.read_buffer() };
1033            (db_ptr as u32, db_len as u16)
1034        });
1035        let n_transfers = Self::init_common(&mut stream, &peripheral, config, first_buf, db);
1036
1037        Self {
1038            stream,
1039            peripheral,
1040            _direction: PhantomData,
1041            buf: Some(buf),
1042            double_buf,
1043            transfer_length: n_transfers,
1044        }
1045    }
1046
1047    /// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1048    /// immediately after a transfer complete event if using double buffering, otherwise you might
1049    /// lose data. Returns the old buffer together with its `CurrentBuffer`. If an error occurs,
1050    /// this method will return the new buffer with the error.
1051    ///
1052    /// This method will clear the transfer complete flag on entry, it will also clear it again if
1053    /// an overrun occurs during its execution. Moreover, if an overrun occurs, the stream will be
1054    /// disabled and the transfer error flag will be set. This method can be called before the end
1055    /// of an ongoing transfer only if not using double buffering, in that case, the current
1056    /// transfer will be canceled and a new one will be started. A `NotReady` error will be returned
1057    /// if this method is called before the end of a transfer while double buffering.
1058    pub fn next_transfer(&mut self, new_buf: BUF) -> Result<(BUF, CurrentBuffer), DMAError<BUF>> {
1059        let ptr_and_len = {
1060            // NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until the
1061            // end of the DMA transfer
1062            let (buf_ptr, buf_len) = unsafe { new_buf.read_buffer() };
1063            (buf_ptr as u32, buf_len as u16)
1064        };
1065        self.next_transfer_common(new_buf, ptr_and_len, self.double_buf.is_some())
1066    }
1067
1068    /// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1069    /// immediately after a transfer complete event if using double buffering, otherwise you might
1070    /// lose data. The closure must return `(BUF, T)` where `BUF` is the new buffer to be used. This
1071    /// method can be called before the end of an ongoing transfer only if not using double
1072    /// buffering, in that case, the current transfer will be canceled and a new one will be
1073    /// started. A `NotReady` error will be returned if this method is called before the end of a
1074    /// transfer while double buffering and the closure won't be executed.
1075    ///
1076    /// # Panics
1077    /// This method will panic when double buffering if one or both of the following conditions
1078    /// happen:
1079    ///
1080    /// * The new buffer's length is smaller than the one used in the `init` method.
1081    /// * The closure `f` takes too long to return and a buffer overrun occurs.
1082    ///
1083    /// # Safety
1084    ///
1085    /// Memory corruption might occur in the previous buffer, the one passed to the closure, if an
1086    /// overrun occurs in double buffering mode.
1087    pub unsafe fn next_transfer_with<F, T>(&mut self, f: F) -> Result<T, DMAError<()>>
1088    where
1089        F: FnOnce(BUF, CurrentBuffer) -> (BUF, T),
1090    {
1091        if self.double_buf.is_some() {
1092            if !self.stream.is_transfer_complete() {
1093                return Err(DMAError::NotReady(()));
1094            }
1095            self.stream.clear_transfer_complete();
1096
1097            let current_buffer = self.stream.current_buffer();
1098            // double buffering, unwrap can never fail
1099            let db = if current_buffer == CurrentBuffer::SecondBuffer {
1100                self.buf.take().unwrap()
1101            } else {
1102                self.double_buf.take().unwrap()
1103            };
1104            let r = f(db, !current_buffer);
1105            let new_buf = r.0;
1106            let ptr_and_len = {
1107                let (new_buf_ptr, new_buf_len) = new_buf.read_buffer();
1108                (new_buf_ptr as u32, new_buf_len as u16)
1109            };
1110            self.next_transfer_with_common(new_buf, ptr_and_len, true, current_buffer);
1111            return Ok(r.1);
1112        }
1113        stream_disable(&mut self.stream);
1114        self.stream.clear_transfer_complete();
1115
1116        // "No re-ordering of reads and writes across this point is allowed"
1117        compiler_fence(Ordering::SeqCst);
1118
1119        // Can never fail, we never let the Transfer without a buffer
1120        let old_buf = self.buf.take().unwrap();
1121        let r = f(old_buf, CurrentBuffer::FirstBuffer);
1122        let new_buf = r.0;
1123
1124        let ptr_and_len = {
1125            let (new_buf_ptr, new_buf_len) = new_buf.read_buffer();
1126            (new_buf_ptr as u32, new_buf_len as u16)
1127        };
1128        self.next_transfer_with_common(new_buf, ptr_and_len, false, CurrentBuffer::FirstBuffer);
1129        Ok(r.1)
1130    }
1131}
1132
1133impl<STREAM, const CHANNEL: u8, PERIPHERAL, BUF> RxISR
1134    for Transfer<STREAM, CHANNEL, PERIPHERAL, PeripheralToMemory, BUF>
1135where
1136    STREAM: Stream,
1137    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, PeripheralToMemory> + RxISR,
1138{
1139    /// Return true if the line idle status is set
1140    fn is_idle(&self) -> bool {
1141        self.peripheral.is_idle()
1142    }
1143
1144    /// Return true if the rx register is not empty (and can be read)
1145    fn is_rx_not_empty(&self) -> bool {
1146        self.peripheral.is_rx_not_empty()
1147    }
1148
1149    /// Clear idle line interrupt flag
1150    fn clear_idle_interrupt(&self) {
1151        self.peripheral.clear_idle_interrupt();
1152    }
1153}
1154
1155impl<STREAM, const CHANNEL: u8, PERIPHERAL, BUF>
1156    Transfer<STREAM, CHANNEL, PERIPHERAL, PeripheralToMemory, BUF>
1157where
1158    STREAM: Stream,
1159    ChannelX<CHANNEL>: Channel,
1160    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, PeripheralToMemory> + SafePeripheralRead,
1161    BUF: WriteBuffer<Word = <PERIPHERAL as PeriAddress>::MemSize>,
1162{
1163    /// Access the owned peripheral for reading
1164    pub fn peripheral(&self) -> &PERIPHERAL {
1165        &self.peripheral
1166    }
1167}
1168
1169impl<STREAM, const CHANNEL: u8, PERIPHERAL, BUF>
1170    Transfer<STREAM, CHANNEL, PERIPHERAL, PeripheralToMemory, BUF>
1171where
1172    STREAM: Stream,
1173    ChannelX<CHANNEL>: Channel,
1174    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, PeripheralToMemory>,
1175    BUF: WriteBuffer<Word = <PERIPHERAL as PeriAddress>::MemSize>,
1176{
1177    /// Configures the DMA stream to the correct channel for the peripheral, configures source and
1178    /// destination and applies supplied configuration. If double buffering is enabled, the
1179    /// number of transfers will be the minimum length of `memory` and `double_buf`.
1180    ///
1181    /// # Panics
1182    ///
1183    /// * When double buffering is enabled but the `double_buf` argument is `None`.
1184    pub fn init_peripheral_to_memory(
1185        mut stream: STREAM,
1186        peripheral: PERIPHERAL,
1187        mut buf: BUF,
1188        mut double_buf: Option<BUF>,
1189        config: config::DmaConfig,
1190    ) -> Self {
1191        let first_buf = {
1192            // NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until the
1193            // end of the DMA transfer
1194            let (buf_ptr, buf_len) = unsafe { buf.write_buffer() };
1195            (buf_ptr as u32, buf_len as u16)
1196        };
1197
1198        let db = double_buf.as_mut().map(|db| {
1199            let (db_ptr, db_len) = unsafe { db.write_buffer() };
1200            (db_ptr as u32, db_len as u16)
1201        });
1202        let n_transfers = Self::init_common(&mut stream, &peripheral, config, first_buf, db);
1203
1204        Self {
1205            stream,
1206            peripheral,
1207            _direction: PhantomData,
1208            buf: Some(buf),
1209            double_buf,
1210            transfer_length: n_transfers,
1211        }
1212    }
1213
1214    /// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1215    /// immediately after a transfer complete event if using double buffering, otherwise you might
1216    /// lose data. Returns the old buffer together with its `CurrentBuffer`. If an error occurs,
1217    /// this method will return the new buffer with the error.
1218    ///
1219    /// This method will clear the transfer complete flag on entry, it will also clear it again if
1220    /// an overrun occurs during its execution. Moreover, if an overrun occurs, the stream will be
1221    /// disabled and the transfer error flag will be set. This method can be called before the end
1222    /// of an ongoing transfer only if not using double buffering, in that case, the current
1223    /// transfer will be canceled and a new one will be started. A `NotReady` error will be returned
1224    /// if this method is called before the end of a transfer while double buffering.
1225    pub fn next_transfer(
1226        &mut self,
1227        mut new_buf: BUF,
1228    ) -> Result<(BUF, CurrentBuffer), DMAError<BUF>> {
1229        let ptr_and_len = {
1230            // NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until the
1231            // end of the DMA transfer
1232            let (buf_ptr, buf_len) = unsafe { new_buf.write_buffer() };
1233            (buf_ptr as u32, buf_len as u16)
1234        };
1235        self.next_transfer_common(new_buf, ptr_and_len, self.double_buf.is_some())
1236    }
1237
1238    /// Changes the buffer and restarts or continues a double buffer transfer. This must be called
1239    /// immediately after a transfer complete event if using double buffering, otherwise you might
1240    /// lose data. The closure must return `(BUF, T)` where `BUF` is the new buffer to be used. This
1241    /// method can be called before the end of an ongoing transfer only if not using double
1242    /// buffering, in that case, the current transfer will be canceled and a new one will be
1243    /// started. A `NotReady` error will be returned if this method is called before the end of a
1244    /// transfer while double buffering and the closure won't be executed.
1245    ///
1246    /// # Panics
1247    /// This method will panic when double buffering if one or both of the following conditions
1248    /// happen:
1249    ///
1250    /// * The new buffer's length is smaller than the one used in the `init` method.
1251    /// * The closure `f` takes too long to return and a buffer overrun occurs.
1252    ///
1253    /// # Safety
1254    ///
1255    /// Memory corruption might occur in the previous buffer, the one passed to the closure, if an
1256    /// overrun occurs in double buffering mode.
1257    pub unsafe fn next_transfer_with<F, T>(&mut self, f: F) -> Result<T, DMAError<()>>
1258    where
1259        F: FnOnce(BUF, CurrentBuffer) -> (BUF, T),
1260    {
1261        if self.double_buf.is_some() {
1262            if !self.stream.is_transfer_complete() {
1263                return Err(DMAError::NotReady(()));
1264            }
1265            self.stream.clear_transfer_complete();
1266
1267            let current_buffer = self.stream.current_buffer();
1268            // double buffering, unwrap can never fail
1269            let db = if current_buffer == CurrentBuffer::SecondBuffer {
1270                self.buf.take().unwrap()
1271            } else {
1272                self.double_buf.take().unwrap()
1273            };
1274            let r = f(db, !current_buffer);
1275            let mut new_buf = r.0;
1276            let ptr_and_len = {
1277                let (new_buf_ptr, new_buf_len) = new_buf.write_buffer();
1278                (new_buf_ptr as u32, new_buf_len as u16)
1279            };
1280            self.next_transfer_with_common(new_buf, ptr_and_len, true, current_buffer);
1281            return Ok(r.1);
1282        }
1283        stream_disable(&mut self.stream);
1284        self.stream.clear_transfer_complete();
1285
1286        // "No re-ordering of reads and writes across this point is allowed"
1287        compiler_fence(Ordering::SeqCst);
1288
1289        // Can never fail, we never let the Transfer without a buffer
1290        let old_buf = self.buf.take().unwrap();
1291        let r = f(old_buf, CurrentBuffer::FirstBuffer);
1292        let mut new_buf = r.0;
1293
1294        let ptr_and_len = {
1295            let (new_buf_ptr, new_buf_len) = new_buf.write_buffer();
1296            (new_buf_ptr as u32, new_buf_len as u16)
1297        };
1298        self.next_transfer_with_common(new_buf, ptr_and_len, false, CurrentBuffer::FirstBuffer);
1299        Ok(r.1)
1300    }
1301}
1302
1303impl<STREAM, const CHANNEL: u8, PERIPHERAL, BUF, S>
1304    Transfer<STREAM, CHANNEL, PERIPHERAL, MemoryToMemory<S>, BUF>
1305where
1306    STREAM: Stream,
1307    ChannelX<CHANNEL>: Channel,
1308    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, MemoryToMemory<S>>,
1309    MemoryToMemory<S>: PeriAddress,
1310    BUF: WriteBuffer<Word = <PERIPHERAL as PeriAddress>::MemSize>,
1311{
1312    /// Configures the DMA stream to the correct channel for the peripheral, configures source and
1313    /// destination and applies supplied configuration. In a memory to memory transfer,
1314    /// the `double_buf` argument is the source of the data. If double buffering is enabled, the
1315    /// number of transfers will be the minimum length of `memory` and `double_buf`.
1316    ///
1317    /// # Panics
1318    ///
1319    /// * When the FIFO is disabled or double buffering is enabled in `DmaConfig` while initializing
1320    ///   a memory to memory transfer.
1321    pub fn init_memory_to_memory(
1322        mut stream: STREAM,
1323        peripheral: PERIPHERAL,
1324        mut buf: BUF,
1325        mut double_buf: BUF,
1326        config: config::DmaConfig,
1327    ) -> Self {
1328        let first_buf = {
1329            // NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until the
1330            // end of the DMA transfer
1331            let (buf_ptr, buf_len) = unsafe { buf.write_buffer() };
1332            (buf_ptr as u32, buf_len as u16)
1333        };
1334
1335        let db = {
1336            let (db_ptr, db_len) = unsafe { double_buf.write_buffer() };
1337            (db_ptr as u32, db_len as u16)
1338        };
1339        let n_transfers = Self::init_common(&mut stream, &peripheral, config, first_buf, Some(db));
1340
1341        Self {
1342            stream,
1343            peripheral,
1344            _direction: PhantomData,
1345            buf: Some(buf),
1346            double_buf: Some(double_buf),
1347            transfer_length: n_transfers,
1348        }
1349    }
1350
1351    /// Changes the buffer and restarts.Returns the old buffer together with its `CurrentBuffer`. If
1352    /// an error occurs, this method will return the new buffer with the error.
1353    ///
1354    /// This method will clear the transfer complete flag on entry. This method can be called before
1355    /// the end of an ongoing transfer, in that case, the current transfer will be canceled and a
1356    /// new one will be started.
1357    pub fn next_transfer(
1358        &mut self,
1359        mut new_buf: BUF,
1360    ) -> Result<(BUF, CurrentBuffer), DMAError<BUF>> {
1361        let ptr_and_len = {
1362            // NOTE(unsafe) We now own this buffer and we won't call any &mut methods on it until the
1363            // end of the DMA transfer
1364            let (buf_ptr, buf_len) = unsafe { new_buf.write_buffer() };
1365            (buf_ptr as u32, buf_len as u16)
1366        };
1367        self.next_transfer_common(new_buf, ptr_and_len, false)
1368    }
1369
1370    /// Changes the buffer and restarts a transfer. This must be called
1371    /// The closure must return `(BUF, T)` where `BUF` is the new buffer to be used. This
1372    /// method can be called before the end of an ongoing transfer,
1373    /// in that case, the current transfer will be canceled and a new one will be
1374    /// started.
1375    pub fn next_transfer_with<F, T>(&mut self, f: F) -> T
1376    where
1377        F: FnOnce(BUF, CurrentBuffer) -> (BUF, T),
1378    {
1379        stream_disable(&mut self.stream);
1380        self.stream.clear_transfer_complete();
1381
1382        // "No re-ordering of reads and writes across this point is allowed"
1383        compiler_fence(Ordering::SeqCst);
1384
1385        // Can never fail, we never let the Transfer without a buffer
1386        let old_buf = self.buf.take().unwrap();
1387        let r = f(old_buf, CurrentBuffer::FirstBuffer);
1388        let mut new_buf = r.0;
1389
1390        let ptr_and_len = {
1391            let (new_buf_ptr, new_buf_len) = unsafe { new_buf.write_buffer() };
1392            (new_buf_ptr as u32, new_buf_len as u16)
1393        };
1394        // NOTE(unsafe) We aren't double buffering, so this is fine
1395        unsafe {
1396            self.next_transfer_with_common(new_buf, ptr_and_len, false, CurrentBuffer::FirstBuffer);
1397        }
1398        r.1
1399    }
1400}
1401
1402impl<STREAM, const CHANNEL: u8, PERIPHERAL, DIR, BUF>
1403    Transfer<STREAM, CHANNEL, PERIPHERAL, DIR, BUF>
1404where
1405    STREAM: Stream,
1406    ChannelX<CHANNEL>: Channel,
1407    DIR: Direction,
1408    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, DIR>,
1409{
1410    /// Starts the transfer, the closure will be executed right after enabling the stream.
1411    pub fn start<F>(&mut self, f: F)
1412    where
1413        F: FnOnce(&mut PERIPHERAL),
1414    {
1415        // "Preceding reads and writes cannot be moved past subsequent writes"
1416        compiler_fence(Ordering::Release);
1417
1418        unsafe {
1419            self.stream.enable();
1420        }
1421        f(&mut self.peripheral);
1422    }
1423
1424    /// Pauses the dma stream, the closure will be executed right before disabling the stream.
1425    pub fn pause<F>(&mut self, f: F)
1426    where
1427        F: FnOnce(&mut PERIPHERAL),
1428    {
1429        f(&mut self.peripheral);
1430        stream_disable(&mut self.stream)
1431    }
1432
1433    /// Stops the stream and returns the underlying resources.
1434    pub fn release(mut self) -> (STREAM, PERIPHERAL, BUF, Option<BUF>) {
1435        stream_disable(&mut self.stream);
1436        compiler_fence(Ordering::SeqCst);
1437        self.stream.clear_all_flags();
1438
1439        unsafe {
1440            let stream = ptr::read(&self.stream);
1441            let peripheral = ptr::read(&self.peripheral);
1442            let buf = ptr::read(&self.buf);
1443            let double_buf = ptr::read(&self.double_buf);
1444            mem::forget(self);
1445            (stream, peripheral, buf.unwrap(), double_buf)
1446        }
1447    }
1448
1449    /// Get the number of remaining transfers (ndt) of the underlying DMA stream.
1450    pub fn number_of_transfers(&self) -> u16 {
1451        self.stream.number_of_transfers()
1452    }
1453
1454    /// Get the underlying stream of the transfer.
1455    ///
1456    /// # Safety
1457    ///
1458    /// This implementation relies on several configurations points in order to be sound, this
1459    /// method can void that. The use of this method is completely discouraged, only use it if you
1460    /// know the internals of this API in its entirety.
1461    pub unsafe fn stream(&mut self) -> &mut STREAM {
1462        &mut self.stream
1463    }
1464
1465    /// Wait for the transfer to complete.
1466    #[inline(always)]
1467    pub fn wait(&self) {
1468        while !self.stream.is_transfer_complete() {}
1469    }
1470
1471    /// Applies all fields in DmaConfig.
1472    fn apply_config(stream: &mut STREAM, config: config::DmaConfig) {
1473        let msize = match mem::size_of::<<PERIPHERAL as PeriAddress>::MemSize>() {
1474            1 => DmaDataSize::Byte,
1475            2 => DmaDataSize::HalfWord,
1476            4 => DmaDataSize::Word,
1477            //this case can only happen on wrong implemention of PeriAddress::MemSize
1478            _ => DmaDataSize::Word,
1479        };
1480
1481        stream.clear_all_flags();
1482        stream.set_priority(config.priority);
1483        // NOTE(unsafe) These values are correct because of the invariants of PeriAddress
1484        unsafe {
1485            stream.set_memory_size(msize);
1486            stream.set_peripheral_size(msize);
1487        }
1488        stream.set_memory_increment(config.memory_increment);
1489        stream.set_peripheral_increment(config.peripheral_increment);
1490        let mut interrupts = BitFlags::default();
1491        if config.transfer_complete_interrupt {
1492            interrupts |= DmaEvent::TransferComplete;
1493        }
1494        if config.half_transfer_interrupt {
1495            interrupts |= DmaEvent::HalfTransfer;
1496        }
1497        if config.transfer_error_interrupt {
1498            interrupts |= DmaEvent::TransferError;
1499        }
1500        if config.direct_mode_error_interrupt {
1501            interrupts |= DmaEvent::DirectModeError;
1502        }
1503        stream.listen_only(interrupts);
1504        if config.fifo_error_interrupt {
1505            stream.listen_fifo_error();
1506        } else {
1507            stream.unlisten_fifo_error();
1508        }
1509        stream.set_double_buffer(config.double_buffer);
1510        stream.set_fifo_threshold(config.fifo_threshold);
1511        stream.set_fifo_enable(config.fifo_enable);
1512        stream.set_memory_burst(config.memory_burst);
1513        stream.set_peripheral_burst(config.peripheral_burst);
1514    }
1515
1516    fn init_common(
1517        stream: &mut STREAM,
1518        peripheral: &PERIPHERAL,
1519        config: config::DmaConfig,
1520        // pointer and len
1521        buf: (u32, u16),
1522        db: Option<(u32, u16)>,
1523    ) -> u16 {
1524        stream_disable(stream);
1525
1526        // Set the channel
1527        stream.set_channel(ChannelX::<CHANNEL>::VALUE);
1528
1529        // Set peripheral to memory mode
1530        stream.set_direction(DIR::direction());
1531        let (buf_ptr, buf_len) = buf;
1532
1533        // Set the memory address
1534        stream.set_memory_address(buf_ptr);
1535
1536        let is_mem2mem = DIR::direction() == DmaDirection::MemoryToMemory;
1537        if is_mem2mem {
1538            // Fifo must be enabled for memory to memory
1539            if !config.fifo_enable {
1540                panic!("Fifo disabled.");
1541            } else if config.double_buffer {
1542                panic!("Double buffering enabled.");
1543            }
1544        } else {
1545            // Set the peripheral address
1546            stream.set_peripheral_address(peripheral.address());
1547        }
1548
1549        let db_len = if let Some((db_ptr, db_len)) = db {
1550            if is_mem2mem {
1551                // Double buffer is the source in mem2mem mode
1552                stream.set_peripheral_address(db_ptr);
1553            } else {
1554                stream.set_alternate_memory_address(db_ptr);
1555            }
1556            Some(db_len)
1557        } else {
1558            // Double buffer mode must not be enabled if we haven't been given a second buffer
1559            if config.double_buffer {
1560                panic!("No second buffer.");
1561            }
1562            None
1563        };
1564
1565        let n_transfers = if let Some(db) = db_len {
1566            buf_len.min(db)
1567        } else {
1568            buf_len
1569        };
1570        stream.set_number_of_transfers(n_transfers);
1571
1572        Self::apply_config(stream, config);
1573        n_transfers
1574    }
1575
1576    #[allow(clippy::branches_sharing_code)]
1577    fn next_transfer_common(
1578        &mut self,
1579        new_buf: BUF,
1580        ptr_and_len: (u32, u16),
1581        double_buffering: bool,
1582    ) -> Result<(BUF, CurrentBuffer), DMAError<BUF>> {
1583        if double_buffering {
1584            if !self.stream.is_transfer_complete() {
1585                return Err(DMAError::NotReady(new_buf));
1586            }
1587            self.stream.clear_transfer_complete();
1588            let (new_buf_ptr, new_buf_len) = ptr_and_len;
1589
1590            // We can't change the transfer length while double buffering
1591            if new_buf_len < self.transfer_length {
1592                return Err(DMAError::SmallBuffer(new_buf));
1593            }
1594
1595            if self.stream.current_buffer() == CurrentBuffer::SecondBuffer {
1596                // "Preceding reads and writes cannot be moved past subsequent writes"
1597                compiler_fence(Ordering::Release);
1598                self.stream.set_memory_address(new_buf_ptr);
1599
1600                // Check if an overrun occurred, the buffer address won't be updated in that case
1601                if self.stream.memory_address() != new_buf_ptr {
1602                    self.stream.clear_transfer_complete();
1603                    return Err(DMAError::Overrun(new_buf));
1604                }
1605
1606                // "Subsequent reads and writes cannot be moved ahead of preceding reads"
1607                compiler_fence(Ordering::Acquire);
1608
1609                let old_buf = self.buf.replace(new_buf);
1610
1611                // We always have a buffer, so unwrap can't fail
1612                return Ok((old_buf.unwrap(), CurrentBuffer::FirstBuffer));
1613            } else {
1614                // "Preceding reads and writes cannot be moved past subsequent writes"
1615                compiler_fence(Ordering::Release);
1616                self.stream.set_alternate_memory_address(new_buf_ptr);
1617
1618                // Check if an overrun occurred, the buffer address won't be updated in that case
1619                if self.stream.alternate_memory_address() != new_buf_ptr {
1620                    self.stream.clear_transfer_complete();
1621                    return Err(DMAError::Overrun(new_buf));
1622                }
1623
1624                // "Subsequent reads and writes cannot be moved ahead of preceding reads"
1625                compiler_fence(Ordering::Acquire);
1626
1627                let old_buf = self.double_buf.replace(new_buf);
1628
1629                // double buffering, unwrap can never fail
1630                return Ok((old_buf.unwrap(), CurrentBuffer::SecondBuffer));
1631            }
1632        }
1633        stream_disable(&mut self.stream);
1634        self.stream.clear_transfer_complete();
1635
1636        // "No re-ordering of reads and writes across this point is allowed"
1637        compiler_fence(Ordering::SeqCst);
1638
1639        let (buf_ptr, buf_len) = ptr_and_len;
1640        self.stream.set_memory_address(buf_ptr);
1641        self.stream.set_number_of_transfers(buf_len);
1642        let old_buf = self.buf.replace(new_buf);
1643
1644        unsafe {
1645            self.stream.enable();
1646        }
1647
1648        Ok((old_buf.unwrap(), CurrentBuffer::FirstBuffer))
1649    }
1650
1651    /// # Safety
1652    ///
1653    /// Memory corruption might occur in the previous buffer, the one passed to the closure, if an
1654    /// overrun occurs in double buffering mode.
1655    #[allow(clippy::branches_sharing_code)]
1656    unsafe fn next_transfer_with_common(
1657        &mut self,
1658        new_buf: BUF,
1659        ptr_and_len: (u32, u16),
1660        double_buffering: bool,
1661        current_buffer: CurrentBuffer,
1662    ) {
1663        if double_buffering {
1664            let (new_buf_ptr, new_buf_len) = ptr_and_len;
1665
1666            // We can't change the transfer length while double buffering
1667            assert!(
1668                new_buf_len >= self.transfer_length,
1669                "Second Buffer not big enough"
1670            );
1671
1672            // We don't know how long the closure took to complete, we might have changed the
1673            // current buffer twice (or any even number of times) and got back to the same buffer
1674            // we had in the beginning of the method, check for that
1675            if self.stream.is_transfer_complete() {
1676                // If this is true, then RAM corruption might have occurred, there's nothing we
1677                // can do apart from panicking.
1678                // TODO: Is this the best solution ? The closure based approach seems necessary
1679                // if we want to support BBqueue.
1680                panic!("Overrun");
1681            }
1682
1683            if current_buffer == CurrentBuffer::SecondBuffer {
1684                // "Preceding reads and writes cannot be moved past subsequent writes"
1685                compiler_fence(Ordering::Release);
1686                self.stream.set_memory_address(new_buf_ptr);
1687
1688                // Check again if an overrun occurred, the buffer address won't be updated in that
1689                // case
1690                if self.stream.memory_address() != new_buf_ptr {
1691                    panic!("Overrun");
1692                }
1693
1694                // "Subsequent reads and writes cannot be moved ahead of preceding reads"
1695                compiler_fence(Ordering::Acquire);
1696
1697                self.buf.replace(new_buf);
1698            } else {
1699                // "Preceding reads and writes cannot be moved past subsequent writes"
1700                compiler_fence(Ordering::Release);
1701                self.stream.set_alternate_memory_address(new_buf_ptr);
1702
1703                if self.stream.alternate_memory_address() != new_buf_ptr {
1704                    panic!("Overrun");
1705                }
1706
1707                // "Subsequent reads and writes cannot be moved ahead of preceding reads"
1708                compiler_fence(Ordering::Acquire);
1709
1710                self.double_buf.replace(new_buf);
1711            }
1712            return;
1713        }
1714        let (buf_ptr, buf_len) = ptr_and_len;
1715        self.stream.set_memory_address(buf_ptr);
1716        self.stream.set_number_of_transfers(buf_len);
1717        self.buf.replace(new_buf);
1718
1719        self.stream.enable();
1720    }
1721}
1722
1723impl<STREAM, const CHANNEL: u8, PERIPHERAL, DIR, BUF> crate::Sealed
1724    for Transfer<STREAM, CHANNEL, PERIPHERAL, DIR, BUF>
1725where
1726    STREAM: Stream,
1727    PERIPHERAL: PeriAddress,
1728{
1729}
1730
1731impl<STREAM, const CHANNEL: u8, PERIPHERAL, DIR, BUF> crate::ClearFlags
1732    for Transfer<STREAM, CHANNEL, PERIPHERAL, DIR, BUF>
1733where
1734    STREAM: Stream,
1735    ChannelX<CHANNEL>: Channel,
1736    DIR: Direction,
1737    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, DIR>,
1738{
1739    type Flag = DmaFlag;
1740
1741    #[inline(always)]
1742    fn clear_flags(&mut self, flags: impl Into<BitFlags<DmaFlag>>) {
1743        self.stream.clear_flags(flags)
1744    }
1745}
1746
1747impl<STREAM, const CHANNEL: u8, PERIPHERAL, DIR, BUF> crate::ReadFlags
1748    for Transfer<STREAM, CHANNEL, PERIPHERAL, DIR, BUF>
1749where
1750    STREAM: Stream,
1751    ChannelX<CHANNEL>: Channel,
1752    DIR: Direction,
1753    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, DIR>,
1754{
1755    type Flag = DmaFlag;
1756
1757    #[inline(always)]
1758    fn flags(&self) -> BitFlags<DmaFlag> {
1759        self.stream.flags()
1760    }
1761}
1762
1763impl<STREAM, const CHANNEL: u8, PERIPHERAL, DIR, BUF> StreamISR
1764    for Transfer<STREAM, CHANNEL, PERIPHERAL, DIR, BUF>
1765where
1766    STREAM: Stream,
1767    ChannelX<CHANNEL>: Channel,
1768    DIR: Direction,
1769    PERIPHERAL: PeriAddress + DMASet<STREAM, CHANNEL, DIR>,
1770{
1771}
1772
1773impl<STREAM, const CHANNEL: u8, PERIPHERAL, DIR, BUF> Drop
1774    for Transfer<STREAM, CHANNEL, PERIPHERAL, DIR, BUF>
1775where
1776    STREAM: Stream,
1777    PERIPHERAL: PeriAddress,
1778{
1779    fn drop(&mut self) {
1780        stream_disable(&mut self.stream);
1781        compiler_fence(Ordering::SeqCst);
1782    }
1783}