diff options
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.c | 675 |
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 | */ | ||
103 | const 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 | */ | ||
129 | static 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 | */ | ||
162 | OSAL_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 | */ | ||
180 | OSAL_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 | */ | ||
198 | OSAL_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 | */ | ||
216 | OSAL_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 | */ | ||
234 | OSAL_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 | */ | ||
252 | OSAL_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 | */ | ||
270 | OSAL_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 | */ | ||
288 | OSAL_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 | */ | ||
306 | OSAL_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 | */ | ||
324 | OSAL_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 | */ | ||
342 | OSAL_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 | */ | ||
360 | OSAL_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 | */ | ||
378 | OSAL_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 | */ | ||
396 | OSAL_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 | */ | ||
414 | OSAL_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 | */ | ||
432 | OSAL_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 | */ | ||
454 | void 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 | */ | ||
490 | const 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 | */ | ||
585 | const 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 | */ | ||
608 | void 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 | */ | ||
648 | void 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 | */ | ||
665 | void 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 | /** @} */ | ||