1use crate::dmamux::DmaMuxIndex;
3use crate::rcc::Rcc;
4use crate::stm32::DMAMUX;
5
6pub trait DmaExt {
8 type Channels;
10
11 fn reset(self, rcc: &mut Rcc) -> Self;
13
14 fn split(self, rcc: &mut Rcc, dmamux: DMAMUX) -> Self::Channels;
16}
17
18pub enum Priority {
20 Low = 0b00,
22 Medium = 0b01,
24 High = 0b10,
26 VeryHigh = 0b11,
28}
29
30impl From<Priority> for u8 {
31 fn from(prio: Priority) -> Self {
32 match prio {
33 Priority::Low => 0b00,
34 Priority::Medium => 0b01,
35 Priority::High => 0b10,
36 Priority::VeryHigh => 0b11,
37 }
38 }
39}
40
41pub enum Direction {
43 FromMemory,
45 FromPeripheral,
47}
48
49impl From<Direction> for bool {
50 fn from(dir: Direction) -> Self {
51 match dir {
52 Direction::FromMemory => true,
53 Direction::FromPeripheral => false,
54 }
55 }
56}
57
58#[doc = "Peripheral size"]
59#[derive(Clone, Copy, Debug, Eq, PartialEq)]
60#[repr(u8)]
61pub enum WordSize {
62 #[doc = "0: 8-bit size"]
63 BITS8 = 0,
64 #[doc = "1: 16-bit size"]
65 BITS16 = 1,
66 #[doc = "2: 32-bit size"]
67 BITS32 = 2,
68}
69impl From<WordSize> for u8 {
70 #[inline(always)]
71 fn from(variant: WordSize) -> Self {
72 variant as _
73 }
74}
75
76pub enum Event {
78 HalfTransfer,
80 TransferComplete,
82 TransferError,
84 Any,
86}
87
88mod private {
89 use crate::stm32;
90
91 pub trait Channel {
93 fn ch(&self) -> &stm32::dma::CH;
95 }
96}
97
98pub trait Channel: private::Channel {
100 fn select_peripheral(&mut self, index: DmaMuxIndex);
102
103 fn event_occurred(&self, event: Event) -> bool;
105
106 fn clear_event(&mut self, event: Event);
114
115 fn reset(&mut self) {
118 self.ch().cr.reset();
119 self.ch().ndtr.reset();
120 self.ch().par.reset();
121 self.ch().mar.reset();
122 self.clear_event(Event::Any);
123 }
124
125 fn set_peripheral_address(&mut self, address: u32, inc: bool) {
134 assert!(!self.is_enabled());
135
136 self.ch().par.write(|w| unsafe { w.pa().bits(address) });
137 self.ch().cr.modify(|_, w| w.pinc().bit(inc));
138 }
139
140 fn set_memory_address(&mut self, address: u32, inc: bool) {
149 assert!(!self.is_enabled());
150
151 self.ch().mar.write(|w| unsafe { w.ma().bits(address) });
152 self.ch().cr.modify(|_, w| w.minc().bit(inc));
153 }
154
155 fn set_transfer_length(&mut self, len: u16) {
163 assert!(!self.is_enabled());
164
165 self.ch().ndtr.write(|w| unsafe { w.ndt().bits(len) });
166 }
167
168 fn set_word_size(&mut self, wsize: WordSize) {
170 self.ch().cr.modify(|_, w| unsafe {
171 w.psize().bits(wsize as u8);
172 w.msize().bits(wsize as u8)
173 });
174 }
175
176 fn set_priority_level(&mut self, priority: Priority) {
178 let pl = priority.into();
179 self.ch().cr.modify(|_, w| unsafe { w.pl().bits(pl) });
180 }
181
182 fn set_direction(&mut self, direction: Direction) {
184 let dir = direction.into();
185 self.ch().cr.modify(|_, w| w.dir().bit(dir));
186 }
187
188 fn set_circular_mode(&mut self, circular: bool) {
190 self.ch().cr.modify(|_, w| w.circ().bit(circular));
191 }
192
193 fn listen(&mut self, event: Event) {
195 use Event::*;
196 match event {
197 HalfTransfer => self.ch().cr.modify(|_, w| w.htie().set_bit()),
198 TransferComplete => self.ch().cr.modify(|_, w| w.tcie().set_bit()),
199 TransferError => self.ch().cr.modify(|_, w| w.teie().set_bit()),
200 Any => self.ch().cr.modify(|_, w| {
201 w.htie().set_bit();
202 w.tcie().set_bit();
203 w.teie().set_bit()
204 }),
205 }
206 }
207
208 fn unlisten(&mut self, event: Event) {
210 use Event::*;
211 match event {
212 HalfTransfer => self.ch().cr.modify(|_, w| w.htie().clear_bit()),
213 TransferComplete => self.ch().cr.modify(|_, w| w.tcie().clear_bit()),
214 TransferError => self.ch().cr.modify(|_, w| w.teie().clear_bit()),
215 Any => self.ch().cr.modify(|_, w| {
216 w.htie().clear_bit();
217 w.tcie().clear_bit();
218 w.teie().clear_bit()
219 }),
220 }
221 }
222
223 fn enable(&mut self) {
225 self.clear_event(Event::Any);
226 self.ch().cr.modify(|_, w| w.en().set_bit());
227 }
228
229 fn disable(&mut self) {
231 self.ch().cr.modify(|_, w| w.en().clear_bit());
232 }
233
234 fn is_enabled(&self) -> bool {
236 self.ch().cr.read().en().bit_is_set()
237 }
238}
239
240#[cfg(any(feature = "stm32g030", feature = "stm32g031", feature = "stm32g041"))]
242macro_rules! dma {
243 (
244 channels: {
245 $( $Ci:ident: (
246 $chi:ident,
247 $htifi:ident, $tcifi:ident, $teifi:ident, $gifi:ident,
248 $chtifi:ident, $ctcifi:ident, $cteifi:ident, $cgifi:ident,
249 $MuxCi: ident
250 ), )+
251 },
252 ) => {
253 use crate::dmamux;
254 use crate::rcc::{Enable, Reset};
255 use crate::stm32::{self, DMA};
256
257 use crate::dmamux::DmaMuxExt;
258
259 pub struct Channels {
261 $( pub $chi: $Ci, )+
262 }
263
264 impl Channels {
265 fn reset(&mut self) {
268 $( self.$chi.reset(); )+
269 }
270 }
271
272
273 $(
274 pub struct $Ci {
276 mux: dmamux::$MuxCi,
277 }
278
279 impl private::Channel for $Ci {
280 fn ch(&self) -> &stm32::dma::CH {
281 unsafe { &(*DMA::ptr()).$chi }
283 }
284 }
285
286 impl $Ci {
287 pub fn mux(&mut self) -> &mut dyn dmamux::DmaMuxChannel {
288 &mut self.mux
289 }
290 }
291
292 impl Channel for $Ci {
293
294 fn select_peripheral(&mut self, index: DmaMuxIndex) {
295 self.mux().select_peripheral(index);
296 }
297
298 fn event_occurred(&self, event: Event) -> bool {
299 use Event::*;
300
301 let flags = unsafe { (*DMA::ptr()).isr.read() };
303 match event {
304 HalfTransfer => flags.$htifi().bit_is_set(),
305 TransferComplete => flags.$tcifi().bit_is_set(),
306 TransferError => flags.$teifi().bit_is_set(),
307 Any => flags.$gifi().bit_is_set(),
308 }
309 }
310
311 fn clear_event(&mut self, event: Event) {
312 use Event::*;
313
314 unsafe {
316 let _ = &(*DMA::ptr()).ifcr.write(|w| match event {
317 HalfTransfer => w.$chtifi().set_bit(),
318 TransferComplete => w.$ctcifi().set_bit(),
319 TransferError => w.$cteifi().set_bit(),
320 Any => w.$cgifi().set_bit(),
321 });
322 }
323 }
324
325 }
326 )+
327 }
328}
329
330#[cfg(any(feature = "stm32g030", feature = "stm32g031", feature = "stm32g041"))]
345dma!(
346 channels: {
347 C1: (ch1, htif1, tcif1, teif1, gif1, chtif1, ctcif1, cteif1, cgif1, C0),
348 C2: (ch2, htif2, tcif2, teif2, gif2, chtif2, ctcif2, cteif2, cgif2, C1),
349 C3: (ch3, htif3, tcif3, teif3, gif3, chtif3, ctcif3, cteif3, cgif3, C2),
350 C4: (ch4, htif4, tcif4, teif4, gif4, chtif4, ctcif4, cteif4, cgif4, C3),
351 C5: (ch5, htif5, tcif5, teif5, gif5, chtif5, ctcif5, cteif5, cgif5, C4),
352 },
353);
354
355#[cfg(any(feature = "stm32g030", feature = "stm32g031", feature = "stm32g041"))]
356impl DmaExt for DMA {
357 type Channels = Channels;
358
359 fn reset(self, rcc: &mut Rcc) -> Self {
360 <DMA as Reset>::reset(rcc);
362 self
363 }
364
365 fn split(self, rcc: &mut Rcc, dmamux: DMAMUX) -> Self::Channels {
366 let muxchannels = dmamux.split();
367 DMA::enable(rcc);
369
370 let mut channels = Channels {
371 ch1: C1 {
372 mux: muxchannels.ch0,
373 },
374 ch2: C2 {
375 mux: muxchannels.ch1,
376 },
377 ch3: C3 {
378 mux: muxchannels.ch2,
379 },
380 ch4: C4 {
381 mux: muxchannels.ch3,
382 },
383 ch5: C5 {
384 mux: muxchannels.ch4,
385 },
386 #[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))]
387 ch6: C6 {
388 mux: muxchannels.ch5,
389 },
390 #[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))]
391 ch7: C7 {
392 mux: muxchannels.ch6,
393 },
394 };
395 channels.reset();
396 channels
397 }
398}
399
400pub trait Target {
402 fn dmamux(&self) -> crate::dmamux::DmaMuxIndex;
404
405 fn enable_dma(&mut self) {}
407 fn disable_dma(&mut self) {}
409}