1pub use crate::common::dma::*;
4pub type DmaPriority = pac::dma1::ch::cr::PL;
5
6use crate::{Steal, common::wrap_trait::*, pac, rcc::Rcc};
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 $(
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
78pub 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> Steal for Ch<DMA, C>
100where
101 DMA: RegisterBlock + Steal,
102{
103 unsafe fn steal(&self) -> Self {
104 unsafe {
105 Self {
106 dma: self.dma.steal(),
107 }
108 }
109 }
110}
111
112impl<DMA, const C: u8> DmaChannel for Ch<DMA, C>
113where
114 DMA: RegisterBlock,
115{
116 #[inline]
117 fn start(&mut self) {
118 self.dma.ifcr().write(|w| w.cgif(C).set_bit());
119 self.ch().cr().modify(|_, w| w.en().set_bit());
120 }
121
122 #[inline]
123 fn stop(&mut self) {
124 self.ch().cr().modify(|_, w| w.en().clear_bit());
125 self.dma.ifcr().write(|w| w.cgif(C).set_bit());
126 self.set_transfer_length(0);
127 }
128
129 #[inline]
130 fn set_peripheral_address<T: Sized>(
131 &mut self,
132 address: usize,
133 mem_to_periph: bool,
134 increase: bool,
135 circular: bool,
136 ) {
137 self.ch()
138 .par()
139 .write(|w| unsafe { w.pa().bits(address as u32) });
140 self.ch().cr().modify(|_, w| {
141 w.mem2mem()
142 .clear_bit()
143 .pinc()
144 .bit(increase)
145 .circ()
146 .bit(circular)
147 .dir()
148 .bit(mem_to_periph);
149
150 match core::mem::size_of::<T>() {
151 2 => {
152 w.msize().bits16();
153 w.psize().bits16()
154 }
155 4 => {
156 w.msize().bits32();
157 w.psize().bits32()
158 }
159 _ => {
160 w.msize().bits8();
161 w.psize().bits8()
162 }
163 }
164 });
165 }
166
167 #[inline(always)]
168 fn set_memory_address(&mut self, address: usize, increase: bool) {
169 self.ch()
170 .mar()
171 .write(|w| unsafe { w.ma().bits(address as u32) });
172 self.ch().cr().modify(|_, w| w.minc().bit(increase));
173 }
174
175 #[inline(always)]
176 fn set_transfer_length(&mut self, len: usize) {
177 self.ch()
178 .ndtr()
179 .write(|w| w.ndt().set(u16::try_from(len).unwrap()));
180 }
181
182 #[inline]
183 fn set_memory_to_memory<T: Sized>(&mut self, _src_addr: usize, _dst_addr: usize, _len: usize) {
184 todo!()
185 }
186
187 #[inline]
188 fn get_unprocessed_len(&self) -> usize {
189 self.ch().ndtr().read().bits() as usize
190 }
191
192 #[inline]
193 fn in_progress(&self) -> bool {
194 self.get_unprocessed_len() != 0 && self.dma.isr().read().tcif(C).bit_is_clear()
195 }
196
197 #[inline]
198 fn set_interrupt(&mut self, event: DmaEvent, enable: bool) {
199 match event {
200 DmaEvent::HalfTransfer => self.ch().cr().modify(|_, w| w.htie().bit(enable)),
201 DmaEvent::TransferComplete => self.ch().cr().modify(|_, w| w.tcie().bit(enable)),
202 };
203 }
204
205 #[inline]
206 fn is_interrupted(&mut self, event: DmaEvent) -> bool {
207 match event {
208 DmaEvent::TransferComplete => {
209 if self.dma.isr().read().tcif(C).bit_is_set() {
210 self.dma.ifcr().write(|w| w.ctcif(C).set_bit());
211 true
212 } else {
213 false
214 }
215 }
216 DmaEvent::HalfTransfer => {
217 if self.dma.isr().read().htif(C).bit_is_set() {
218 self.dma.ifcr().write(|w| w.chtif(C).set_bit());
219 true
220 } else {
221 false
222 }
223 }
224 }
225 }
226}
227
228pub trait DmaBindTx<U>: DmaChannel {}
229pub trait DmaBindRx<U>: DmaChannel {}
230
231impl DmaBindTx<pac::USART3> for dma1::C2 {}
236impl DmaBindRx<pac::USART3> for dma1::C3 {}
237impl DmaBindTx<pac::USART1> for dma1::C4 {}
238impl DmaBindRx<pac::USART1> for dma1::C5 {}
239impl DmaBindRx<pac::USART2> for dma1::C6 {}
240impl DmaBindTx<pac::USART2> for dma1::C7 {}
241impl DmaBindRx<pac::UART4> for dma2::C3 {}
242impl DmaBindTx<pac::UART4> for dma2::C5 {}
243
244impl DmaBindRx<pac::SPI1> for dma1::C2 {}
245impl DmaBindTx<pac::SPI1> for dma1::C3 {}
246impl DmaBindRx<pac::SPI2> for dma1::C4 {}
247impl DmaBindTx<pac::SPI2> for dma1::C5 {}
248impl DmaBindRx<pac::SPI3> for dma2::C1 {}
249impl DmaBindTx<pac::SPI3> for dma2::C2 {}
250
251impl DmaBindTx<pac::I2C2> for dma1::C4 {}
252impl DmaBindRx<pac::I2C2> for dma1::C5 {}
253impl DmaBindTx<pac::I2C1> for dma1::C6 {}
254impl DmaBindRx<pac::I2C1> for dma1::C7 {}