py32_hal/dma/
mod.rs

1//! Direct Memory Access (DMA)
2
3// The following code is modified from embassy-stm32
4// https://github.com/embassy-rs/embassy/tree/main/embassy-stm32
5// Special thanks to the Embassy Project and its contributors for their work!
6
7#![macro_use]
8
9mod dma;
10pub use dma::*;
11
12mod util;
13pub(crate) use util::*;
14
15pub(crate) mod ringbuffer;
16pub mod word;
17
18use embassy_hal_internal::{impl_peripheral, Peripheral};
19
20use crate::interrupt;
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24enum Dir {
25    MemoryToPeripheral,
26    PeripheralToMemory,
27}
28
29/// DMA request type alias. (also known as DMA channel number in some chips)
30pub type Request = u8;
31// pub type Request = ();
32
33pub(crate) trait SealedChannel {
34    fn id(&self) -> u8;
35}
36
37pub(crate) trait ChannelInterrupt {
38    #[cfg_attr(not(feature = "rt"), allow(unused))]
39    unsafe fn on_irq();
40}
41
42/// DMA channel.
43#[allow(private_bounds)]
44pub trait Channel: SealedChannel + Peripheral<P = Self> + Into<AnyChannel> + 'static {
45    /// Type-erase (degrade) this pin into an `AnyChannel`.
46    ///
47    /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which
48    /// are all different types, into the same type. It is useful for
49    /// creating arrays of channels, or avoiding generics.
50    #[inline]
51    fn degrade(self) -> AnyChannel {
52        AnyChannel { id: self.id() }
53    }
54}
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(x: crate::peripherals::$channel_peri) -> Self {
73                crate::dma::Channel::degrade(x)
74            }
75        }
76    };
77}
78
79/// Type-erased DMA channel.
80pub struct AnyChannel {
81    pub(crate) id: u8,
82}
83impl_peripheral!(AnyChannel);
84
85impl AnyChannel {
86    fn info(&self) -> &ChannelInfo {
87        &crate::_generated::DMA_CHANNELS[self.id as usize]
88    }
89}
90
91impl SealedChannel for AnyChannel {
92    fn id(&self) -> u8 {
93        self.id
94    }
95}
96impl Channel for AnyChannel {}
97
98const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len();
99static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT];
100
101/// "No DMA" placeholder.
102///
103/// You may pass this in place of a real DMA channel when creating a driver
104/// to indicate it should not use DMA.
105///
106/// This often causes async functionality to not be available on the instance,
107/// leaving only blocking functionality.
108pub struct NoDma;
109
110impl_peripheral!(NoDma);
111
112// safety: must be called only once at startup
113pub(crate) unsafe fn init(
114    cs: critical_section::CriticalSection,
115    dma_priority: interrupt::Priority,
116) {
117    dma::init(cs, dma_priority);
118}