stm32f1_hal/
dma.rs

1//! # Direct Memory Access
2
3use crate::{common::wrap_trait::*, pac, rcc::Rcc, Steal};
4
5pub use crate::common::dma::*;
6pub type DmaPriority = pac::dma1::ch::cr::PL;
7
8pub trait DmaInit {
9    type Channels;
10
11    fn split(self, rcc: &mut Rcc) -> Self::Channels;
12}
13
14macro_rules! dma {
15    ($DMAX:ty: ($dmaX:ident, {
16        $($CX:ident: ($ch: literal),)+
17    }),) => {
18        pub mod $dmaX {
19            use super::*;
20
21            #[non_exhaustive]
22            #[allow(clippy::manual_non_exhaustive)]
23            pub struct Channels((), $(pub $CX),+);
24
25            $(
26                pub type $CX = super::Ch<$DMAX, $ch>;
27            )+
28
29            impl DmaInit for $DMAX {
30                type Channels = Channels;
31
32                fn split(self, rcc: &mut Rcc) -> Channels {
33                    rcc.enable(&self);
34
35                    // reset the DMA control registers (stops all on-going transfers)
36                    $(
37                        self.ch($ch).cr().reset();
38                    )+
39
40                    Channels((), $(Ch::<$DMAX, $ch>{ dma: unsafe { self.steal() }}),+)
41                }
42            }
43        }
44    }
45}
46
47dma! {
48    pac::DMA1: (dma1, {
49        C1: (0),
50        C2: (1),
51        C3: (2),
52        C4: (3),
53        C5: (4),
54        C6: (5),
55        C7: (6),
56    }),
57}
58
59dma! {
60    pac::DMA2: (dma2, {
61        C1: (0),
62        C2: (1),
63        C3: (2),
64        C4: (3),
65        C5: (4),
66    }),
67}
68
69wrap_trait_deref! {
70    (pac::DMA1, pac::DMA2,),
71    pub trait RegisterBlock {
72        fn isr(&self) -> &pac::dma1::ISR;
73        fn ifcr(&self) -> &pac::dma1::IFCR;
74        fn ch(&self, n: usize) -> &pac::dma1::CH;
75    }
76}
77
78// DMA Channel ----------------------------------------------------------------
79
80pub struct Ch<DMA, const C: u8> {
81    dma: DMA,
82}
83
84impl<DMA, const C: u8> Ch<DMA, C>
85where
86    DMA: RegisterBlock,
87{
88    #[inline]
89    pub fn set_priority(&mut self, priority: DmaPriority) {
90        self.ch().cr().modify(|_, w| w.pl().variant(priority));
91    }
92
93    #[inline(always)]
94    fn ch(&self) -> &pac::dma1::CH {
95        self.dma.ch(C as usize)
96    }
97}
98
99impl<DMA, const C: u8> DmaChannel for Ch<DMA, C>
100where
101    DMA: RegisterBlock,
102{
103    #[inline]
104    fn start(&mut self) {
105        self.dma.ifcr().write(|w| w.cgif(C).set_bit());
106        self.ch().cr().modify(|_, w| w.en().set_bit());
107    }
108
109    #[inline]
110    fn stop(&mut self) {
111        self.ch().cr().modify(|_, w| w.en().clear_bit());
112        self.dma.ifcr().write(|w| w.cgif(C).set_bit());
113        self.set_transfer_length(0);
114    }
115
116    #[inline]
117    fn set_peripheral_address<T: Sized>(
118        &mut self,
119        address: usize,
120        mem_to_periph: bool,
121        increase: bool,
122        circular: bool,
123    ) {
124        self.ch()
125            .par()
126            .write(|w| unsafe { w.pa().bits(address as u32) });
127        self.ch().cr().modify(|_, w| {
128            w.mem2mem()
129                .clear_bit()
130                .pinc()
131                .bit(increase)
132                .circ()
133                .bit(circular)
134                .dir()
135                .bit(mem_to_periph);
136
137            match core::mem::size_of::<T>() {
138                2 => {
139                    w.msize().bits16();
140                    w.psize().bits16()
141                }
142                4 => {
143                    w.msize().bits32();
144                    w.psize().bits32()
145                }
146                _ => {
147                    w.msize().bits8();
148                    w.psize().bits8()
149                }
150            }
151        });
152    }
153
154    #[inline(always)]
155    fn set_memory_address(&mut self, address: usize, increase: bool) {
156        self.ch()
157            .mar()
158            .write(|w| unsafe { w.ma().bits(address as u32) });
159        self.ch().cr().modify(|_, w| w.minc().bit(increase));
160    }
161
162    #[inline(always)]
163    fn set_transfer_length(&mut self, len: usize) {
164        self.ch()
165            .ndtr()
166            .write(|w| w.ndt().set(u16::try_from(len).unwrap()));
167    }
168
169    #[inline]
170    fn set_memory_to_memory<T: Sized>(&mut self, _src_addr: usize, _dst_addr: usize, _len: usize) {
171        todo!()
172    }
173
174    #[inline]
175    fn get_left_len(&self) -> usize {
176        self.ch().ndtr().read().bits() as usize
177    }
178
179    #[inline]
180    fn in_progress(&self) -> bool {
181        self.get_left_len() != 0 && self.dma.isr().read().tcif(C).bit_is_clear()
182    }
183
184    #[inline]
185    fn set_interrupt(&mut self, event: DmaEvent, enable: bool) {
186        match event {
187            DmaEvent::HalfTransfer => self.ch().cr().modify(|_, w| w.htie().bit(enable)),
188            DmaEvent::TransferComplete => self.ch().cr().modify(|_, w| w.tcie().bit(enable)),
189        };
190    }
191
192    #[inline]
193    fn is_interrupted(&mut self, event: DmaEvent) -> bool {
194        match event {
195            DmaEvent::TransferComplete => {
196                if self.dma.isr().read().tcif(C).bit_is_set() {
197                    self.dma.ifcr().write(|w| w.ctcif(C).set_bit());
198                    true
199                } else {
200                    false
201                }
202            }
203            DmaEvent::HalfTransfer => {
204                if self.dma.isr().read().htif(C).bit_is_set() {
205                    self.dma.ifcr().write(|w| w.chtif(C).set_bit());
206                    true
207                } else {
208                    false
209                }
210            }
211        }
212    }
213}
214
215pub trait DmaBindTx<U>: DmaChannel {}
216pub trait DmaBindRx<U>: DmaChannel {}
217
218// table
219// Do NOT manually modify the code.
220// It's generated by scripts/generate_dma_table.py from scripts/table/stm32f1_dma_table.csv
221
222impl DmaBindTx<pac::USART3> for dma1::C2 {}
223impl DmaBindRx<pac::USART3> for dma1::C3 {}
224impl DmaBindTx<pac::USART1> for dma1::C4 {}
225impl DmaBindRx<pac::USART1> for dma1::C5 {}
226impl DmaBindRx<pac::USART2> for dma1::C6 {}
227impl DmaBindTx<pac::USART2> for dma1::C7 {}
228impl DmaBindRx<pac::UART4> for dma2::C3 {}
229impl DmaBindTx<pac::UART4> for dma2::C5 {}
230
231impl DmaBindRx<pac::SPI1> for dma1::C2 {}
232impl DmaBindTx<pac::SPI1> for dma1::C3 {}
233impl DmaBindRx<pac::SPI2> for dma1::C4 {}
234impl DmaBindTx<pac::SPI2> for dma1::C5 {}
235impl DmaBindRx<pac::SPI3> for dma2::C1 {}
236impl DmaBindTx<pac::SPI3> for dma2::C2 {}
237
238impl DmaBindTx<pac::I2C2> for dma1::C4 {}
239impl DmaBindRx<pac::I2C2> for dma1::C5 {}
240impl DmaBindTx<pac::I2C1> for dma1::C6 {}
241impl DmaBindRx<pac::I2C1> for dma1::C7 {}