aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c')
-rw-r--r--lib/chibios/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c675
1 files changed, 675 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c b/lib/chibios/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c
new file mode 100644
index 000000000..eab184a20
--- /dev/null
+++ b/lib/chibios/os/hal/ports/STM32/LLD/DMAv2/stm32_dma.c
@@ -0,0 +1,675 @@
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 DMAv2/stm32_dma.c
19 * @brief Enhanced 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.allocated_mask.
44 */
45#define STM32_DMA1_STREAMS_MASK 0x000000FFU
46
47/**
48 * @brief Mask of the DMA2 streams in @p dma.allocated_mask.
49 */
50#define STM32_DMA2_STREAMS_MASK 0x0000FF00U
51
52#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
53
54#define DMA1_CH0_VARIANT DMAMUX1_Channel0
55#define DMA1_CH1_VARIANT DMAMUX1_Channel1
56#define DMA1_CH2_VARIANT DMAMUX1_Channel2
57#define DMA1_CH3_VARIANT DMAMUX1_Channel3
58#define DMA1_CH4_VARIANT DMAMUX1_Channel4
59#define DMA1_CH5_VARIANT DMAMUX1_Channel5
60#define DMA1_CH6_VARIANT DMAMUX1_Channel6
61#define DMA1_CH7_VARIANT DMAMUX1_Channel7
62#define DMA2_CH0_VARIANT DMAMUX1_Channel8
63#define DMA2_CH1_VARIANT DMAMUX1_Channel9
64#define DMA2_CH2_VARIANT DMAMUX1_Channel10
65#define DMA2_CH3_VARIANT DMAMUX1_Channel11
66#define DMA2_CH4_VARIANT DMAMUX1_Channel12
67#define DMA2_CH5_VARIANT DMAMUX1_Channel13
68#define DMA2_CH6_VARIANT DMAMUX1_Channel14
69#define DMA2_CH7_VARIANT DMAMUX1_Channel15
70
71#else /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
72
73#define DMA1_CH0_VARIANT 0
74#define DMA1_CH1_VARIANT 0
75#define DMA1_CH2_VARIANT 0
76#define DMA1_CH3_VARIANT 0
77#define DMA1_CH4_VARIANT 0
78#define DMA1_CH5_VARIANT 0
79#define DMA1_CH6_VARIANT 0
80#define DMA1_CH7_VARIANT 0
81#define DMA2_CH0_VARIANT 0
82#define DMA2_CH1_VARIANT 0
83#define DMA2_CH2_VARIANT 0
84#define DMA2_CH3_VARIANT 0
85#define DMA2_CH4_VARIANT 0
86#define DMA2_CH5_VARIANT 0
87#define DMA2_CH6_VARIANT 0
88#define DMA2_CH7_VARIANT 0
89
90#endif /* !(STM32_DMA_SUPPORTS_DMAMUX == TRUE) */
91
92/*===========================================================================*/
93/* Driver exported variables. */
94/*===========================================================================*/
95
96/**
97 * @brief DMA streams descriptors.
98 * @details This table keeps the association between an unique stream
99 * identifier and the involved physical registers.
100 * @note Don't use this array directly, use the appropriate wrapper macros
101 * instead: @p STM32_DMA1_STREAM0, @p STM32_DMA1_STREAM1 etc.
102 */
103const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
104 {DMA1_Stream0, &DMA1->LIFCR, DMA1_CH0_VARIANT, 0, 0, STM32_DMA1_CH0_NUMBER},
105 {DMA1_Stream1, &DMA1->LIFCR, DMA1_CH1_VARIANT, 6, 1, STM32_DMA1_CH1_NUMBER},
106 {DMA1_Stream2, &DMA1->LIFCR, DMA1_CH2_VARIANT, 16, 2, STM32_DMA1_CH2_NUMBER},
107 {DMA1_Stream3, &DMA1->LIFCR, DMA1_CH3_VARIANT, 22, 3, STM32_DMA1_CH3_NUMBER},
108 {DMA1_Stream4, &DMA1->HIFCR, DMA1_CH4_VARIANT, 0, 4, STM32_DMA1_CH4_NUMBER},
109 {DMA1_Stream5, &DMA1->HIFCR, DMA1_CH5_VARIANT, 6, 5, STM32_DMA1_CH5_NUMBER},
110 {DMA1_Stream6, &DMA1->HIFCR, DMA1_CH6_VARIANT, 16, 6, STM32_DMA1_CH6_NUMBER},
111 {DMA1_Stream7, &DMA1->HIFCR, DMA1_CH7_VARIANT, 22, 7, STM32_DMA1_CH7_NUMBER},
112 {DMA2_Stream0, &DMA2->LIFCR, DMA2_CH0_VARIANT, 0, 8, STM32_DMA2_CH0_NUMBER},
113 {DMA2_Stream1, &DMA2->LIFCR, DMA2_CH1_VARIANT, 6, 9, STM32_DMA2_CH1_NUMBER},
114 {DMA2_Stream2, &DMA2->LIFCR, DMA2_CH2_VARIANT, 16, 10, STM32_DMA2_CH2_NUMBER},
115 {DMA2_Stream3, &DMA2->LIFCR, DMA2_CH3_VARIANT, 22, 11, STM32_DMA2_CH3_NUMBER},
116 {DMA2_Stream4, &DMA2->HIFCR, DMA2_CH4_VARIANT, 0, 12, STM32_DMA2_CH4_NUMBER},
117 {DMA2_Stream5, &DMA2->HIFCR, DMA2_CH5_VARIANT, 6, 13, STM32_DMA2_CH5_NUMBER},
118 {DMA2_Stream6, &DMA2->HIFCR, DMA2_CH6_VARIANT, 16, 14, STM32_DMA2_CH6_NUMBER},
119 {DMA2_Stream7, &DMA2->HIFCR, DMA2_CH7_VARIANT, 22, 15, STM32_DMA2_CH7_NUMBER},
120};
121
122/*===========================================================================*/
123/* Driver local variables and types. */
124/*===========================================================================*/
125
126/**
127 * @brief Global DMA-related data structures.
128 */
129static struct {
130 /**
131 * @brief Mask of the allocated streams.
132 */
133 uint32_t allocated_mask;
134 /**
135 * @brief DMA IRQ redirectors.
136 */
137 struct {
138 /**
139 * @brief DMA callback function.
140 */
141 stm32_dmaisr_t func;
142 /**
143 * @brief DMA callback parameter.
144 */
145 void *param;
146 } streams[STM32_DMA_STREAMS];
147} dma;
148
149/*===========================================================================*/
150/* Driver local functions. */
151/*===========================================================================*/
152
153/*===========================================================================*/
154/* Driver interrupt handlers. */
155/*===========================================================================*/
156
157/**
158 * @brief DMA1 stream 0 shared interrupt handler.
159 *
160 * @isr
161 */
162OSAL_IRQ_HANDLER(STM32_DMA1_CH0_HANDLER) {
163 uint32_t flags;
164
165 OSAL_IRQ_PROLOGUE();
166
167 flags = (DMA1->LISR >> 0U) & STM32_DMA_ISR_MASK;
168 DMA1->LIFCR = flags << 0U;
169 if (dma.streams[0].func)
170 dma.streams[0].func(dma.streams[0].param, flags);
171
172 OSAL_IRQ_EPILOGUE();
173}
174
175/**
176 * @brief DMA1 stream 1 shared interrupt handler.
177 *
178 * @isr
179 */
180OSAL_IRQ_HANDLER(STM32_DMA1_CH1_HANDLER) {
181 uint32_t flags;
182
183 OSAL_IRQ_PROLOGUE();
184
185 flags = (DMA1->LISR >> 6U) & STM32_DMA_ISR_MASK;
186 DMA1->LIFCR = flags << 6U;
187 if (dma.streams[1].func)
188 dma.streams[1].func(dma.streams[1].param, flags);
189
190 OSAL_IRQ_EPILOGUE();
191}
192
193/**
194 * @brief DMA1 stream 2 shared interrupt handler.
195 *
196 * @isr
197 */
198OSAL_IRQ_HANDLER(STM32_DMA1_CH2_HANDLER) {
199 uint32_t flags;
200
201 OSAL_IRQ_PROLOGUE();
202
203 flags = (DMA1->LISR >> 16U) & STM32_DMA_ISR_MASK;
204 DMA1->LIFCR = flags << 16U;
205 if (dma.streams[2].func)
206 dma.streams[2].func(dma.streams[2].param, flags);
207
208 OSAL_IRQ_EPILOGUE();
209}
210
211/**
212 * @brief DMA1 stream 3 shared interrupt handler.
213 *
214 * @isr
215 */
216OSAL_IRQ_HANDLER(STM32_DMA1_CH3_HANDLER) {
217 uint32_t flags;
218
219 OSAL_IRQ_PROLOGUE();
220
221 flags = (DMA1->LISR >> 22U) & STM32_DMA_ISR_MASK;
222 DMA1->LIFCR = flags << 22U;
223 if (dma.streams[3].func)
224 dma.streams[3].func(dma.streams[3].param, flags);
225
226 OSAL_IRQ_EPILOGUE();
227}
228
229/**
230 * @brief DMA1 stream 4 shared interrupt handler.
231 *
232 * @isr
233 */
234OSAL_IRQ_HANDLER(STM32_DMA1_CH4_HANDLER) {
235 uint32_t flags;
236
237 OSAL_IRQ_PROLOGUE();
238
239 flags = (DMA1->HISR >> 0U) & STM32_DMA_ISR_MASK;
240 DMA1->HIFCR = flags << 0U;
241 if (dma.streams[4].func)
242 dma.streams[4].func(dma.streams[4].param, flags);
243
244 OSAL_IRQ_EPILOGUE();
245}
246
247/**
248 * @brief DMA1 stream 5 shared interrupt handler.
249 *
250 * @isr
251 */
252OSAL_IRQ_HANDLER(STM32_DMA1_CH5_HANDLER) {
253 uint32_t flags;
254
255 OSAL_IRQ_PROLOGUE();
256
257 flags = (DMA1->HISR >> 6U) & STM32_DMA_ISR_MASK;
258 DMA1->HIFCR = flags << 6U;
259 if (dma.streams[5].func)
260 dma.streams[5].func(dma.streams[5].param, flags);
261
262 OSAL_IRQ_EPILOGUE();
263}
264
265/**
266 * @brief DMA1 stream 6 shared interrupt handler.
267 *
268 * @isr
269 */
270OSAL_IRQ_HANDLER(STM32_DMA1_CH6_HANDLER) {
271 uint32_t flags;
272
273 OSAL_IRQ_PROLOGUE();
274
275 flags = (DMA1->HISR >> 16U) & STM32_DMA_ISR_MASK;
276 DMA1->HIFCR = flags << 16U;
277 if (dma.streams[6].func)
278 dma.streams[6].func(dma.streams[6].param, flags);
279
280 OSAL_IRQ_EPILOGUE();
281}
282
283/**
284 * @brief DMA1 stream 7 shared interrupt handler.
285 *
286 * @isr
287 */
288OSAL_IRQ_HANDLER(STM32_DMA1_CH7_HANDLER) {
289 uint32_t flags;
290
291 OSAL_IRQ_PROLOGUE();
292
293 flags = (DMA1->HISR >> 22U) & STM32_DMA_ISR_MASK;
294 DMA1->HIFCR = flags << 22U;
295 if (dma.streams[7].func)
296 dma.streams[7].func(dma.streams[7].param, flags);
297
298 OSAL_IRQ_EPILOGUE();
299}
300
301/**
302 * @brief DMA2 stream 0 shared interrupt handler.
303 *
304 * @isr
305 */
306OSAL_IRQ_HANDLER(STM32_DMA2_CH0_HANDLER) {
307 uint32_t flags;
308
309 OSAL_IRQ_PROLOGUE();
310
311 flags = (DMA2->LISR >> 0U) & STM32_DMA_ISR_MASK;
312 DMA2->LIFCR = flags << 0U;
313 if (dma.streams[8].func)
314 dma.streams[8].func(dma.streams[8].param, flags);
315
316 OSAL_IRQ_EPILOGUE();
317}
318
319/**
320 * @brief DMA2 stream 1 shared interrupt handler.
321 *
322 * @isr
323 */
324OSAL_IRQ_HANDLER(STM32_DMA2_CH1_HANDLER) {
325 uint32_t flags;
326
327 OSAL_IRQ_PROLOGUE();
328
329 flags = (DMA2->LISR >> 6U) & STM32_DMA_ISR_MASK;
330 DMA2->LIFCR = flags << 6U;
331 if (dma.streams[9].func)
332 dma.streams[9].func(dma.streams[9].param, flags);
333
334 OSAL_IRQ_EPILOGUE();
335}
336
337/**
338 * @brief DMA2 stream 2 shared interrupt handler.
339 *
340 * @isr
341 */
342OSAL_IRQ_HANDLER(STM32_DMA2_CH2_HANDLER) {
343 uint32_t flags;
344
345 OSAL_IRQ_PROLOGUE();
346
347 flags = (DMA2->LISR >> 16U) & STM32_DMA_ISR_MASK;
348 DMA2->LIFCR = flags << 16U;
349 if (dma.streams[10].func)
350 dma.streams[10].func(dma.streams[10].param, flags);
351
352 OSAL_IRQ_EPILOGUE();
353}
354
355/**
356 * @brief DMA2 stream 3 shared interrupt handler.
357 *
358 * @isr
359 */
360OSAL_IRQ_HANDLER(STM32_DMA2_CH3_HANDLER) {
361 uint32_t flags;
362
363 OSAL_IRQ_PROLOGUE();
364
365 flags = (DMA2->LISR >> 22U) & STM32_DMA_ISR_MASK;
366 DMA2->LIFCR = flags << 22U;
367 if (dma.streams[11].func)
368 dma.streams[11].func(dma.streams[11].param, flags);
369
370 OSAL_IRQ_EPILOGUE();
371}
372
373/**
374 * @brief DMA2 stream 4 shared interrupt handler.
375 *
376 * @isr
377 */
378OSAL_IRQ_HANDLER(STM32_DMA2_CH4_HANDLER) {
379 uint32_t flags;
380
381 OSAL_IRQ_PROLOGUE();
382
383 flags = (DMA2->HISR >> 0U) & STM32_DMA_ISR_MASK;
384 DMA2->HIFCR = flags << 0U;
385 if (dma.streams[12].func)
386 dma.streams[12].func(dma.streams[12].param, flags);
387
388 OSAL_IRQ_EPILOGUE();
389}
390
391/**
392 * @brief DMA2 stream 5 shared interrupt handler.
393 *
394 * @isr
395 */
396OSAL_IRQ_HANDLER(STM32_DMA2_CH5_HANDLER) {
397 uint32_t flags;
398
399 OSAL_IRQ_PROLOGUE();
400
401 flags = (DMA2->HISR >> 6U) & STM32_DMA_ISR_MASK;
402 DMA2->HIFCR = flags << 6U;
403 if (dma.streams[13].func)
404 dma.streams[13].func(dma.streams[13].param, flags);
405
406 OSAL_IRQ_EPILOGUE();
407}
408
409/**
410 * @brief DMA2 stream 6 shared interrupt handler.
411 *
412 * @isr
413 */
414OSAL_IRQ_HANDLER(STM32_DMA2_CH6_HANDLER) {
415 uint32_t flags;
416
417 OSAL_IRQ_PROLOGUE();
418
419 flags = (DMA2->HISR >> 16U) & STM32_DMA_ISR_MASK;
420 DMA2->HIFCR = flags << 16U;
421 if (dma.streams[14].func)
422 dma.streams[14].func(dma.streams[14].param, flags);
423
424 OSAL_IRQ_EPILOGUE();
425}
426
427/**
428 * @brief DMA2 stream 7 shared interrupt handler.
429 *
430 * @isr
431 */
432OSAL_IRQ_HANDLER(STM32_DMA2_CH7_HANDLER) {
433 uint32_t flags;
434
435 OSAL_IRQ_PROLOGUE();
436
437 flags = (DMA2->HISR >> 22U) & STM32_DMA_ISR_MASK;
438 DMA2->HIFCR = flags << 22U;
439 if (dma.streams[15].func)
440 dma.streams[15].func(dma.streams[15].param, flags);
441
442 OSAL_IRQ_EPILOGUE();
443}
444
445/*===========================================================================*/
446/* Driver exported functions. */
447/*===========================================================================*/
448
449/**
450 * @brief STM32 DMA helper initialization.
451 *
452 * @init
453 */
454void dmaInit(void) {
455 unsigned i;
456
457 dma.allocated_mask = 0U;
458 for (i = 0U; i < STM32_DMA_STREAMS; i++) {
459 _stm32_dma_streams[i].stream->CR = STM32_DMA_CR_RESET_VALUE;
460 dma.streams[i].func = NULL;
461 }
462 DMA1->LIFCR = 0xFFFFFFFFU;
463 DMA1->HIFCR = 0xFFFFFFFFU;
464 DMA2->LIFCR = 0xFFFFFFFFU;
465 DMA2->HIFCR = 0xFFFFFFFFU;
466}
467
468/**
469 * @brief Allocates a DMA stream.
470 * @details The stream is allocated and, if required, the DMA clock enabled.
471 * The function also enables the IRQ vector associated to the stream
472 * and initializes its priority.
473 *
474 * @param[in] id numeric identifiers of a specific stream or:
475 * - @p STM32_DMA_STREAM_ID_ANY for any stream.
476 * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
477 * on DMA1.
478 * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
479 * on DMA2.
480 * .
481 * @param[in] priority IRQ priority for the DMA stream
482 * @param[in] func handling function pointer, can be @p NULL
483 * @param[in] param a parameter to be passed to the handling function
484 * @return Pointer to the allocated @p stm32_dma_stream_t
485 * structure.
486 * @retval NULL if a/the stream is not available.
487 *
488 * @iclass
489 */
490const stm32_dma_stream_t *dmaStreamAllocI(uint32_t id,
491 uint32_t priority,
492 stm32_dmaisr_t func,
493 void *param) {
494 uint32_t i, startid, endid;
495
496 osalDbgCheckClassI();
497
498 if (id < STM32_DMA_STREAMS) {
499 startid = id;
500 endid = id;
501 }
502#if STM32_DMA_SUPPORTS_DMAMUX == TRUE
503 else if (id == STM32_DMA_STREAM_ID_ANY) {
504 startid = 0U;
505 endid = STM32_DMA_STREAMS - 1U;
506 }
507 else if (id == STM32_DMA_STREAM_ID_ANY_DMA1) {
508 startid = 0U;
509 endid = (STM32_DMA_STREAMS / 2U) - 1U;
510 }
511 else if (id == STM32_DMA_STREAM_ID_ANY_DMA2) {
512 startid = (STM32_DMA_STREAMS / 2U) - 1U;
513 endid = STM32_DMA_STREAMS - 1U;
514 }
515#endif
516 else {
517 osalDbgCheck(false);
518 return NULL;
519 }
520
521 for (i = startid; i <= endid; i++) {
522 uint32_t mask = (1U << i);
523 if ((dma.allocated_mask & mask) == 0U) {
524 const stm32_dma_stream_t *dmastp = STM32_DMA_STREAM(i);
525
526 /* Installs the DMA handler.*/
527 dma.streams[i].func = func;
528 dma.streams[i].param = param;
529 dma.allocated_mask |= mask;
530
531 /* Enabling DMA clocks required by the current streams set.*/
532 if ((STM32_DMA1_STREAMS_MASK & mask) != 0U) {
533 rccEnableDMA1(true);
534 }
535 if ((STM32_DMA2_STREAMS_MASK & mask) != 0U) {
536 rccEnableDMA2(true);
537 }
538
539#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccEnableDMAMUX)
540 /* Enabling DMAMUX if present.*/
541 if (dma.allocated_mask != 0U) {
542 rccEnableDMAMUX(true);
543 }
544#endif
545
546 /* Putting the stream in a safe state.*/
547 dmaStreamDisable(dmastp);
548 dmastp->stream->CR = STM32_DMA_CR_RESET_VALUE;
549 dmastp->stream->FCR = STM32_DMA_FCR_RESET_VALUE;
550
551 /* Enables the associated IRQ vector if a callback is defined.*/
552 if (func != NULL) {
553 nvicEnableVector(dmastp->vector, priority);
554 }
555
556 return dmastp;
557 }
558 }
559
560 return NULL;
561}
562
563/**
564 * @brief Allocates a DMA stream.
565 * @details The stream is allocated and, if required, the DMA clock enabled.
566 * The function also enables the IRQ vector associated to the stream
567 * and initializes its priority.
568 *
569 * @param[in] id numeric identifiers of a specific stream or:
570 * - @p STM32_DMA_STREAM_ID_ANY for any stream.
571 * - @p STM32_DMA_STREAM_ID_ANY_DMA1 for any stream
572 * on DMA1.
573 * - @p STM32_DMA_STREAM_ID_ANY_DMA2 for any stream
574 * on DMA2.
575 * .
576 * @param[in] priority IRQ priority for the DMA stream
577 * @param[in] func handling function pointer, can be @p NULL
578 * @param[in] param a parameter to be passed to the handling function
579 * @return Pointer to the allocated @p stm32_dma_stream_t
580 * structure.
581 * @retval NULL if a/the stream is not available.
582 *
583 * @api
584 */
585const stm32_dma_stream_t *dmaStreamAlloc(uint32_t id,
586 uint32_t priority,
587 stm32_dmaisr_t func,
588 void *param) {
589 const stm32_dma_stream_t *dmastp;
590
591 osalSysLock();
592 dmastp = dmaStreamAllocI(id, priority, func, param);
593 osalSysUnlock();
594
595 return dmastp;
596}
597
598/**
599 * @brief Releases a DMA stream.
600 * @details The stream is freed and, if required, the DMA clock disabled.
601 * Trying to release a unallocated stream is an illegal operation
602 * and is trapped if assertions are enabled.
603 *
604 * @param[in] dmastp pointer to a stm32_dma_stream_t structure
605 *
606 * @iclass
607 */
608void dmaStreamFreeI(const stm32_dma_stream_t *dmastp) {
609
610 osalDbgCheck(dmastp != NULL);
611
612 /* Check if the streams is not taken.*/
613 osalDbgAssert((dma.allocated_mask & (1U << dmastp->selfindex)) != 0U,
614 "not allocated");
615
616 /* Disables the associated IRQ vector.*/
617 nvicDisableVector(dmastp->vector);
618
619 /* Marks the stream as not allocated.*/
620 dma.allocated_mask &= ~(1U << dmastp->selfindex);
621
622 /* Shutting down clocks that are no more required, if any.*/
623 if ((dma.allocated_mask & STM32_DMA1_STREAMS_MASK) == 0U) {
624 rccDisableDMA1();
625 }
626 if ((dma.allocated_mask & STM32_DMA2_STREAMS_MASK) == 0U) {
627 rccDisableDMA2();
628 }
629
630#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) && defined(rccDisableDMAMUX)
631 /* Shutting down DMAMUX if present.*/
632 if (dma.allocated_mask == 0U) {
633 rccDisableDMAMUX();
634 }
635#endif
636}
637
638/**
639 * @brief Releases a DMA stream.
640 * @details The stream is freed and, if required, the DMA clock disabled.
641 * Trying to release a unallocated stream is an illegal operation
642 * and is trapped if assertions are enabled.
643 *
644 * @param[in] dmastp pointer to a stm32_dma_stream_t structure
645 *
646 * @api
647 */
648void dmaStreamFree(const stm32_dma_stream_t *dmastp) {
649
650 osalSysLock();
651 dmaStreamFreeI(dmastp);
652 osalSysUnlock();
653}
654
655#if (STM32_DMA_SUPPORTS_DMAMUX == TRUE) || defined(__DOXYGEN__)
656/**
657 * @brief Associates a peripheral request to a DMA stream.
658 * @note This function can be invoked in both ISR or thread context.
659 *
660 * @param[in] dmastp pointer to a @p stm32_dma_stream_t structure
661 * @param[in] per peripheral identifier
662 *
663 * @special
664 */
665void dmaSetRequestSource(const stm32_dma_stream_t *dmastp, uint32_t per) {
666
667 osalDbgCheck(per < 256U);
668
669 dmastp->mux->CCR = per;
670}
671#endif
672
673#endif /* STM32_DMA_REQUIRED */
674
675/** @} */