aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c')
-rw-r--r--lib/chibios/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c816
1 files changed, 816 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c b/lib/chibios/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c
new file mode 100644
index 000000000..65fa5e8bc
--- /dev/null
+++ b/lib/chibios/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c
@@ -0,0 +1,816 @@
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file DMAv1/stm32_dma.c
19 * @brief DMA helper driver code.
20 *
21 * @addtogroup STM32_DMA
22 * @details DMA sharing helper driver. In the STM32 the DMA streams are a
23 * shared resource, this driver allows to allocate and free DMA
24 * streams at runtime in order to allow all the other device
25 * drivers to coordinate the access to the resource.
26 * @note The DMA ISR handlers are all declared into this module because
27 * sharing, the various device drivers can associate a callback to
28 * ISRs when allocating streams.
29 * @{
30 */
31
32#include "hal.h"
33
34/* The following macro is only defined if some driver requiring DMA services
35 has been enabled.*/
36#if defined(STM32_DMA_REQUIRED) || defined(__DOXYGEN__)
37
38/*===========================================================================*/
39/* Driver local definitions. */
40/*===========================================================================*/
41
42/**
43 * @brief Mask of the DMA1 streams in @p dma_streams_mask.
44 */
45#define STM32_DMA1_STREAMS_MASK ((1U << STM32_DMA1_NUM_CHANNELS) - 1U)
46
47/**
48 * @brief Mask of the DMA2 streams in @p dma_streams_mask.
49 */
50#define STM32_DMA2_STREAMS_MASK (((1U << STM32_DMA2_NUM_CHANNELS) - \
51 1U) << STM32_DMA1_NUM_CHANNELS)
52
53#if STM32_DMA_SUPPORTS_CSELR == TRUE
54
55#if defined(DMA1_CSELR)
56#define __DMA1_CSELR &DMA1_CSELR->CSELR
57#else
58#define __DMA1_CSELR &DMA1->CSELR
59#endif
60
61#if defined(DMA2_CSELR)
62#define __DMA2_CSELR &DMA2_CSELR->CSELR
63#else
64#define __DMA2_CSELR &DMA2->CSELR
65#endif
66
67#define DMA1_CH1_VARIANT __DMA1_CSELR
68#define DMA1_CH2_VARIANT __DMA1_CSELR
69#define DMA1_CH3_VARIANT __DMA1_CSELR
70#define DMA1_CH4_VARIANT __DMA1_CSELR
71#define DMA1_CH5_VARIANT __DMA1_CSELR
72#define DMA1_CH6_VARIANT __DMA1_CSELR
73#define DMA1_CH7_VARIANT __DMA1_CSELR
74#define DMA1_CH8_VARIANT __DMA1_CSELR
75#define DMA2_CH1_VARIANT __DMA2_CSELR
76#define DMA2_CH2_VARIANT __DMA2_CSELR
77#define DMA2_CH3_VARIANT __DMA2_CSELR
78#define DMA2_CH4_VARIANT __DMA2_CSELR
79#define DMA2_CH5_VARIANT __DMA2_CSELR
80#define DMA2_CH6_VARIANT __DMA2_CSELR
81#define DMA2_CH7_VARIANT __DMA2_CSELR
82#define DMA2_CH8_VARIANT __DMA2_CSELR
83
84#elif STM32_DMA_SUPPORTS_DMAMUX == TRUE
85
86#define DMAMUX1_CHANNEL(id) (DMAMUX1_BASE + ((id) * 4U))
87
88#define DMA1_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0))
89#define DMA1_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1))
90#define DMA1_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2))
91#define DMA1_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3))
92#define DMA1_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4))
93#define DMA1_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5))
94#define DMA1_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6))
95#define DMA1_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7))
96#define DMA2_CH1_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(0 + STM32_DMA1_NUM_CHANNELS))
97#define DMA2_CH2_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(1 + STM32_DMA1_NUM_CHANNELS))
98#define DMA2_CH3_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(2 + STM32_DMA1_NUM_CHANNELS))
99#define DMA2_CH4_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(3 + STM32_DMA1_NUM_CHANNELS))
100#define DMA2_CH5_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(4 + STM32_DMA1_NUM_CHANNELS))
101#define DMA2_CH6_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(5 + STM32_DMA1_NUM_CHANNELS))
102#define DMA2_CH7_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(6 + STM32_DMA1_NUM_CHANNELS))
103#define DMA2_CH8_VARIANT ((DMAMUX_Channel_TypeDef *)DMAMUX1_CHANNEL(7 + STM32_DMA1_NUM_CHANNELS))
104
105#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
106
107#define DMA1_CH1_VARIANT 0
108#define DMA1_CH2_VARIANT 0
109#define DMA1_CH3_VARIANT 0
110#define DMA1_CH4_VARIANT 0
111#define DMA1_CH5_VARIANT 0
112#define DMA1_CH6_VARIANT 0
113#define DMA1_CH7_VARIANT 0
114#define DMA2_CH1_VARIANT 0
115#define DMA2_CH2_VARIANT 0
116#define DMA2_CH3_VARIANT 0
117#define DMA2_CH4_VARIANT 0
118#define DMA2_CH5_VARIANT 0
119#define DMA2_CH6_VARIANT 0
120#define DMA2_CH7_VARIANT 0
121
122#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
123
124/*
125 * Default ISR collision masks.
126 */
127#if !defined(STM32_DMA1_CH1_CMASK)
128#define STM32_DMA1_CH1_CMASK (1U << 0U)
129#endif
130
131#if !defined(STM32_DMA1_CH2_CMASK)
132#define STM32_DMA1_CH2_CMASK (1U << 1U)
133#endif
134
135#if !defined(STM32_DMA1_CH3_CMASK)
136#define STM32_DMA1_CH3_CMASK (1U << 2U)
137#endif
138
139#if !defined(STM32_DMA1_CH4_CMASK)
140#define STM32_DMA1_CH4_CMASK (1U << 3U)
141#endif
142
143#if !defined(STM32_DMA1_CH5_CMASK)
144#define STM32_DMA1_CH5_CMASK (1U << 4U)
145#endif
146
147#if !defined(STM32_DMA1_CH6_CMASK)
148#define STM32_DMA1_CH6_CMASK (1U << 5U)
149#endif
150
151#if !defined(STM32_DMA1_CH7_CMASK)
152#define STM32_DMA1_CH7_CMASK (1U << 6U)
153#endif
154
155#if !defined(STM32_DMA1_CH8_CMASK)
156#define STM32_DMA1_CH8_CMASK (1U << 7U)
157#endif
158
159#if !defined(STM32_DMA2_CH1_CMASK)
160#define STM32_DMA2_CH1_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 0U))
161#endif
162
163#if !defined(STM32_DMA2_CH2_CMASK)
164#define STM32_DMA2_CH2_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 1U))
165#endif
166
167#if !defined(STM32_DMA2_CH3_CMASK)
168#define STM32_DMA2_CH3_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 2U))
169#endif
170
171#if !defined(STM32_DMA2_CH4_CMASK)
172#define STM32_DMA2_CH4_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 3U))
173#endif
174
175#if !defined(STM32_DMA2_CH5_CMASK)
176#define STM32_DMA2_CH5_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 4U))
177#endif
178
179#if !defined(STM32_DMA2_CH6_CMASK)
180#define STM32_DMA2_CH6_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 5U))
181#endif
182
183#if !defined(STM32_DMA2_CH7_CMASK)
184#define STM32_DMA2_CH7_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 6U))
185#endif
186
187#if !defined(STM32_DMA2_CH8_CMASK)
188#define STM32_DMA2_CH8_CMASK (1U << (STM32_DMA1_NUM_CHANNELS + 7U))
189#endif
190
191/*===========================================================================*/
192/* Driver exported variables. */
193/*===========================================================================*/
194
195/**
196 * @brief DMA streams descriptors.
197 * @details This table keeps the association between an unique stream
198 * identifier and the involved physical registers.
199 * @note Don't use this array directly, use the appropriate wrapper macros
200 * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc.
201 */
202const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
203#if STM32_DMA1_NUM_CHANNELS > 0
204 {DMA1, DMA1_Channel1, STM32_DMA1_CH1_CMASK, DMA1_CH1_VARIANT, 0, 0, STM32_DMA1_CH1_NUMBER},
205#endif
206#if STM32_DMA1_NUM_CHANNELS > 1
207 {DMA1, DMA1_Channel2, STM32_DMA1_CH2_CMASK, DMA1_CH2_VARIANT, 4, 1, STM32_DMA1_CH2_NUMBER},
208#endif
209#if STM32_DMA1_NUM_CHANNELS > 2
210 {DMA1, DMA1_Channel3, STM32_DMA1_CH3_CMASK, DMA1_CH3_VARIANT, 8, 2, STM32_DMA1_CH3_NUMBER},
211#endif
212#if STM32_DMA1_NUM_CHANNELS > 3
213 {DMA1, DMA1_Channel4, STM32_DMA1_CH4_CMASK, DMA1_CH4_VARIANT, 12, 3, STM32_DMA1_CH4_NUMBER},
214#endif
215#if STM32_DMA1_NUM_CHANNELS > 4
216 {DMA1, DMA1_Channel5, STM32_DMA1_CH5_CMASK, DMA1_CH5_VARIANT, 16, 4, STM32_DMA1_CH5_NUMBER},
217#endif
218#if STM32_DMA1_NUM_CHANNELS > 5
219 {DMA1, DMA1_Channel6, STM32_DMA1_CH6_CMASK, DMA1_CH6_VARIANT, 20, 5, STM32_DMA1_CH6_NUMBER},
220#endif
221#if STM32_DMA1_NUM_CHANNELS > 6
222 {DMA1, DMA1_Channel7, STM32_DMA1_CH7_CMASK, DMA1_CH7_VARIANT, 24, 6, STM32_DMA1_CH7_NUMBER},
223#endif
224#if STM32_DMA1_NUM_CHANNELS > 7
225 {DMA1, DMA1_Channel8, STM32_DMA1_CH8_CMASK, DMA1_CH8_VARIANT, 28, 7, STM32_DMA1_CH8_NUMBER},
226#endif
227#if STM32_DMA2_NUM_CHANNELS > 0
228 {DMA2, DMA2_Channel1, STM32_DMA2_CH1_CMASK, DMA2_CH1_VARIANT, 0, 0 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH1_NUMBER},
229#endif
230#if STM32_DMA2_NUM_CHANNELS > 1
231 {DMA2, DMA2_Channel2, STM32_DMA2_CH2_CMASK, DMA2_CH2_VARIANT, 4, 1 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH2_NUMBER},
232#endif
233#if STM32_DMA2_NUM_CHANNELS > 2
234 {DMA2, DMA2_Channel3, STM32_DMA2_CH3_CMASK, DMA2_CH3_VARIANT, 8, 2 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH3_NUMBER},
235#endif
236#if STM32_DMA2_NUM_CHANNELS > 3
237 {DMA2, DMA2_Channel4, STM32_DMA2_CH4_CMASK, DMA2_CH4_VARIANT, 12, 3 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH4_NUMBER},
238#endif
239#if STM32_DMA2_NUM_CHANNELS > 4
240 {DMA2, DMA2_Channel5, STM32_DMA2_CH5_CMASK, DMA2_CH5_VARIANT, 16, 4 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH5_NUMBER},
241#endif
242#if STM32_DMA2_NUM_CHANNELS > 5
243 {DMA2, DMA2_Channel6, STM32_DMA2_CH6_CMASK, DMA2_CH6_VARIANT, 20, 5 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH6_NUMBER},
244#endif
245#if STM32_DMA2_NUM_CHANNELS > 6
246 {DMA2, DMA2_Channel7, STM32_DMA2_CH7_CMASK, DMA2_CH7_VARIANT, 24, 6 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH7_NUMBER},
247#endif
248#if STM32_DMA2_NUM_CHANNELS > 7
249 {DMA2, DMA2_Channel8, STM32_DMA2_CH8_CMASK, DMA2_CH8_VARIANT, 28, 7 + STM32_DMA1_NUM_CHANNELS, STM32_DMA2_CH8_NUMBER},
250#endif
251};
252
253/*===========================================================================*/
254/* Driver local variables and types. */
255/*===========================================================================*/
256
257/**
258 * @brief Global DMA-related data structures.
259 */
260static struct {
261 /**
262 * @brief Mask of the allocated streams.
263 */
264 uint32_t allocated_mask;
265 /**
266 * @brief Mask of the enabled streams ISRs.
267 */
268 uint32_t isr_mask;
269 /**
270 * @brief DMA IRQ redirectors.
271 */
272 struct {
273 /**
274 * @brief DMA callback function.
275 */
276 stm32_dmaisr_t func;
277 /**
278 * @brief DMA callback parameter.
279 */
280 void *param;
281 } streams[STM32_DMA_STREAMS];
282} dma;
283
284/*===========================================================================*/
285/* Driver local functions. */
286/*===========================================================================*/
287
288/*===========================================================================*/
289/* Driver interrupt handlers. */
290/*===========================================================================*/
291
292#if defined(STM32_DMA1_CH1_HANDLER) || defined(__DOXYGEN__)
293/**
294 * @brief DMA1 stream 1 shared ISR.
295 *
296 * @isr
297 */
298OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) {
299
300 OSAL_IRQ_PROLOGUE();
301
302 dmaServeInterrupt(STM32_DMA1_STREAM1);
303
304 OSAL_IRQ_EPILOGUE();
305}
306#endif
307
308#if defined(STM32_DMA1_CH2_HANDLER) || defined(__DOXYGEN__)
309/**
310 * @brief DMA1 stream 2 shared ISR.
311 *
312 * @isr
313 */
314OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) {
315
316 OSAL_IRQ_PROLOGUE();
317
318 dmaServeInterrupt(STM32_DMA1_STREAM2);
319
320 OSAL_IRQ_EPILOGUE();
321}
322#endif
323
324#if defined(STM32_DMA1_CH3_HANDLER) || defined(__DOXYGEN__)
325/**
326 * @brief DMA1 stream 3 shared ISR.
327 *
328 * @isr
329 */
330OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) {
331
332 OSAL_IRQ_PROLOGUE();
333
334 dmaServeInterrupt(STM32_DMA1_STREAM3);
335
336 OSAL_IRQ_EPILOGUE();
337}
338#endif
339
340#if defined(STM32_DMA1_CH4_HANDLER) || defined(__DOXYGEN__)
341/**
342 * @brief DMA1 stream 4 shared ISR.
343 *
344 * @isr
345 */
346OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) {
347
348 OSAL_IRQ_PROLOGUE();
349
350 dmaServeInterrupt(STM32_DMA1_STREAM4);
351
352 OSAL_IRQ_EPILOGUE();
353}
354#endif
355
356#if defined(STM32_DMA1_CH5_HANDLER) || defined(__DOXYGEN__)
357/**
358 * @brief DMA1 stream 5 shared ISR.
359 *
360 * @isr
361 */
362OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) {
363
364 OSAL_IRQ_PROLOGUE();
365
366 dmaServeInterrupt(STM32_DMA1_STREAM5);
367
368 OSAL_IRQ_EPILOGUE();
369}
370#endif
371
372#if defined(STM32_DMA1_CH6_HANDLER) || defined(__DOXYGEN__)
373/**
374 * @brief DMA1 stream 6 shared ISR.
375 *
376 * @isr
377 */
378OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) {
379
380 OSAL_IRQ_PROLOGUE();
381
382 dmaServeInterrupt(STM32_DMA1_STREAM6);
383
384 OSAL_IRQ_EPILOGUE();
385}
386#endif
387
388#if defined(STM32_DMA1_CH7_HANDLER) || defined(__DOXYGEN__)
389/**
390 * @brief DMA1 stream 7 shared ISR.
391 *
392 * @isr
393 */
394OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) {
395
396 OSAL_IRQ_PROLOGUE();
397
398 dmaServeInterrupt(STM32_DMA1_STREAM7);
399
400 OSAL_IRQ_EPILOGUE();
401}
402#endif
403
404#if defined(STM32_DMA1_CH8_HANDLER) || defined(__DOXYGEN__)
405/**
406 * @brief DMA1 stream 8 shared ISR.
407 *
408 * @isr
409 */
410OSAL_IRQ_HANDLER(STM32_DMA1_CH8_HANDLER) {
411
412 OSAL_IRQ_PROLOGUE();
413
414 dmaServeInterrupt(STM32_DMA1_STREAM8);
415
416 OSAL_IRQ_EPILOGUE();
417}
418#endif
419
420#if defined(STM32_DMA2_CH1_HANDLER) || defined(__DOXYGEN__)
421/**
422 * @brief DMA2 stream 1 shared ISR.
423 *
424 * @isr
425 */
426OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) {
427
428 OSAL_IRQ_PROLOGUE();
429
430 dmaServeInterrupt(STM32_DMA2_STREAM1);
431
432 OSAL_IRQ_EPILOGUE();
433}
434#endif
435
436#if defined(STM32_DMA2_CH2_HANDLER) || defined(__DOXYGEN__)
437/**
438 * @brief DMA2 stream 2 shared ISR.
439 *
440 * @isr
441 */
442OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) {
443
444 OSAL_IRQ_PROLOGUE();
445
446 dmaServeInterrupt(STM32_DMA2_STREAM2);
447
448 OSAL_IRQ_EPILOGUE();
449}
450#endif
451
452#if defined(STM32_DMA2_CH3_HANDLER) || defined(__DOXYGEN__)
453/**
454 * @brief DMA2 stream 3 shared ISR.
455 *
456 * @isr
457 */
458OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) {
459
460 OSAL_IRQ_PROLOGUE();
461
462 dmaServeInterrupt(STM32_DMA2_STREAM3);
463
464 OSAL_IRQ_EPILOGUE();
465}
466#endif
467
468#if defined(STM32_DMA2_CH4_HANDLER) || defined(__DOXYGEN__)
469/**
470 * @brief DMA2 stream 4 shared ISR.
471 *
472 * @isr
473 */
474OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) {
475
476 OSAL_IRQ_PROLOGUE();
477
478 dmaServeInterrupt(STM32_DMA2_STREAM4);
479
480 OSAL_IRQ_EPILOGUE();
481}
482#endif
483
484#if defined(STM32_DMA2_CH5_HANDLER) || defined(__DOXYGEN__)
485/**
486 * @brief DMA2 stream 5 shared ISR.
487 *
488 * @isr
489 */
490OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) {
491
492 OSAL_IRQ_PROLOGUE();
493
494 dmaServeInterrupt(STM32_DMA2_STREAM5);
495
496 OSAL_IRQ_EPILOGUE();
497}
498#endif
499
500#if defined(STM32_DMA2_CH6_HANDLER) || defined(__DOXYGEN__)
501/**
502 * @brief DMA2 stream 6 shared ISR.
503 *
504 * @isr
505 */
506OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) {
507
508 OSAL_IRQ_PROLOGUE();
509
510 dmaServeInterrupt(STM32_DMA2_STREAM6);
511
512 OSAL_IRQ_EPILOGUE();
513}
514#endif
515
516#if defined(STM32_DMA2_CH7_HANDLER) || defined(__DOXYGEN__)
517/**
518 * @brief DMA2 stream 7 shared ISR.
519 *
520 * @isr
521 */
522OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) {
523
524 OSAL_IRQ_PROLOGUE();
525
526 dmaServeInterrupt(STM32_DMA2_STREAM7);
527
528 OSAL_IRQ_EPILOGUE();
529}
530#endif
531
532#if defined(STM32_DMA2_CH8_HANDLER) || defined(__DOXYGEN__)
533/**
534 * @brief DMA2 stream 8 shared ISR.
535 *
536 * @isr
537 */
538OSAL_IRQ_HANDLER(STM32_DMA2_CH8_HANDLER) {
539
540 OSAL_IRQ_PROLOGUE();
541
542 dmaServeInterrupt(STM32_DMA2_STREAM8);
543
544 OSAL_IRQ_EPILOGUE();
545}
546#endif
547
548/*===========================================================================*/
549/* Driver exported functions. */
550/*===========================================================================*/
551
552/**
553 * @brief STM32 DMA helper initialization.
554 *
555 * @init
556 */
557void dmaInit(void) {
558 int i;
559
560 dma.allocated_mask = 0U;
561 dma.isr_mask = 0U;
562 for (i = 0; i < STM32_DMA_STREAMS; i++) {
563 _stm32_dma_streams[i].channel->CCR = STM32_DMA_CCR_RESET_VALUE;
564 dma.streams[i].func = NULL;
565 }
566 DMA1->IFCR = 0xFFFFFFFFU;
567#if STM32_DMA2_NUM_CHANNELS > 0
568 DMA2->IFCR = 0xFFFFFFFFU;
569#endif
570}
571
572/**
573 * @brief Allocates a DMA stream.
574 * @details The stream is allocated and, if required, the DMA clock enabled.
575 * The function also enables the IRQ vector associated to the stream
576 * and initializes its priority.
577 *
578 * @param[in] id numeric identifiers of a specific stream or:
579 * - @p STM32_DMA_STREAM_ID_ANY for any stream.
580 * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
581 * on DMA1.
582 * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
583 * on DMA2.
584 * .
585 * @param[in] priority IRQ priority for the DMA stream
586 * @param[in] func handling function pointer, can be @p NULL
587 * @param[in] param a parameter to be passed to the handling function
588 * @return Pointer to the allocated @p stm32_dma_stream_t
589 * structure.
590 * @retval NULL if a/the stream is not available.
591 *
592 * @iclass
593 */
594const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id,
595 uint32_t priority,
596 stm32_dmaisr_t func,
597 void *param) {
598 uint32_t i, startid, endid;
599
600 osalDbgCheckClassI();
601
602 if (id < STM32_DMA_STREAMS) {
603 startid = id;
604 endid = id;
605 }
606#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
607 else if (id == STM32_DMA_STREAM_ID_ANY) {
608 startid = 0U;
609 endid = STM32_DMA_STREAMS - 1U;
610 }
611 else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) {
612 startid = 0U;
613 endid = STM32_DMA1_NUM_CHANNELS - 1U;
614 }
615#if STM32_DMA2_NUM_CHANNELS > 0
616 else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) {
617 startid = STM32_DMA1_NUM_CHANNELS;
618 endid = STM32_DMA_STREAMS - 1U;
619 }
620#endif
621#endif
622 else {
623 osalDbgCheck(false);
624 return NULL;
625 }
626
627 for (i = startid; i <= endid; i++) {
628 uint32_t mask = (1U << i);
629 if ((dma.allocated_mask & mask) == 0U) {
630 const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i);
631
632 /* Installs the DMA handler.*/
633 dma.streams[i].func = func;
634 dma.streams[i].param = param;
635 dma.allocated_mask |= mask;
636
637 /* Enabling DMA clocks required by the current streams set.*/
638 if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) {
639 rccEnableDMA1(true);
640 }
641#if STM32_DMA2_NUM_CHANNELS > 0
642 if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) {
643 rccEnableDMA2(true);
644 }
645#endif
646
647#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX)
648 /* Enabling DMAMUX if present.*/
649 if (dma.allocated_mask != 0U) {
650 rccEnableDMAMUX(true);
651 }
652#endif
653
654 /* Enables the associated IRQ vector if not already enabled and if a
655 callback is defined.*/
656 if (func != NULL) {
657 if ((dma.isr_mask & dmastp->cmask) == 0U) {
658 nvicEnableVector(dmastp->vector, priority);
659 }
660 dma.isr_mask |= mask;
661 }
662
663 /* Putting the stream in a known state.*/
664 dmaStreamDisable(dmastp);
665 dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE;
666
667 return dmastp;
668 }
669 }
670
671 return NULL;
672}
673
674/**
675 * @brief Allocates a DMA stream.
676 * @details The stream is allocated and, if required, the DMA clock enabled.
677 * The function also enables the IRQ vector associated to the stream
678 * and initializes its priority.
679 *
680 * @param[in] id numeric identifiers of a specific stream or:
681 * - @p STM32_DMA_STREAM_ID_ANY for any stream.
682 * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
683 * on DMA1.
684 * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
685 * on DMA2.
686 * .
687 * @param[in] priority IRQ priority for the DMA stream
688 * @param[in] func handling function pointer, can be @p NULL
689 * @param[in] param a parameter to be passed to the handling function
690 * @return Pointer to the allocated @p stm32_dma_stream_t
691 * structure.
692 * @retval NULL if a/the stream is not available.
693 *
694 * @api
695 */
696const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id,
697 uint32_t priority,
698 stm32_dmaisr_t func,
699 void *param) {
700 const stm32_dma_stream_t *dmastp;
701
702 osalSysLock();
703 dmastp = dmaStreamAllocI(id, priority, func, param);
704 osalSysUnlock();
705
706 return dmastp;
707}
708
709/**
710 * @brief Releases a DMA stream.
711 * @details The stream is freed and, if required, the DMA clock disabled.
712 * Trying to release a unallocated stream is an illegal operation
713 * and is trapped if assertions are enabled.
714 *
715 * @param[in] dmastp pointer to a stm32_dma_stream_t structure
716 *
717 * @iclass
718 */
719void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) {
720 uint32_t selfindex = (uint32_t)dmastp->selfindex;
721
722 osalDbgCheck(dmastp != NULL);
723
724 /* Check if the streams is not taken.*/
725 osalDbgAssert((dma.allocated_mask & (1 << selfindex)) != 0U,
726 "not allocated");
727
728 /* Marks the stream as not allocated.*/
729 dma.allocated_mask &= ~(1U << selfindex);
730 dma.isr_mask &= ~(1U << selfindex);
731
732 /* Disables the associated IRQ vector if it is no more in use.*/
733 if ((dma.isr_mask & dmastp->cmask) == 0U) {
734 nvicDisableVector(dmastp->vector);
735 }
736
737 /* Removes the DMA handler.*/
738 dma.streams[selfindex].func = NULL;
739 dma.streams[selfindex].param = NULL;
740
741 /* Shutting down clocks that are no more required, if any.*/
742 if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) {
743 rccDisableDMA1();
744 }
745#if STM32_DMA2_NUM_CHANNELS > 0
746 if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) {
747 rccDisableDMA2();
748 }
749#endif
750
751#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX)
752 /* Shutting down DMAMUX if present.*/
753 if (dma.allocated_mask == 0U) {
754 rccDisableDMAMUX();
755 }
756#endif
757}
758
759/**
760 * @brief Releases a DMA stream.
761 * @details The stream is freed and, if required, the DMA clock disabled.
762 * Trying to release a unallocated stream is an illegal operation
763 * and is trapped if assertions are enabled.
764 *
765 * @param[in] dmastp pointer to a stm32_dma_stream_t structure
766 *
767 * @api
768 */
769void dmaStreamFree(const stm32_dma_stream_t *dmastp) {
770
771 osalSysLock();
772 dmaStreamFreeI(dmastp);
773 osalSysUnlock();
774}
775
776/**
777 * @brief Serves a DMA IRQ.
778 *
779 * @param[in] dmastp pointer to a stm32_dma_stream_t structure
780 *
781 * @special
782 */
783void dmaServeInterrupt(const stm32_dma_stream_t *dmastp) {
784 uint32_t flags;
785 uint32_t selfindex = (uint32_t)dmastp->selfindex;
786
787 flags = (dmastp->dma->ISR >> dmastp->shift) & STM32_DMA_ISR_MASK;
788 if (flags & dmastp->channel->CCR) {
789 dmastp->dma->IFCR = flags << dmastp->shift;
790 if (dma.streams[selfindex].func) {
791 dma.streams[selfindex].func(dma.streams[selfindex].param, flags);
792 }
793 }
794}
795
796#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
797/**
798 * @brief Associates a peripheral request to a DMA stream.
799 * @note This function can be invoked in both ISR or thread context.
800 *
801 * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure
802 * @param[in] per peripheral identifier
803 *
804 * @special
805 */
806void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) {
807
808 osalDbgCheck(per < 256U);
809
810 dmastp->mux->CCR = per;
811}
812#endif
813
814#endif /* STM32_DMA_REQUIRED */
815
816/** @} */