stm32f4xx/
dma.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use core::fmt::Debug;
6
7use kernel::platform::chip::ClockInterface;
8use kernel::utilities::cells::{MapCell, OptionalCell};
9use kernel::utilities::leasable_buffer::SubSliceMut;
10use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
11use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite};
12use kernel::utilities::StaticRef;
13
14use crate::clocks::{phclk, Stm32f4Clocks};
15use crate::nvic;
16use crate::spi;
17use crate::usart;
18
19/// DMA controller
20#[repr(C)]
21pub struct DmaRegisters {
22    /// low interrupt status register
23    lisr: ReadOnly<u32, LISR::Register>,
24    /// high interrupt status register
25    hisr: ReadOnly<u32, HISR::Register>,
26    /// low interrupt flag clear register
27    lifcr: ReadWrite<u32, LIFCR::Register>,
28    /// high interrupt flag clear register
29    hifcr: ReadWrite<u32, HIFCR::Register>,
30    /// stream x configuration register
31    s0cr: ReadWrite<u32, S0CR::Register>,
32    /// stream x number of data register
33    s0ndtr: ReadWrite<u32>,
34    /// stream x peripheral address register
35    s0par: ReadWrite<u32>,
36    /// stream x memory 0 address register
37    s0m0ar: ReadWrite<u32>,
38    /// stream x memory 1 address register
39    s0m1ar: ReadWrite<u32>,
40    /// stream x FIFO control register
41    s0fcr: ReadWrite<u32, S0FCR::Register>,
42    /// stream x configuration register
43    s1cr: ReadWrite<u32, S1CR::Register>,
44    /// stream x number of data register
45    s1ndtr: ReadWrite<u32>,
46    /// stream x peripheral address register
47    s1par: ReadWrite<u32>,
48    /// stream x memory 0 address register
49    s1m0ar: ReadWrite<u32>,
50    /// stream x memory 1 address register
51    s1m1ar: ReadWrite<u32>,
52    /// stream x FIFO control register
53    s1fcr: ReadWrite<u32, S1FCR::Register>,
54    /// stream x configuration register
55    s2cr: ReadWrite<u32, S2CR::Register>,
56    /// stream x number of data register
57    s2ndtr: ReadWrite<u32>,
58    /// stream x peripheral address register
59    s2par: ReadWrite<u32>,
60    /// stream x memory 0 address register
61    s2m0ar: ReadWrite<u32>,
62    /// stream x memory 1 address register
63    s2m1ar: ReadWrite<u32>,
64    /// stream x FIFO control register
65    s2fcr: ReadWrite<u32, S2FCR::Register>,
66    /// stream x configuration register
67    s3cr: ReadWrite<u32, S3CR::Register>,
68    /// stream x number of data register
69    s3ndtr: ReadWrite<u32>,
70    /// stream x peripheral address register
71    s3par: ReadWrite<u32>,
72    /// stream x memory 0 address register
73    s3m0ar: ReadWrite<u32>,
74    /// stream x memory 1 address register
75    s3m1ar: ReadWrite<u32>,
76    /// stream x FIFO control register
77    s3fcr: ReadWrite<u32, S3FCR::Register>,
78    /// stream x configuration register
79    s4cr: ReadWrite<u32, S4CR::Register>,
80    /// stream x number of data register
81    s4ndtr: ReadWrite<u32>,
82    /// stream x peripheral address register
83    s4par: ReadWrite<u32>,
84    /// stream x memory 0 address register
85    s4m0ar: ReadWrite<u32>,
86    /// stream x memory 1 address register
87    s4m1ar: ReadWrite<u32>,
88    /// stream x FIFO control register
89    s4fcr: ReadWrite<u32, S4FCR::Register>,
90    /// stream x configuration register
91    s5cr: ReadWrite<u32, S5CR::Register>,
92    /// stream x number of data register
93    s5ndtr: ReadWrite<u32>,
94    /// stream x peripheral address register
95    s5par: ReadWrite<u32>,
96    /// stream x memory 0 address register
97    s5m0ar: ReadWrite<u32>,
98    /// stream x memory 1 address register
99    s5m1ar: ReadWrite<u32>,
100    /// stream x FIFO control register
101    s5fcr: ReadWrite<u32, S5FCR::Register>,
102    /// stream x configuration register
103    s6cr: ReadWrite<u32, S6CR::Register>,
104    /// stream x number of data register
105    s6ndtr: ReadWrite<u32>,
106    /// stream x peripheral address register
107    s6par: ReadWrite<u32>,
108    /// stream x memory 0 address register
109    s6m0ar: ReadWrite<u32>,
110    /// stream x memory 1 address register
111    s6m1ar: ReadWrite<u32>,
112    /// stream x FIFO control register
113    s6fcr: ReadWrite<u32, S6FCR::Register>,
114    /// stream x configuration register
115    s7cr: ReadWrite<u32, S7CR::Register>,
116    /// stream x number of data register
117    s7ndtr: ReadWrite<u32>,
118    /// stream x peripheral address register
119    s7par: ReadWrite<u32>,
120    /// stream x memory 0 address register
121    s7m0ar: ReadWrite<u32>,
122    /// stream x memory 1 address register
123    s7m1ar: ReadWrite<u32>,
124    /// stream x FIFO control register
125    s7fcr: ReadWrite<u32, S7FCR::Register>,
126}
127
128register_bitfields![u32,
129    LISR [
130        /// Stream x transfer complete interrupt flag (x = 3..0)
131        TCIF3 OFFSET(27) NUMBITS(1) [],
132        /// Stream x half transfer interrupt flag (x=3..0)
133        HTIF3 OFFSET(26) NUMBITS(1) [],
134        /// Stream x transfer error interrupt flag (x=3..0)
135        TEIF3 OFFSET(25) NUMBITS(1) [],
136        /// Stream x direct mode error interrupt flag (x=3..0)
137        DMEIF3 OFFSET(24) NUMBITS(1) [],
138        /// Stream x FIFO error interrupt flag (x=3..0)
139        FEIF3 OFFSET(22) NUMBITS(1) [],
140        /// Stream x transfer complete interrupt flag (x = 3..0)
141        TCIF2 OFFSET(21) NUMBITS(1) [],
142        /// Stream x half transfer interrupt flag (x=3..0)
143        HTIF2 OFFSET(20) NUMBITS(1) [],
144        /// Stream x transfer error interrupt flag (x=3..0)
145        TEIF2 OFFSET(19) NUMBITS(1) [],
146        /// Stream x direct mode error interrupt flag (x=3..0)
147        DMEIF2 OFFSET(18) NUMBITS(1) [],
148        /// Stream x FIFO error interrupt flag (x=3..0)
149        FEIF2 OFFSET(16) NUMBITS(1) [],
150        /// Stream x transfer complete interrupt flag (x = 3..0)
151        TCIF1 OFFSET(11) NUMBITS(1) [],
152        /// Stream x half transfer interrupt flag (x=3..0)
153        HTIF1 OFFSET(10) NUMBITS(1) [],
154        /// Stream x transfer error interrupt flag (x=3..0)
155        TEIF1 OFFSET(9) NUMBITS(1) [],
156        /// Stream x direct mode error interrupt flag (x=3..0)
157        DMEIF1 OFFSET(8) NUMBITS(1) [],
158        /// Stream x FIFO error interrupt flag (x=3..0)
159        FEIF1 OFFSET(6) NUMBITS(1) [],
160        /// Stream x transfer complete interrupt flag (x = 3..0)
161        TCIF0 OFFSET(5) NUMBITS(1) [],
162        /// Stream x half transfer interrupt flag (x=3..0)
163        HTIF0 OFFSET(4) NUMBITS(1) [],
164        /// Stream x transfer error interrupt flag (x=3..0)
165        TEIF0 OFFSET(3) NUMBITS(1) [],
166        /// Stream x direct mode error interrupt flag (x=3..0)
167        DMEIF0 OFFSET(2) NUMBITS(1) [],
168        /// Stream x FIFO error interrupt flag (x=3..0)
169        FEIF0 OFFSET(0) NUMBITS(1) []
170    ],
171    HISR [
172        /// Stream x transfer complete interrupt flag (x=7..4)
173        TCIF7 OFFSET(27) NUMBITS(1) [],
174        /// Stream x half transfer interrupt flag (x=7..4)
175        HTIF7 OFFSET(26) NUMBITS(1) [],
176        /// Stream x transfer error interrupt flag (x=7..4)
177        TEIF7 OFFSET(25) NUMBITS(1) [],
178        /// Stream x direct mode error interrupt flag (x=7..4)
179        DMEIF7 OFFSET(24) NUMBITS(1) [],
180        /// Stream x FIFO error interrupt flag (x=7..4)
181        FEIF7 OFFSET(22) NUMBITS(1) [],
182        /// Stream x transfer complete interrupt flag (x=7..4)
183        TCIF6 OFFSET(21) NUMBITS(1) [],
184        /// Stream x half transfer interrupt flag (x=7..4)
185        HTIF6 OFFSET(20) NUMBITS(1) [],
186        /// Stream x transfer error interrupt flag (x=7..4)
187        TEIF6 OFFSET(19) NUMBITS(1) [],
188        /// Stream x direct mode error interrupt flag (x=7..4)
189        DMEIF6 OFFSET(18) NUMBITS(1) [],
190        /// Stream x FIFO error interrupt flag (x=7..4)
191        FEIF6 OFFSET(16) NUMBITS(1) [],
192        /// Stream x transfer complete interrupt flag (x=7..4)
193        TCIF5 OFFSET(11) NUMBITS(1) [],
194        /// Stream x half transfer interrupt flag (x=7..4)
195        HTIF5 OFFSET(10) NUMBITS(1) [],
196        /// Stream x transfer error interrupt flag (x=7..4)
197        TEIF5 OFFSET(9) NUMBITS(1) [],
198        /// Stream x direct mode error interrupt flag (x=7..4)
199        DMEIF5 OFFSET(8) NUMBITS(1) [],
200        /// Stream x FIFO error interrupt flag (x=7..4)
201        FEIF5 OFFSET(6) NUMBITS(1) [],
202        /// Stream x transfer complete interrupt flag (x=7..4)
203        TCIF4 OFFSET(5) NUMBITS(1) [],
204        /// Stream x half transfer interrupt flag (x=7..4)
205        HTIF4 OFFSET(4) NUMBITS(1) [],
206        /// Stream x transfer error interrupt flag (x=7..4)
207        TEIF4 OFFSET(3) NUMBITS(1) [],
208        /// Stream x direct mode error interrupt flag (x=7..4)
209        DMEIF4 OFFSET(2) NUMBITS(1) [],
210        /// Stream x FIFO error interrupt flag (x=7..4)
211        FEIF4 OFFSET(0) NUMBITS(1) []
212    ],
213    LIFCR [
214        /// Stream x clear transfer complete interrupt flag (x = 3..0)
215        CTCIF3 OFFSET(27) NUMBITS(1) [],
216        /// Stream x clear half transfer interrupt flag (x = 3..0)
217        CHTIF3 OFFSET(26) NUMBITS(1) [],
218        /// Stream x clear transfer error interrupt flag (x = 3..0)
219        CTEIF3 OFFSET(25) NUMBITS(1) [],
220        /// Stream x clear direct mode error interrupt flag (x = 3..0)
221        CDMEIF3 OFFSET(24) NUMBITS(1) [],
222        /// Stream x clear FIFO error interrupt flag (x = 3..0)
223        CFEIF3 OFFSET(22) NUMBITS(1) [],
224        /// Stream x clear transfer complete interrupt flag (x = 3..0)
225        CTCIF2 OFFSET(21) NUMBITS(1) [],
226        /// Stream x clear half transfer interrupt flag (x = 3..0)
227        CHTIF2 OFFSET(20) NUMBITS(1) [],
228        /// Stream x clear transfer error interrupt flag (x = 3..0)
229        CTEIF2 OFFSET(19) NUMBITS(1) [],
230        /// Stream x clear direct mode error interrupt flag (x = 3..0)
231        CDMEIF2 OFFSET(18) NUMBITS(1) [],
232        /// Stream x clear FIFO error interrupt flag (x = 3..0)
233        CFEIF2 OFFSET(16) NUMBITS(1) [],
234        /// Stream x clear transfer complete interrupt flag (x = 3..0)
235        CTCIF1 OFFSET(11) NUMBITS(1) [],
236        /// Stream x clear half transfer interrupt flag (x = 3..0)
237        CHTIF1 OFFSET(10) NUMBITS(1) [],
238        /// Stream x clear transfer error interrupt flag (x = 3..0)
239        CTEIF1 OFFSET(9) NUMBITS(1) [],
240        /// Stream x clear direct mode error interrupt flag (x = 3..0)
241        CDMEIF1 OFFSET(8) NUMBITS(1) [],
242        /// Stream x clear FIFO error interrupt flag (x = 3..0)
243        CFEIF1 OFFSET(6) NUMBITS(1) [],
244        /// Stream x clear transfer complete interrupt flag (x = 3..0)
245        CTCIF0 OFFSET(5) NUMBITS(1) [],
246        /// Stream x clear half transfer interrupt flag (x = 3..0)
247        CHTIF0 OFFSET(4) NUMBITS(1) [],
248        /// Stream x clear transfer error interrupt flag (x = 3..0)
249        CTEIF0 OFFSET(3) NUMBITS(1) [],
250        /// Stream x clear direct mode error interrupt flag (x = 3..0)
251        CDMEIF0 OFFSET(2) NUMBITS(1) [],
252        /// Stream x clear FIFO error interrupt flag (x = 3..0)
253        CFEIF0 OFFSET(0) NUMBITS(1) []
254    ],
255    HIFCR [
256        /// Stream x clear transfer complete interrupt flag (x = 7..4)
257        CTCIF7 OFFSET(27) NUMBITS(1) [],
258        /// Stream x clear half transfer interrupt flag (x = 7..4)
259        CHTIF7 OFFSET(26) NUMBITS(1) [],
260        /// Stream x clear transfer error interrupt flag (x = 7..4)
261        CTEIF7 OFFSET(25) NUMBITS(1) [],
262        /// Stream x clear direct mode error interrupt flag (x = 7..4)
263        CDMEIF7 OFFSET(24) NUMBITS(1) [],
264        /// Stream x clear FIFO error interrupt flag (x = 7..4)
265        CFEIF7 OFFSET(22) NUMBITS(1) [],
266        /// Stream x clear transfer complete interrupt flag (x = 7..4)
267        CTCIF6 OFFSET(21) NUMBITS(1) [],
268        /// Stream x clear half transfer interrupt flag (x = 7..4)
269        CHTIF6 OFFSET(20) NUMBITS(1) [],
270        /// Stream x clear transfer error interrupt flag (x = 7..4)
271        CTEIF6 OFFSET(19) NUMBITS(1) [],
272        /// Stream x clear direct mode error interrupt flag (x = 7..4)
273        CDMEIF6 OFFSET(18) NUMBITS(1) [],
274        /// Stream x clear FIFO error interrupt flag (x = 7..4)
275        CFEIF6 OFFSET(16) NUMBITS(1) [],
276        /// Stream x clear transfer complete interrupt flag (x = 7..4)
277        CTCIF5 OFFSET(11) NUMBITS(1) [],
278        /// Stream x clear half transfer interrupt flag (x = 7..4)
279        CHTIF5 OFFSET(10) NUMBITS(1) [],
280        /// Stream x clear transfer error interrupt flag (x = 7..4)
281        CTEIF5 OFFSET(9) NUMBITS(1) [],
282        /// Stream x clear direct mode error interrupt flag (x = 7..4)
283        CDMEIF5 OFFSET(8) NUMBITS(1) [],
284        /// Stream x clear FIFO error interrupt flag (x = 7..4)
285        CFEIF5 OFFSET(6) NUMBITS(1) [],
286        /// Stream x clear transfer complete interrupt flag (x = 7..4)
287        CTCIF4 OFFSET(5) NUMBITS(1) [],
288        /// Stream x clear half transfer interrupt flag (x = 7..4)
289        CHTIF4 OFFSET(4) NUMBITS(1) [],
290        /// Stream x clear transfer error interrupt flag (x = 7..4)
291        CTEIF4 OFFSET(3) NUMBITS(1) [],
292        /// Stream x clear direct mode error interrupt flag (x = 7..4)
293        CDMEIF4 OFFSET(2) NUMBITS(1) [],
294        /// Stream x clear FIFO error interrupt flag (x = 7..4)
295        CFEIF4 OFFSET(0) NUMBITS(1) []
296    ],
297    S0CR [
298        /// Channel selection
299        CHSEL OFFSET(25) NUMBITS(3) [],
300        /// Memory burst transfer configuration
301        MBURST OFFSET(23) NUMBITS(2) [],
302        /// Peripheral burst transfer configuration
303        PBURST OFFSET(21) NUMBITS(2) [],
304        /// Current target (only in double buffer mode)
305        CT OFFSET(19) NUMBITS(1) [],
306        /// Double buffer mode
307        DBM OFFSET(18) NUMBITS(1) [],
308        /// Priority level
309        PL OFFSET(16) NUMBITS(2) [],
310        /// Peripheral increment offset size
311        PINCOS OFFSET(15) NUMBITS(1) [],
312        /// Memory data size
313        MSIZE OFFSET(13) NUMBITS(2) [],
314        /// Peripheral data size
315        PSIZE OFFSET(11) NUMBITS(2) [],
316        /// Memory increment mode
317        MINC OFFSET(10) NUMBITS(1) [],
318        /// Peripheral increment mode
319        PINC OFFSET(9) NUMBITS(1) [],
320        /// Circular mode
321        CIRC OFFSET(8) NUMBITS(1) [],
322        /// Data transfer direction
323        DIR OFFSET(6) NUMBITS(2) [],
324        /// Peripheral flow controller
325        PFCTRL OFFSET(5) NUMBITS(1) [],
326        /// Transfer complete interrupt enable
327        TCIE OFFSET(4) NUMBITS(1) [],
328        /// Half transfer interrupt enable
329        HTIE OFFSET(3) NUMBITS(1) [],
330        /// Transfer error interrupt enable
331        TEIE OFFSET(2) NUMBITS(1) [],
332        /// Direct mode error interrupt enable
333        DMEIE OFFSET(1) NUMBITS(1) [],
334        /// Stream enable / flag stream ready when read low
335        EN OFFSET(0) NUMBITS(1) []
336    ],
337    S0FCR [
338        /// FIFO error interrupt enable
339        FEIE OFFSET(7) NUMBITS(1) [],
340        /// FIFO status
341        FS OFFSET(3) NUMBITS(3) [],
342        /// Direct mode disable
343        DMDIS OFFSET(2) NUMBITS(1) [],
344        /// FIFO threshold selection
345        FTH OFFSET(0) NUMBITS(2) []
346    ],
347    S1CR [
348        /// Channel selection
349        CHSEL OFFSET(25) NUMBITS(3) [],
350        /// Memory burst transfer configuration
351        MBURST OFFSET(23) NUMBITS(2) [],
352        /// Peripheral burst transfer configuration
353        PBURST OFFSET(21) NUMBITS(2) [],
354        /// ACK
355        ACK OFFSET(20) NUMBITS(1) [],
356        /// Current target (only in double buffer mode)
357        CT OFFSET(19) NUMBITS(1) [],
358        /// Double buffer mode
359        DBM OFFSET(18) NUMBITS(1) [],
360        /// Priority level
361        PL OFFSET(16) NUMBITS(2) [],
362        /// Peripheral increment offset size
363        PINCOS OFFSET(15) NUMBITS(1) [],
364        /// Memory data size
365        MSIZE OFFSET(13) NUMBITS(2) [],
366        /// Peripheral data size
367        PSIZE OFFSET(11) NUMBITS(2) [],
368        /// Memory increment mode
369        MINC OFFSET(10) NUMBITS(1) [],
370        /// Peripheral increment mode
371        PINC OFFSET(9) NUMBITS(1) [],
372        /// Circular mode
373        CIRC OFFSET(8) NUMBITS(1) [],
374        /// Data transfer direction
375        DIR OFFSET(6) NUMBITS(2) [],
376        /// Peripheral flow controller
377        PFCTRL OFFSET(5) NUMBITS(1) [],
378        /// Transfer complete interrupt enable
379        TCIE OFFSET(4) NUMBITS(1) [],
380        /// Half transfer interrupt enable
381        HTIE OFFSET(3) NUMBITS(1) [],
382        /// Transfer error interrupt enable
383        TEIE OFFSET(2) NUMBITS(1) [],
384        /// Direct mode error interrupt enable
385        DMEIE OFFSET(1) NUMBITS(1) [],
386        /// Stream enable / flag stream ready when read low
387        EN OFFSET(0) NUMBITS(1) []
388    ],
389    S1FCR [
390        /// FIFO error interrupt enable
391        FEIE OFFSET(7) NUMBITS(1) [],
392        /// FIFO status
393        FS OFFSET(3) NUMBITS(3) [],
394        /// Direct mode disable
395        DMDIS OFFSET(2) NUMBITS(1) [],
396        /// FIFO threshold selection
397        FTH OFFSET(0) NUMBITS(2) []
398    ],
399    S2CR [
400        /// Channel selection
401        CHSEL OFFSET(25) NUMBITS(3) [],
402        /// Memory burst transfer configuration
403        MBURST OFFSET(23) NUMBITS(2) [],
404        /// Peripheral burst transfer configuration
405        PBURST OFFSET(21) NUMBITS(2) [],
406        /// ACK
407        ACK OFFSET(20) NUMBITS(1) [],
408        /// Current target (only in double buffer mode)
409        CT OFFSET(19) NUMBITS(1) [],
410        /// Double buffer mode
411        DBM OFFSET(18) NUMBITS(1) [],
412        /// Priority level
413        PL OFFSET(16) NUMBITS(2) [],
414        /// Peripheral increment offset size
415        PINCOS OFFSET(15) NUMBITS(1) [],
416        /// Memory data size
417        MSIZE OFFSET(13) NUMBITS(2) [],
418        /// Peripheral data size
419        PSIZE OFFSET(11) NUMBITS(2) [],
420        /// Memory increment mode
421        MINC OFFSET(10) NUMBITS(1) [],
422        /// Peripheral increment mode
423        PINC OFFSET(9) NUMBITS(1) [],
424        /// Circular mode
425        CIRC OFFSET(8) NUMBITS(1) [],
426        /// Data transfer direction
427        DIR OFFSET(6) NUMBITS(2) [],
428        /// Peripheral flow controller
429        PFCTRL OFFSET(5) NUMBITS(1) [],
430        /// Transfer complete interrupt enable
431        TCIE OFFSET(4) NUMBITS(1) [],
432        /// Half transfer interrupt enable
433        HTIE OFFSET(3) NUMBITS(1) [],
434        /// Transfer error interrupt enable
435        TEIE OFFSET(2) NUMBITS(1) [],
436        /// Direct mode error interrupt enable
437        DMEIE OFFSET(1) NUMBITS(1) [],
438        /// Stream enable / flag stream ready when read low
439        EN OFFSET(0) NUMBITS(1) []
440    ],
441    S2FCR [
442        /// FIFO error interrupt enable
443        FEIE OFFSET(7) NUMBITS(1) [],
444        /// FIFO status
445        FS OFFSET(3) NUMBITS(3) [],
446        /// Direct mode disable
447        DMDIS OFFSET(2) NUMBITS(1) [],
448        /// FIFO threshold selection
449        FTH OFFSET(0) NUMBITS(2) []
450    ],
451    S3CR [
452        /// Channel selection
453        CHSEL OFFSET(25) NUMBITS(3) [],
454        /// Memory burst transfer configuration
455        MBURST OFFSET(23) NUMBITS(2) [],
456        /// Peripheral burst transfer configuration
457        PBURST OFFSET(21) NUMBITS(2) [],
458        /// ACK
459        ACK OFFSET(20) NUMBITS(1) [],
460        /// Current target (only in double buffer mode)
461        CT OFFSET(19) NUMBITS(1) [],
462        /// Double buffer mode
463        DBM OFFSET(18) NUMBITS(1) [],
464        /// Priority level
465        PL OFFSET(16) NUMBITS(2) [],
466        /// Peripheral increment offset size
467        PINCOS OFFSET(15) NUMBITS(1) [],
468        /// Memory data size
469        MSIZE OFFSET(13) NUMBITS(2) [],
470        /// Peripheral data size
471        PSIZE OFFSET(11) NUMBITS(2) [],
472        /// Memory increment mode
473        MINC OFFSET(10) NUMBITS(1) [],
474        /// Peripheral increment mode
475        PINC OFFSET(9) NUMBITS(1) [],
476        /// Circular mode
477        CIRC OFFSET(8) NUMBITS(1) [],
478        /// Data transfer direction
479        DIR OFFSET(6) NUMBITS(2) [],
480        /// Peripheral flow controller
481        PFCTRL OFFSET(5) NUMBITS(1) [],
482        /// Transfer complete interrupt enable
483        TCIE OFFSET(4) NUMBITS(1) [],
484        /// Half transfer interrupt enable
485        HTIE OFFSET(3) NUMBITS(1) [],
486        /// Transfer error interrupt enable
487        TEIE OFFSET(2) NUMBITS(1) [],
488        /// Direct mode error interrupt enable
489        DMEIE OFFSET(1) NUMBITS(1) [],
490        /// Stream enable / flag stream ready when read low
491        EN OFFSET(0) NUMBITS(1) []
492    ],
493    S3FCR [
494        /// FIFO error interrupt enable
495        FEIE OFFSET(7) NUMBITS(1) [],
496        /// FIFO status
497        FS OFFSET(3) NUMBITS(3) [],
498        /// Direct mode disable
499        DMDIS OFFSET(2) NUMBITS(1) [],
500        /// FIFO threshold selection
501        FTH OFFSET(0) NUMBITS(2) []
502    ],
503    S4CR [
504        /// Channel selection
505        CHSEL OFFSET(25) NUMBITS(3) [],
506        /// Memory burst transfer configuration
507        MBURST OFFSET(23) NUMBITS(2) [],
508        /// Peripheral burst transfer configuration
509        PBURST OFFSET(21) NUMBITS(2) [],
510        /// ACK
511        ACK OFFSET(20) NUMBITS(1) [],
512        /// Current target (only in double buffer mode)
513        CT OFFSET(19) NUMBITS(1) [],
514        /// Double buffer mode
515        DBM OFFSET(18) NUMBITS(1) [],
516        /// Priority level
517        PL OFFSET(16) NUMBITS(2) [],
518        /// Peripheral increment offset size
519        PINCOS OFFSET(15) NUMBITS(1) [],
520        /// Memory data size
521        MSIZE OFFSET(13) NUMBITS(2) [],
522        /// Peripheral data size
523        PSIZE OFFSET(11) NUMBITS(2) [],
524        /// Memory increment mode
525        MINC OFFSET(10) NUMBITS(1) [],
526        /// Peripheral increment mode
527        PINC OFFSET(9) NUMBITS(1) [],
528        /// Circular mode
529        CIRC OFFSET(8) NUMBITS(1) [],
530        /// Data transfer direction
531        DIR OFFSET(6) NUMBITS(2) [],
532        /// Peripheral flow controller
533        PFCTRL OFFSET(5) NUMBITS(1) [],
534        /// Transfer complete interrupt enable
535        TCIE OFFSET(4) NUMBITS(1) [],
536        /// Half transfer interrupt enable
537        HTIE OFFSET(3) NUMBITS(1) [],
538        /// Transfer error interrupt enable
539        TEIE OFFSET(2) NUMBITS(1) [],
540        /// Direct mode error interrupt enable
541        DMEIE OFFSET(1) NUMBITS(1) [],
542        /// Stream enable / flag stream ready when read low
543        EN OFFSET(0) NUMBITS(1) []
544    ],
545    S4FCR [
546        /// FIFO error interrupt enable
547        FEIE OFFSET(7) NUMBITS(1) [],
548        /// FIFO status
549        FS OFFSET(3) NUMBITS(3) [],
550        /// Direct mode disable
551        DMDIS OFFSET(2) NUMBITS(1) [],
552        /// FIFO threshold selection
553        FTH OFFSET(0) NUMBITS(2) []
554    ],
555    S5CR [
556        /// Channel selection
557        CHSEL OFFSET(25) NUMBITS(3) [],
558        /// Memory burst transfer configuration
559        MBURST OFFSET(23) NUMBITS(2) [],
560        /// Peripheral burst transfer configuration
561        PBURST OFFSET(21) NUMBITS(2) [],
562        /// ACK
563        ACK OFFSET(20) NUMBITS(1) [],
564        /// Current target (only in double buffer mode)
565        CT OFFSET(19) NUMBITS(1) [],
566        /// Double buffer mode
567        DBM OFFSET(18) NUMBITS(1) [],
568        /// Priority level
569        PL OFFSET(16) NUMBITS(2) [],
570        /// Peripheral increment offset size
571        PINCOS OFFSET(15) NUMBITS(1) [],
572        /// Memory data size
573        MSIZE OFFSET(13) NUMBITS(2) [],
574        /// Peripheral data size
575        PSIZE OFFSET(11) NUMBITS(2) [],
576        /// Memory increment mode
577        MINC OFFSET(10) NUMBITS(1) [],
578        /// Peripheral increment mode
579        PINC OFFSET(9) NUMBITS(1) [],
580        /// Circular mode
581        CIRC OFFSET(8) NUMBITS(1) [],
582        /// Data transfer direction
583        DIR OFFSET(6) NUMBITS(2) [],
584        /// Peripheral flow controller
585        PFCTRL OFFSET(5) NUMBITS(1) [],
586        /// Transfer complete interrupt enable
587        TCIE OFFSET(4) NUMBITS(1) [],
588        /// Half transfer interrupt enable
589        HTIE OFFSET(3) NUMBITS(1) [],
590        /// Transfer error interrupt enable
591        TEIE OFFSET(2) NUMBITS(1) [],
592        /// Direct mode error interrupt enable
593        DMEIE OFFSET(1) NUMBITS(1) [],
594        /// Stream enable / flag stream ready when read low
595        EN OFFSET(0) NUMBITS(1) []
596    ],
597    S5FCR [
598        /// FIFO error interrupt enable
599        FEIE OFFSET(7) NUMBITS(1) [],
600        /// FIFO status
601        FS OFFSET(3) NUMBITS(3) [],
602        /// Direct mode disable
603        DMDIS OFFSET(2) NUMBITS(1) [],
604        /// FIFO threshold selection
605        FTH OFFSET(0) NUMBITS(2) []
606    ],
607    S6CR [
608        /// Channel selection
609        CHSEL OFFSET(25) NUMBITS(3) [],
610        /// Memory burst transfer configuration
611        MBURST OFFSET(23) NUMBITS(2) [],
612        /// Peripheral burst transfer configuration
613        PBURST OFFSET(21) NUMBITS(2) [],
614        /// ACK
615        ACK OFFSET(20) NUMBITS(1) [],
616        /// Current target (only in double buffer mode)
617        CT OFFSET(19) NUMBITS(1) [],
618        /// Double buffer mode
619        DBM OFFSET(18) NUMBITS(1) [],
620        /// Priority level
621        PL OFFSET(16) NUMBITS(2) [],
622        /// Peripheral increment offset size
623        PINCOS OFFSET(15) NUMBITS(1) [],
624        /// Memory data size
625        MSIZE OFFSET(13) NUMBITS(2) [],
626        /// Peripheral data size
627        PSIZE OFFSET(11) NUMBITS(2) [],
628        /// Memory increment mode
629        MINC OFFSET(10) NUMBITS(1) [],
630        /// Peripheral increment mode
631        PINC OFFSET(9) NUMBITS(1) [],
632        /// Circular mode
633        CIRC OFFSET(8) NUMBITS(1) [],
634        /// Data transfer direction
635        DIR OFFSET(6) NUMBITS(2) [],
636        /// Peripheral flow controller
637        PFCTRL OFFSET(5) NUMBITS(1) [],
638        /// Transfer complete interrupt enable
639        TCIE OFFSET(4) NUMBITS(1) [],
640        /// Half transfer interrupt enable
641        HTIE OFFSET(3) NUMBITS(1) [],
642        /// Transfer error interrupt enable
643        TEIE OFFSET(2) NUMBITS(1) [],
644        /// Direct mode error interrupt enable
645        DMEIE OFFSET(1) NUMBITS(1) [],
646        /// Stream enable / flag stream ready when read low
647        EN OFFSET(0) NUMBITS(1) []
648    ],
649    S6FCR [
650        /// FIFO error interrupt enable
651        FEIE OFFSET(7) NUMBITS(1) [],
652        /// FIFO status
653        FS OFFSET(3) NUMBITS(3) [],
654        /// Direct mode disable
655        DMDIS OFFSET(2) NUMBITS(1) [],
656        /// FIFO threshold selection
657        FTH OFFSET(0) NUMBITS(2) []
658    ],
659    S7CR [
660        /// Channel selection
661        CHSEL OFFSET(25) NUMBITS(3) [],
662        /// Memory burst transfer configuration
663        MBURST OFFSET(23) NUMBITS(2) [],
664        /// Peripheral burst transfer configuration
665        PBURST OFFSET(21) NUMBITS(2) [],
666        /// ACK
667        ACK OFFSET(20) NUMBITS(1) [],
668        /// Current target (only in double buffer mode)
669        CT OFFSET(19) NUMBITS(1) [],
670        /// Double buffer mode
671        DBM OFFSET(18) NUMBITS(1) [],
672        /// Priority level
673        PL OFFSET(16) NUMBITS(2) [],
674        /// Peripheral increment offset size
675        PINCOS OFFSET(15) NUMBITS(1) [],
676        /// Memory data size
677        MSIZE OFFSET(13) NUMBITS(2) [],
678        /// Peripheral data size
679        PSIZE OFFSET(11) NUMBITS(2) [],
680        /// Memory increment mode
681        MINC OFFSET(10) NUMBITS(1) [],
682        /// Peripheral increment mode
683        PINC OFFSET(9) NUMBITS(1) [],
684        /// Circular mode
685        CIRC OFFSET(8) NUMBITS(1) [],
686        /// Data transfer direction
687        DIR OFFSET(6) NUMBITS(2) [],
688        /// Peripheral flow controller
689        PFCTRL OFFSET(5) NUMBITS(1) [],
690        /// Transfer complete interrupt enable
691        TCIE OFFSET(4) NUMBITS(1) [],
692        /// Half transfer interrupt enable
693        HTIE OFFSET(3) NUMBITS(1) [],
694        /// Transfer error interrupt enable
695        TEIE OFFSET(2) NUMBITS(1) [],
696        /// Direct mode error interrupt enable
697        DMEIE OFFSET(1) NUMBITS(1) [],
698        /// Stream enable / flag stream ready when read low
699        EN OFFSET(0) NUMBITS(1) []
700    ],
701    S7FCR [
702        /// FIFO error interrupt enable
703        FEIE OFFSET(7) NUMBITS(1) [],
704        /// FIFO status
705        FS OFFSET(3) NUMBITS(3) [],
706        /// Direct mode disable
707        DMDIS OFFSET(2) NUMBITS(1) [],
708        /// FIFO threshold selection
709        FTH OFFSET(0) NUMBITS(2) []
710    ]
711];
712
713/// The DMA stream number. What other microcontrollers refer to as "channel",
714/// STM32F446RE refers to as "streams". STM32F446RE has eight streams. A stream
715/// transfers data between memory and peripheral.
716#[repr(u8)]
717#[derive(Copy, Clone, PartialEq, Eq, Debug)]
718pub enum StreamId {
719    Stream0 = 0,
720    Stream1 = 1,
721    Stream2 = 2,
722    Stream3 = 3,
723    Stream4 = 4,
724    Stream5 = 5,
725    Stream6 = 6,
726    Stream7 = 7,
727}
728
729/// Each stream can be selected among up to eight channel requests.
730///
731/// This is basically STM32F446RE's way of selecting the peripheral
732/// for the stream.  Nevertheless, the use of the term channel here is
733/// confusing. Table 28 describes the mapping between stream, channel,
734/// and peripherals.
735#[repr(u32)]
736pub enum ChannelId {
737    Channel0 = 0b000,
738    Channel1 = 0b001,
739    Channel2 = 0b010,
740    Channel3 = 0b011,
741    Channel4 = 0b100,
742    Channel5 = 0b101,
743    Channel6 = 0b110,
744    Channel7 = 0b111,
745}
746
747/// DMA transfer direction. Section 9.5.5
748#[repr(u32)]
749pub enum Direction {
750    PeripheralToMemory = 0b00,
751    MemoryToPeripheral = 0b01,
752    MemoryToMemory = 0b10,
753}
754
755/// DMA data size. Section 9.5.5
756#[repr(u32)]
757pub enum Size {
758    Byte = 0b00,
759    HalfWord = 0b01,
760    Word = 0b10,
761}
762
763pub struct Msize(Size);
764pub struct Psize(Size);
765
766/// DMA transfer mode. Section 9.5.10
767#[repr(u32)]
768pub enum FifoSize {
769    Quarter = 0b00,
770    Half = 0b01,
771    ThreeFourths = 0b10,
772    Full = 0b11,
773}
774
775pub enum TransferMode {
776    Direct,
777    Fifo(FifoSize),
778}
779
780/// This struct refers to a DMA Stream
781///
782/// What other microcontrollers refer to as "channel", STM32F4XX refers to as "streams".
783/// STM32F4XX has eight streams per DMA.
784/// A stream transfers data between memory and peripheral.
785pub struct Stream<'a, DMA: StreamServer<'a>> {
786    streamid: StreamId,
787    client: OptionalCell<&'a dyn StreamClient<'a, DMA>>,
788    buffer: MapCell<SubSliceMut<'static, u8>>,
789    peripheral: OptionalCell<DMA::Peripheral>,
790    dma: &'a DMA,
791}
792
793impl<'a, DMA: StreamServer<'a>> Stream<'a, DMA> {
794    fn new(streamid: StreamId, dma: &'a DMA) -> Self {
795        Self {
796            streamid,
797            buffer: MapCell::empty(),
798            client: OptionalCell::empty(),
799            peripheral: OptionalCell::empty(),
800            dma,
801        }
802    }
803
804    pub fn set_client(&self, client: &'a dyn StreamClient<'a, DMA>) {
805        self.client.set(client);
806    }
807
808    pub fn handle_interrupt(&self) {
809        self.clear_transfer_complete_flag();
810
811        self.client.map(|client| {
812            self.peripheral.map(|pid| {
813                client.transfer_done(pid);
814            });
815        });
816    }
817
818    pub fn setup(&self, pid: DMA::Peripheral) {
819        // A Dma::Peripheral always corresponds to a certain stream.
820        // So make sure we use the correct peripheral with the right channel.
821        // See section 10.3.3 "Channel selection" of the RM0090 reference manual.
822        if self.streamid != pid.into() {
823            panic!(
824                "Error: Peripheral {:?} with stream id {:?} was assigned to wrong Dma Stream: {:?}",
825                pid,
826                pid.into(),
827                self.streamid
828            );
829        }
830
831        self.peripheral.set(pid);
832
833        // Setup is called before interrupts are enabled on the NVIC
834        self.disable_interrupt();
835        self.disable();
836
837        // The numbers below are from Section 1.2 of AN4031. It looks like these
838        // settings can be set only once. Trying to set them again, seems to
839        // generate a hard-fault even when the stream is disabled.
840        //
841        // 8
842        self.set_transfer_mode_for_peripheral();
843        // 9
844        self.set_data_width_for_peripheral();
845    }
846
847    pub fn do_transfer(&self, mut buf: SubSliceMut<'static, u8>) {
848        self.disable_interrupt();
849
850        // The numbers below are from Section 1.2 of AN4031
851        //
852        // NOTE: We only clear TC flag here. Trying to clear any other flag,
853        //       generates a hard-fault
854        // 1
855        self.disable();
856        self.clear_transfer_complete_flag();
857        // 2
858        self.set_peripheral_address();
859        // 3
860        self.set_memory_address(buf.as_mut_ptr() as u32);
861        // 4
862        self.set_data_items(buf.len() as u32);
863        // 5
864        self.set_channel();
865        // 9
866        self.set_direction();
867        self.set_peripheral_address_increment();
868        self.set_memory_address_increment();
869        self.interrupt_enable();
870        // 10
871        self.enable();
872
873        // NOTE: We still have to enable DMA on the peripheral side
874        self.buffer.replace(buf);
875    }
876
877    pub fn abort_transfer(&self) -> (Option<SubSliceMut<'static, u8>>, u32) {
878        self.disable_interrupt();
879
880        self.disable();
881
882        (self.buffer.take(), self.get_data_items())
883    }
884
885    pub fn return_buffer(&self) -> Option<SubSliceMut<'static, u8>> {
886        self.buffer.take()
887    }
888
889    fn set_channel(&self) {
890        self.peripheral.map(|pid| {
891            self.stream_set_channel(pid.channel_id());
892        });
893    }
894
895    fn stream_set_channel(&self, channel_id: ChannelId) {
896        match self.streamid {
897            StreamId::Stream0 => self
898                .dma
899                .registers()
900                .s0cr
901                .modify(S0CR::CHSEL.val(channel_id as u32)),
902            StreamId::Stream1 => self
903                .dma
904                .registers()
905                .s1cr
906                .modify(S1CR::CHSEL.val(channel_id as u32)),
907            StreamId::Stream2 => self
908                .dma
909                .registers()
910                .s2cr
911                .modify(S2CR::CHSEL.val(channel_id as u32)),
912            StreamId::Stream3 => self
913                .dma
914                .registers()
915                .s3cr
916                .modify(S3CR::CHSEL.val(channel_id as u32)),
917            StreamId::Stream4 => self
918                .dma
919                .registers()
920                .s4cr
921                .modify(S4CR::CHSEL.val(channel_id as u32)),
922            StreamId::Stream5 => self
923                .dma
924                .registers()
925                .s5cr
926                .modify(S5CR::CHSEL.val(channel_id as u32)),
927            StreamId::Stream6 => self
928                .dma
929                .registers()
930                .s6cr
931                .modify(S6CR::CHSEL.val(channel_id as u32)),
932            StreamId::Stream7 => self
933                .dma
934                .registers()
935                .s7cr
936                .modify(S7CR::CHSEL.val(channel_id as u32)),
937        }
938    }
939
940    fn set_direction(&self) {
941        self.peripheral.map(|pid| {
942            self.stream_set_direction(pid.direction());
943        });
944    }
945
946    fn stream_set_direction(&self, direction: Direction) {
947        match self.streamid {
948            StreamId::Stream0 => self
949                .dma
950                .registers()
951                .s0cr
952                .modify(S0CR::DIR.val(direction as u32)),
953            StreamId::Stream1 => self
954                .dma
955                .registers()
956                .s1cr
957                .modify(S1CR::DIR.val(direction as u32)),
958            StreamId::Stream2 => self
959                .dma
960                .registers()
961                .s2cr
962                .modify(S2CR::DIR.val(direction as u32)),
963            StreamId::Stream3 => self
964                .dma
965                .registers()
966                .s3cr
967                .modify(S3CR::DIR.val(direction as u32)),
968            StreamId::Stream4 => self
969                .dma
970                .registers()
971                .s4cr
972                .modify(S4CR::DIR.val(direction as u32)),
973            StreamId::Stream5 => self
974                .dma
975                .registers()
976                .s5cr
977                .modify(S5CR::DIR.val(direction as u32)),
978            StreamId::Stream6 => self
979                .dma
980                .registers()
981                .s6cr
982                .modify(S6CR::DIR.val(direction as u32)),
983            StreamId::Stream7 => self
984                .dma
985                .registers()
986                .s7cr
987                .modify(S7CR::DIR.val(direction as u32)),
988        }
989    }
990
991    fn set_peripheral_address(&self) {
992        self.peripheral.map(|pid| {
993            self.stream_set_peripheral_address(pid.address());
994        });
995    }
996
997    fn stream_set_peripheral_address(&self, address: u32) {
998        match self.streamid {
999            StreamId::Stream0 => self.dma.registers().s0par.set(address),
1000            StreamId::Stream1 => self.dma.registers().s1par.set(address),
1001            StreamId::Stream2 => self.dma.registers().s2par.set(address),
1002            StreamId::Stream3 => self.dma.registers().s3par.set(address),
1003            StreamId::Stream4 => self.dma.registers().s4par.set(address),
1004            StreamId::Stream5 => self.dma.registers().s5par.set(address),
1005            StreamId::Stream6 => self.dma.registers().s6par.set(address),
1006            StreamId::Stream7 => self.dma.registers().s7par.set(address),
1007        }
1008    }
1009
1010    fn set_peripheral_address_increment(&self) {
1011        match self.streamid {
1012            StreamId::Stream0 => self.dma.registers().s0cr.modify(S0CR::PINC::CLEAR),
1013            StreamId::Stream1 => self.dma.registers().s1cr.modify(S1CR::PINC::CLEAR),
1014            StreamId::Stream2 => self.dma.registers().s2cr.modify(S2CR::PINC::CLEAR),
1015            StreamId::Stream3 => self.dma.registers().s3cr.modify(S3CR::PINC::CLEAR),
1016            StreamId::Stream4 => self.dma.registers().s4cr.modify(S4CR::PINC::CLEAR),
1017            StreamId::Stream5 => self.dma.registers().s5cr.modify(S5CR::PINC::CLEAR),
1018            StreamId::Stream6 => self.dma.registers().s6cr.modify(S6CR::PINC::CLEAR),
1019            StreamId::Stream7 => self.dma.registers().s7cr.modify(S7CR::PINC::CLEAR),
1020        }
1021    }
1022
1023    fn set_memory_address(&self, buf_addr: u32) {
1024        match self.streamid {
1025            StreamId::Stream0 => self.dma.registers().s0m0ar.set(buf_addr),
1026            StreamId::Stream1 => self.dma.registers().s1m0ar.set(buf_addr),
1027            StreamId::Stream2 => self.dma.registers().s2m0ar.set(buf_addr),
1028            StreamId::Stream3 => self.dma.registers().s3m0ar.set(buf_addr),
1029            StreamId::Stream4 => self.dma.registers().s4m0ar.set(buf_addr),
1030            StreamId::Stream5 => self.dma.registers().s5m0ar.set(buf_addr),
1031            StreamId::Stream6 => self.dma.registers().s6m0ar.set(buf_addr),
1032            StreamId::Stream7 => self.dma.registers().s7m0ar.set(buf_addr),
1033        }
1034    }
1035
1036    fn set_memory_address_increment(&self) {
1037        match self.streamid {
1038            StreamId::Stream0 => self.dma.registers().s0cr.modify(S0CR::MINC::SET),
1039            StreamId::Stream1 => self.dma.registers().s1cr.modify(S1CR::MINC::SET),
1040            StreamId::Stream2 => self.dma.registers().s2cr.modify(S2CR::MINC::SET),
1041            StreamId::Stream3 => self.dma.registers().s3cr.modify(S3CR::MINC::SET),
1042            StreamId::Stream4 => self.dma.registers().s4cr.modify(S4CR::MINC::SET),
1043            StreamId::Stream5 => self.dma.registers().s5cr.modify(S5CR::MINC::SET),
1044            StreamId::Stream6 => self.dma.registers().s6cr.modify(S6CR::MINC::SET),
1045            StreamId::Stream7 => self.dma.registers().s7cr.modify(S7CR::MINC::SET),
1046        }
1047    }
1048
1049    fn get_data_items(&self) -> u32 {
1050        match self.streamid {
1051            StreamId::Stream0 => self.dma.registers().s0ndtr.get(),
1052            StreamId::Stream1 => self.dma.registers().s1ndtr.get(),
1053            StreamId::Stream2 => self.dma.registers().s2ndtr.get(),
1054            StreamId::Stream3 => self.dma.registers().s3ndtr.get(),
1055            StreamId::Stream4 => self.dma.registers().s4ndtr.get(),
1056            StreamId::Stream5 => self.dma.registers().s5ndtr.get(),
1057            StreamId::Stream6 => self.dma.registers().s6ndtr.get(),
1058            StreamId::Stream7 => self.dma.registers().s7ndtr.get(),
1059        }
1060    }
1061
1062    fn set_data_items(&self, data_items: u32) {
1063        match self.streamid {
1064            StreamId::Stream0 => {
1065                self.dma.registers().s0ndtr.set(data_items);
1066            }
1067            StreamId::Stream1 => {
1068                self.dma.registers().s1ndtr.set(data_items);
1069            }
1070            StreamId::Stream2 => {
1071                self.dma.registers().s2ndtr.set(data_items);
1072            }
1073            StreamId::Stream3 => {
1074                self.dma.registers().s3ndtr.set(data_items);
1075            }
1076            StreamId::Stream4 => {
1077                self.dma.registers().s4ndtr.set(data_items);
1078            }
1079            StreamId::Stream5 => {
1080                self.dma.registers().s5ndtr.set(data_items);
1081            }
1082            StreamId::Stream6 => {
1083                self.dma.registers().s6ndtr.set(data_items);
1084            }
1085            StreamId::Stream7 => {
1086                self.dma.registers().s7ndtr.set(data_items);
1087            }
1088        }
1089    }
1090
1091    fn set_data_width_for_peripheral(&self) {
1092        self.peripheral.map(|pid| {
1093            let (msize, psize) = pid.data_width();
1094            self.stream_set_data_width(msize, psize);
1095        });
1096    }
1097
1098    fn stream_set_data_width(&self, msize: Msize, psize: Psize) {
1099        match self.streamid {
1100            StreamId::Stream0 => {
1101                self.dma
1102                    .registers()
1103                    .s0cr
1104                    .modify(S0CR::PSIZE.val(psize.0 as u32));
1105                self.dma
1106                    .registers()
1107                    .s0cr
1108                    .modify(S0CR::MSIZE.val(msize.0 as u32));
1109            }
1110            StreamId::Stream1 => {
1111                self.dma
1112                    .registers()
1113                    .s1cr
1114                    .modify(S1CR::PSIZE.val(psize.0 as u32));
1115                self.dma
1116                    .registers()
1117                    .s1cr
1118                    .modify(S1CR::MSIZE.val(msize.0 as u32));
1119            }
1120            StreamId::Stream2 => {
1121                self.dma
1122                    .registers()
1123                    .s2cr
1124                    .modify(S2CR::PSIZE.val(psize.0 as u32));
1125                self.dma
1126                    .registers()
1127                    .s2cr
1128                    .modify(S2CR::MSIZE.val(msize.0 as u32));
1129            }
1130            StreamId::Stream3 => {
1131                self.dma
1132                    .registers()
1133                    .s3cr
1134                    .modify(S3CR::PSIZE.val(psize.0 as u32));
1135                self.dma
1136                    .registers()
1137                    .s3cr
1138                    .modify(S3CR::MSIZE.val(msize.0 as u32));
1139            }
1140            StreamId::Stream4 => {
1141                self.dma
1142                    .registers()
1143                    .s4cr
1144                    .modify(S4CR::PSIZE.val(psize.0 as u32));
1145                self.dma
1146                    .registers()
1147                    .s4cr
1148                    .modify(S4CR::MSIZE.val(msize.0 as u32));
1149            }
1150            StreamId::Stream5 => {
1151                self.dma
1152                    .registers()
1153                    .s5cr
1154                    .modify(S5CR::PSIZE.val(psize.0 as u32));
1155                self.dma
1156                    .registers()
1157                    .s5cr
1158                    .modify(S5CR::MSIZE.val(msize.0 as u32));
1159            }
1160            StreamId::Stream6 => {
1161                self.dma
1162                    .registers()
1163                    .s6cr
1164                    .modify(S6CR::PSIZE.val(psize.0 as u32));
1165                self.dma
1166                    .registers()
1167                    .s6cr
1168                    .modify(S6CR::MSIZE.val(msize.0 as u32));
1169            }
1170            StreamId::Stream7 => {
1171                self.dma
1172                    .registers()
1173                    .s7cr
1174                    .modify(S7CR::PSIZE.val(psize.0 as u32));
1175                self.dma
1176                    .registers()
1177                    .s7cr
1178                    .modify(S7CR::MSIZE.val(msize.0 as u32));
1179            }
1180        }
1181    }
1182
1183    fn set_transfer_mode_for_peripheral(&self) {
1184        self.peripheral.map(|pid| {
1185            self.stream_set_transfer_mode(pid.transfer_mode());
1186        });
1187    }
1188
1189    fn stream_set_transfer_mode(&self, transfer_mode: TransferMode) {
1190        match self.streamid {
1191            StreamId::Stream0 => match transfer_mode {
1192                TransferMode::Direct => {
1193                    self.dma.registers().s0fcr.modify(S0FCR::DMDIS::CLEAR);
1194                }
1195                TransferMode::Fifo(s) => {
1196                    self.dma.registers().s0fcr.modify(S0FCR::DMDIS::SET);
1197                    self.dma.registers().s0fcr.modify(S0FCR::FTH.val(s as u32));
1198                }
1199            },
1200            StreamId::Stream1 => match transfer_mode {
1201                TransferMode::Direct => {
1202                    self.dma.registers().s1fcr.modify(S1FCR::DMDIS::CLEAR);
1203                }
1204                TransferMode::Fifo(s) => {
1205                    self.dma.registers().s1fcr.modify(S1FCR::DMDIS::SET);
1206                    self.dma.registers().s1fcr.modify(S1FCR::FTH.val(s as u32));
1207                }
1208            },
1209            StreamId::Stream2 => match transfer_mode {
1210                TransferMode::Direct => {
1211                    self.dma.registers().s2fcr.modify(S2FCR::DMDIS::CLEAR);
1212                }
1213                TransferMode::Fifo(s) => {
1214                    self.dma.registers().s2fcr.modify(S2FCR::DMDIS::SET);
1215                    self.dma.registers().s2fcr.modify(S2FCR::FTH.val(s as u32));
1216                }
1217            },
1218            StreamId::Stream3 => match transfer_mode {
1219                TransferMode::Direct => {
1220                    self.dma.registers().s3fcr.modify(S3FCR::DMDIS::CLEAR);
1221                }
1222                TransferMode::Fifo(s) => {
1223                    self.dma.registers().s3fcr.modify(S3FCR::DMDIS::SET);
1224                    self.dma.registers().s3fcr.modify(S3FCR::FTH.val(s as u32));
1225                }
1226            },
1227            StreamId::Stream4 => match transfer_mode {
1228                TransferMode::Direct => {
1229                    self.dma.registers().s4fcr.modify(S4FCR::DMDIS::CLEAR);
1230                }
1231                TransferMode::Fifo(s) => {
1232                    self.dma.registers().s4fcr.modify(S4FCR::DMDIS::SET);
1233                    self.dma.registers().s4fcr.modify(S4FCR::FTH.val(s as u32));
1234                }
1235            },
1236            StreamId::Stream5 => match transfer_mode {
1237                TransferMode::Direct => {
1238                    self.dma.registers().s5fcr.modify(S5FCR::DMDIS::CLEAR);
1239                }
1240                TransferMode::Fifo(s) => {
1241                    self.dma.registers().s5fcr.modify(S5FCR::DMDIS::SET);
1242                    self.dma.registers().s5fcr.modify(S5FCR::FTH.val(s as u32));
1243                }
1244            },
1245            StreamId::Stream6 => match transfer_mode {
1246                TransferMode::Direct => {
1247                    self.dma.registers().s6fcr.modify(S6FCR::DMDIS::CLEAR);
1248                }
1249                TransferMode::Fifo(s) => {
1250                    self.dma.registers().s6fcr.modify(S6FCR::DMDIS::SET);
1251                    self.dma.registers().s6fcr.modify(S6FCR::FTH.val(s as u32));
1252                }
1253            },
1254            StreamId::Stream7 => match transfer_mode {
1255                TransferMode::Direct => {
1256                    self.dma.registers().s7fcr.modify(S7FCR::DMDIS::CLEAR);
1257                }
1258                TransferMode::Fifo(s) => {
1259                    self.dma.registers().s7fcr.modify(S7FCR::DMDIS::SET);
1260                    self.dma.registers().s7fcr.modify(S7FCR::FTH.val(s as u32));
1261                }
1262            },
1263        }
1264    }
1265
1266    fn enable(&self) {
1267        match self.streamid {
1268            StreamId::Stream0 => self.dma.registers().s0cr.modify(S0CR::EN::SET),
1269            StreamId::Stream1 => self.dma.registers().s1cr.modify(S1CR::EN::SET),
1270            StreamId::Stream2 => self.dma.registers().s2cr.modify(S2CR::EN::SET),
1271            StreamId::Stream3 => self.dma.registers().s3cr.modify(S3CR::EN::SET),
1272            StreamId::Stream4 => self.dma.registers().s4cr.modify(S4CR::EN::SET),
1273            StreamId::Stream5 => self.dma.registers().s5cr.modify(S5CR::EN::SET),
1274            StreamId::Stream6 => self.dma.registers().s6cr.modify(S6CR::EN::SET),
1275            StreamId::Stream7 => self.dma.registers().s7cr.modify(S7CR::EN::SET),
1276        }
1277    }
1278
1279    fn disable(&self) {
1280        match self.streamid {
1281            StreamId::Stream0 => self.dma.registers().s0cr.modify(S0CR::EN::CLEAR),
1282            StreamId::Stream1 => self.dma.registers().s1cr.modify(S1CR::EN::CLEAR),
1283            StreamId::Stream2 => self.dma.registers().s2cr.modify(S2CR::EN::CLEAR),
1284            StreamId::Stream3 => self.dma.registers().s3cr.modify(S3CR::EN::CLEAR),
1285            StreamId::Stream4 => self.dma.registers().s4cr.modify(S4CR::EN::CLEAR),
1286            StreamId::Stream5 => self.dma.registers().s5cr.modify(S5CR::EN::CLEAR),
1287            StreamId::Stream6 => self.dma.registers().s6cr.modify(S6CR::EN::CLEAR),
1288            StreamId::Stream7 => self.dma.registers().s7cr.modify(S7CR::EN::CLEAR),
1289        }
1290    }
1291
1292    fn clear_transfer_complete_flag(&self) {
1293        match self.streamid {
1294            StreamId::Stream0 => {
1295                self.dma.registers().lifcr.write(LIFCR::CTCIF0::SET);
1296            }
1297            StreamId::Stream1 => {
1298                self.dma.registers().lifcr.write(LIFCR::CTCIF1::SET);
1299            }
1300            StreamId::Stream2 => {
1301                self.dma.registers().lifcr.write(LIFCR::CTCIF2::SET);
1302            }
1303            StreamId::Stream3 => {
1304                self.dma.registers().lifcr.write(LIFCR::CTCIF3::SET);
1305            }
1306            StreamId::Stream4 => {
1307                self.dma.registers().hifcr.write(HIFCR::CTCIF4::SET);
1308            }
1309            StreamId::Stream5 => {
1310                self.dma.registers().hifcr.write(HIFCR::CTCIF5::SET);
1311            }
1312            StreamId::Stream6 => {
1313                self.dma.registers().hifcr.write(HIFCR::CTCIF6::SET);
1314            }
1315            StreamId::Stream7 => {
1316                self.dma.registers().hifcr.write(HIFCR::CTCIF7::SET);
1317            }
1318        }
1319    }
1320
1321    // We only interrupt on TC (Transfer Complete)
1322    fn interrupt_enable(&self) {
1323        match self.streamid {
1324            StreamId::Stream0 => self.dma.registers().s0cr.modify(S0CR::TCIE::SET),
1325            StreamId::Stream1 => self.dma.registers().s1cr.modify(S1CR::TCIE::SET),
1326            StreamId::Stream2 => self.dma.registers().s2cr.modify(S2CR::TCIE::SET),
1327            StreamId::Stream3 => self.dma.registers().s3cr.modify(S3CR::TCIE::SET),
1328            StreamId::Stream4 => self.dma.registers().s4cr.modify(S4CR::TCIE::SET),
1329            StreamId::Stream5 => self.dma.registers().s5cr.modify(S5CR::TCIE::SET),
1330            StreamId::Stream6 => self.dma.registers().s6cr.modify(S6CR::TCIE::SET),
1331            StreamId::Stream7 => self.dma.registers().s7cr.modify(S7CR::TCIE::SET),
1332        }
1333    }
1334
1335    // We only interrupt on TC (Transfer Complete)
1336    fn disable_interrupt(&self) {
1337        match self.streamid {
1338            StreamId::Stream0 => self.dma.registers().s0cr.modify(S0CR::TCIE::CLEAR),
1339            StreamId::Stream1 => self.dma.registers().s1cr.modify(S1CR::TCIE::CLEAR),
1340            StreamId::Stream2 => self.dma.registers().s2cr.modify(S2CR::TCIE::CLEAR),
1341            StreamId::Stream3 => self.dma.registers().s3cr.modify(S3CR::TCIE::CLEAR),
1342            StreamId::Stream4 => self.dma.registers().s4cr.modify(S4CR::TCIE::CLEAR),
1343            StreamId::Stream5 => self.dma.registers().s5cr.modify(S5CR::TCIE::CLEAR),
1344            StreamId::Stream6 => self.dma.registers().s6cr.modify(S6CR::TCIE::CLEAR),
1345            StreamId::Stream7 => self.dma.registers().s7cr.modify(S7CR::TCIE::CLEAR),
1346        }
1347    }
1348}
1349
1350/// Interface required for each Peripheral by the DMA Stream.
1351///
1352/// The data defined here may vary by Peripheral. It is used by the DMA Stream
1353/// to correctly configure the DMA.
1354///
1355/// To implement a new Peripheral, add it to the corresponding enum (Dma1-/Dma2Peripheral)
1356/// and add its data to the impl of this trait.
1357pub trait StreamPeripheral {
1358    fn transfer_mode(&self) -> TransferMode;
1359
1360    fn data_width(&self) -> (Msize, Psize);
1361
1362    fn channel_id(&self) -> ChannelId;
1363
1364    fn direction(&self) -> Direction;
1365
1366    fn address(&self) -> u32;
1367}
1368
1369pub trait StreamServer<'a> {
1370    type Peripheral: StreamPeripheral + core::marker::Copy + PartialEq + Into<StreamId> + Debug;
1371
1372    fn registers(&self) -> &DmaRegisters;
1373}
1374
1375pub trait StreamClient<'a, DMA: StreamServer<'a>> {
1376    fn transfer_done(&self, pid: DMA::Peripheral);
1377}
1378
1379struct DmaClock<'a>(phclk::PeripheralClock<'a>);
1380
1381impl ClockInterface for DmaClock<'_> {
1382    fn is_enabled(&self) -> bool {
1383        self.0.is_enabled()
1384    }
1385
1386    fn enable(&self) {
1387        self.0.enable();
1388    }
1389
1390    fn disable(&self) {
1391        self.0.disable();
1392    }
1393}
1394
1395// ########################## DMA 1 ######################################
1396
1397/// List of peripherals managed by DMA1
1398#[allow(non_camel_case_types, non_snake_case)]
1399#[derive(Copy, Clone, PartialEq, Debug)]
1400pub enum Dma1Peripheral {
1401    USART2_TX,
1402    USART2_RX,
1403    USART3_TX,
1404    USART3_RX,
1405    SPI3_TX,
1406    SPI3_RX,
1407}
1408
1409impl Dma1Peripheral {
1410    // Returns the IRQ number of the stream associated with the peripheral. Used
1411    // to enable interrupt on the NVIC.
1412    pub fn get_stream_irqn(&self) -> u32 {
1413        match self {
1414            Dma1Peripheral::SPI3_TX => nvic::DMA1_Stream7,
1415            Dma1Peripheral::USART2_TX => nvic::DMA1_Stream6,
1416            Dma1Peripheral::USART2_RX => nvic::DMA1_Stream5,
1417            Dma1Peripheral::USART3_TX => nvic::DMA1_Stream3,
1418            Dma1Peripheral::SPI3_RX => nvic::DMA1_Stream2,
1419            Dma1Peripheral::USART3_RX => nvic::DMA1_Stream1,
1420        }
1421    }
1422
1423    pub fn get_stream_idx(&self) -> usize {
1424        usize::from(StreamId::from(*self) as u8)
1425    }
1426}
1427
1428impl From<Dma1Peripheral> for StreamId {
1429    fn from(pid: Dma1Peripheral) -> StreamId {
1430        match pid {
1431            Dma1Peripheral::SPI3_TX => StreamId::Stream7,
1432            Dma1Peripheral::USART2_TX => StreamId::Stream6,
1433            Dma1Peripheral::USART2_RX => StreamId::Stream5,
1434            Dma1Peripheral::USART3_TX => StreamId::Stream3,
1435            Dma1Peripheral::SPI3_RX => StreamId::Stream2,
1436            Dma1Peripheral::USART3_RX => StreamId::Stream1,
1437        }
1438    }
1439}
1440
1441impl StreamPeripheral for Dma1Peripheral {
1442    fn transfer_mode(&self) -> TransferMode {
1443        TransferMode::Fifo(FifoSize::Full)
1444    }
1445
1446    fn data_width(&self) -> (Msize, Psize) {
1447        (Msize(Size::Byte), Psize(Size::Byte))
1448    }
1449
1450    fn channel_id(&self) -> ChannelId {
1451        match self {
1452            Dma1Peripheral::SPI3_TX => {
1453                // SPI3_RX Stream 7, Channel 0
1454                ChannelId::Channel0
1455            }
1456            Dma1Peripheral::USART2_TX => {
1457                // USART2_TX Stream 6, Channel 4
1458                ChannelId::Channel4
1459            }
1460            Dma1Peripheral::USART2_RX => {
1461                // USART2_RX Stream 5, Channel 4
1462                ChannelId::Channel4
1463            }
1464            Dma1Peripheral::USART3_TX => {
1465                // USART3_TX Stream 3, Channel 4
1466                ChannelId::Channel4
1467            }
1468            Dma1Peripheral::SPI3_RX => {
1469                // SPI3_RX Stream 2, Channel 0
1470                ChannelId::Channel0
1471            }
1472            Dma1Peripheral::USART3_RX => {
1473                // USART3_RX Stream 1, Channel 4
1474                ChannelId::Channel4
1475            }
1476        }
1477    }
1478
1479    fn direction(&self) -> Direction {
1480        match self {
1481            Dma1Peripheral::SPI3_TX => Direction::MemoryToPeripheral,
1482            Dma1Peripheral::USART2_TX => Direction::MemoryToPeripheral,
1483            Dma1Peripheral::USART2_RX => Direction::PeripheralToMemory,
1484            Dma1Peripheral::USART3_TX => Direction::MemoryToPeripheral,
1485            Dma1Peripheral::SPI3_RX => Direction::PeripheralToMemory,
1486            Dma1Peripheral::USART3_RX => Direction::PeripheralToMemory,
1487        }
1488    }
1489
1490    fn address(&self) -> u32 {
1491        match self {
1492            Dma1Peripheral::SPI3_TX => spi::get_address_dr(spi::SPI3_BASE),
1493            Dma1Peripheral::USART2_TX => usart::get_address_dr(usart::USART2_BASE),
1494            Dma1Peripheral::USART2_RX => usart::get_address_dr(usart::USART2_BASE),
1495            Dma1Peripheral::USART3_TX => usart::get_address_dr(usart::USART3_BASE),
1496            Dma1Peripheral::SPI3_RX => spi::get_address_dr(spi::SPI3_BASE),
1497            Dma1Peripheral::USART3_RX => usart::get_address_dr(usart::USART3_BASE),
1498        }
1499    }
1500}
1501
1502pub fn new_dma1_stream<'a>(dma: &'a Dma1) -> [Stream<'a, Dma1<'a>>; 8] {
1503    [
1504        Stream::new(StreamId::Stream0, dma),
1505        Stream::new(StreamId::Stream1, dma),
1506        Stream::new(StreamId::Stream2, dma),
1507        Stream::new(StreamId::Stream3, dma),
1508        Stream::new(StreamId::Stream4, dma),
1509        Stream::new(StreamId::Stream5, dma),
1510        Stream::new(StreamId::Stream6, dma),
1511        Stream::new(StreamId::Stream7, dma),
1512    ]
1513}
1514
1515const DMA1_BASE: StaticRef<DmaRegisters> =
1516    unsafe { StaticRef::new(0x40026000 as *const DmaRegisters) };
1517
1518/// Dma1 is kept as a separate type from Dma2 in order to allow for more compile-time checks.
1519///
1520/// Excerpt from the discussion on this decision:
1521///
1522/// > It's definitely a tradeoff between having code duplication vs. more checks at compile time.
1523/// > With the current implementation the Dma is propagated to the types of Usart & SPI, so usart1 is a Usart\<Dma2\>.
1524/// > In theory, we could simply have a single DmaPeripheral enum, that contains all peripherals, with a single, non-generic Stream struct implementation.
1525/// > This way we wouldn't have any code duplication and both Usart and Spi would no longer have to be generic over the Dma or its peripheral.
1526/// > The disadvantage then would be, that one could create a Usart instance for usart1 and accidentally pass it a stream of dma1, instead of dma2. Currently, this is impossible, as they are of different types.
1527/// >
1528/// > We could have these checks at runtime, with the Peripheral reporting which Dma it belongs to and the system panicking if it's set up incorrectly, like I have added for checking whether the peripheral is added to the right stream.
1529/// >
1530/// > So we basically have three options here:
1531/// > 1. Keep Stream\<DmaX\>
1532/// > 2. Change to Stream\<DmaXPeripheral\>
1533/// > 3. Remove Generics from Stream & add runtime checks
1534/// >
1535/// > In order of most code duplication & compile-time safety to least.
1536///
1537/// The decision to stick with separate types for DMA 1 and DMA 2 was made because:
1538///
1539/// > Static checks are good, and the code duplication here looks manageable (i.e. it's pretty formulaic and unlikely to need to change much if at all).
1540///
1541/// For details, see [the full discussion](https://github.com/tock/tock/pull/2936#discussion_r792908212).
1542pub struct Dma1<'a> {
1543    registers: StaticRef<DmaRegisters>,
1544    clock: DmaClock<'a>,
1545}
1546
1547impl<'a> Dma1<'a> {
1548    pub const fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
1549        Self {
1550            registers: DMA1_BASE,
1551            clock: DmaClock(phclk::PeripheralClock::new(
1552                phclk::PeripheralClockType::AHB1(phclk::HCLK1::DMA1),
1553                clocks,
1554            )),
1555        }
1556    }
1557
1558    pub fn is_enabled_clock(&self) -> bool {
1559        self.clock.is_enabled()
1560    }
1561
1562    pub fn enable_clock(&self) {
1563        self.clock.enable();
1564    }
1565
1566    pub fn disable_clock(&self) {
1567        self.clock.disable();
1568    }
1569}
1570
1571impl<'a> StreamServer<'a> for Dma1<'a> {
1572    type Peripheral = Dma1Peripheral;
1573
1574    fn registers(&self) -> &DmaRegisters {
1575        &self.registers
1576    }
1577}
1578
1579// ########################## DMA 2 ######################################
1580
1581/// List of peripherals managed by DMA2
1582#[allow(non_camel_case_types, non_snake_case)]
1583#[derive(Copy, Clone, PartialEq, Debug)]
1584pub enum Dma2Peripheral {
1585    USART1_TX,
1586    USART1_RX,
1587}
1588
1589impl Dma2Peripheral {
1590    // Returns the IRQ number of the stream associated with the peripheral. Used
1591    // to enable interrupt on the NVIC.
1592    pub fn get_stream_irqn(&self) -> u32 {
1593        match self {
1594            Dma2Peripheral::USART1_TX => nvic::DMA2_Stream7,
1595            Dma2Peripheral::USART1_RX => nvic::DMA2_Stream5, // could also be Stream 2, chosen arbitrarily
1596        }
1597    }
1598
1599    pub fn get_stream_idx(&self) -> usize {
1600        usize::from(StreamId::from(*self) as u8)
1601    }
1602}
1603
1604impl From<Dma2Peripheral> for StreamId {
1605    fn from(pid: Dma2Peripheral) -> StreamId {
1606        match pid {
1607            Dma2Peripheral::USART1_TX => StreamId::Stream7,
1608            Dma2Peripheral::USART1_RX => StreamId::Stream5,
1609        }
1610    }
1611}
1612
1613impl StreamPeripheral for Dma2Peripheral {
1614    fn transfer_mode(&self) -> TransferMode {
1615        TransferMode::Fifo(FifoSize::Full)
1616    }
1617
1618    fn data_width(&self) -> (Msize, Psize) {
1619        (Msize(Size::Byte), Psize(Size::Byte))
1620    }
1621
1622    fn channel_id(&self) -> ChannelId {
1623        match self {
1624            // USART1_TX Stream 7, Channel 4
1625            Dma2Peripheral::USART1_TX => ChannelId::Channel4,
1626            // USART1_RX Stream 5, Channel 4
1627            Dma2Peripheral::USART1_RX => ChannelId::Channel4,
1628        }
1629    }
1630
1631    fn direction(&self) -> Direction {
1632        match self {
1633            Dma2Peripheral::USART1_TX => Direction::MemoryToPeripheral,
1634            Dma2Peripheral::USART1_RX => Direction::PeripheralToMemory,
1635        }
1636    }
1637
1638    fn address(&self) -> u32 {
1639        match self {
1640            Dma2Peripheral::USART1_TX => usart::get_address_dr(usart::USART1_BASE),
1641            Dma2Peripheral::USART1_RX => usart::get_address_dr(usart::USART1_BASE),
1642        }
1643    }
1644}
1645
1646pub fn new_dma2_stream<'a>(dma: &'a Dma2) -> [Stream<'a, Dma2<'a>>; 8] {
1647    [
1648        Stream::new(StreamId::Stream0, dma),
1649        Stream::new(StreamId::Stream1, dma),
1650        Stream::new(StreamId::Stream2, dma),
1651        Stream::new(StreamId::Stream3, dma),
1652        Stream::new(StreamId::Stream4, dma),
1653        Stream::new(StreamId::Stream5, dma),
1654        Stream::new(StreamId::Stream6, dma),
1655        Stream::new(StreamId::Stream7, dma),
1656    ]
1657}
1658
1659const DMA2_BASE: StaticRef<DmaRegisters> =
1660    unsafe { StaticRef::new(0x40026400 as *const DmaRegisters) };
1661
1662/// For an explanation of why this is its own type, see the docs for the Dma1 struct.
1663pub struct Dma2<'a> {
1664    registers: StaticRef<DmaRegisters>,
1665    clock: DmaClock<'a>,
1666}
1667
1668impl<'a> Dma2<'a> {
1669    pub const fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
1670        Self {
1671            registers: DMA2_BASE,
1672            clock: DmaClock(phclk::PeripheralClock::new(
1673                phclk::PeripheralClockType::AHB1(phclk::HCLK1::DMA2),
1674                clocks,
1675            )),
1676        }
1677    }
1678
1679    pub fn is_enabled_clock(&self) -> bool {
1680        self.clock.is_enabled()
1681    }
1682
1683    pub fn enable_clock(&self) {
1684        self.clock.enable();
1685    }
1686
1687    pub fn disable_clock(&self) {
1688        self.clock.disable();
1689    }
1690}
1691
1692impl<'a> StreamServer<'a> for Dma2<'a> {
1693    type Peripheral = Dma2Peripheral;
1694
1695    fn registers(&self) -> &DmaRegisters {
1696        &self.registers
1697    }
1698}