embassy_stm32/dma/
mod.rs

1//! Direct Memory Access (DMA)
2#![macro_use]
3
4#[cfg(any(bdma, dma))]
5mod dma_bdma;
6#[cfg(any(bdma, dma))]
7pub use dma_bdma::*;
8
9#[cfg(gpdma)]
10pub(crate) mod gpdma;
11#[cfg(gpdma)]
12pub use gpdma::*;
13
14#[cfg(dmamux)]
15mod dmamux;
16#[cfg(dmamux)]
17pub(crate) use dmamux::*;
18
19mod util;
20pub(crate) use util::*;
21
22pub(crate) mod ringbuffer;
23pub mod word;
24
25use embassy_hal_internal::{impl_peripheral, PeripheralType};
26
27use crate::interrupt;
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq)]
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31enum Dir {
32    MemoryToPeripheral,
33    PeripheralToMemory,
34}
35
36/// DMA request type alias. (also known as DMA channel number in some chips)
37#[cfg(any(dma_v2, bdma_v2, gpdma, dmamux))]
38pub type Request = u8;
39/// DMA request type alias. (also known as DMA channel number in some chips)
40#[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))]
41pub type Request = ();
42
43pub(crate) trait SealedChannel {
44    fn id(&self) -> u8;
45}
46
47pub(crate) trait ChannelInterrupt {
48    #[cfg_attr(not(feature = "rt"), allow(unused))]
49    unsafe fn on_irq();
50}
51
52/// DMA channel.
53#[allow(private_bounds)]
54pub trait Channel: SealedChannel + PeripheralType + Into<AnyChannel> + 'static {}
55
56macro_rules! dma_channel_impl {
57    ($channel_peri:ident, $index:expr) => {
58        impl crate::dma::SealedChannel for crate::peripherals::$channel_peri {
59            fn id(&self) -> u8 {
60                $index
61            }
62        }
63        impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri {
64            unsafe fn on_irq() {
65                crate::dma::AnyChannel { id: $index }.on_irq();
66            }
67        }
68
69        impl crate::dma::Channel for crate::peripherals::$channel_peri {}
70
71        impl From<crate::peripherals::$channel_peri> for crate::dma::AnyChannel {
72            fn from(val: crate::peripherals::$channel_peri) -> Self {
73                Self {
74                    id: crate::dma::SealedChannel::id(&val),
75                }
76            }
77        }
78    };
79}
80
81/// Type-erased DMA channel.
82pub struct AnyChannel {
83    pub(crate) id: u8,
84}
85impl_peripheral!(AnyChannel);
86
87impl AnyChannel {
88    fn info(&self) -> &ChannelInfo {
89        &crate::_generated::DMA_CHANNELS[self.id as usize]
90    }
91}
92
93impl SealedChannel for AnyChannel {
94    fn id(&self) -> u8 {
95        self.id
96    }
97}
98impl Channel for AnyChannel {}
99
100const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len();
101static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT];
102
103// safety: must be called only once at startup
104pub(crate) unsafe fn init(
105    cs: critical_section::CriticalSection,
106    #[cfg(bdma)] bdma_priority: interrupt::Priority,
107    #[cfg(dma)] dma_priority: interrupt::Priority,
108    #[cfg(gpdma)] gpdma_priority: interrupt::Priority,
109) {
110    #[cfg(any(dma, bdma))]
111    dma_bdma::init(
112        cs,
113        #[cfg(dma)]
114        dma_priority,
115        #[cfg(bdma)]
116        bdma_priority,
117    );
118    #[cfg(gpdma)]
119    gpdma::init(cs, gpdma_priority);
120    #[cfg(dmamux)]
121    dmamux::init(cs);
122}