diff options
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.c | 816 |
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 | */ | ||
202 | const 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 | */ | ||
260 | static 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 | */ | ||
298 | OSAL_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 | */ | ||
314 | OSAL_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 | */ | ||
330 | OSAL_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 | */ | ||
346 | OSAL_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 | */ | ||
362 | OSAL_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 | */ | ||
378 | OSAL_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 | */ | ||
394 | OSAL_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 | */ | ||
410 | OSAL_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 | */ | ||
426 | OSAL_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 | */ | ||
442 | OSAL_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 | */ | ||
458 | OSAL_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 | */ | ||
474 | OSAL_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 | */ | ||
490 | OSAL_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 | */ | ||
506 | OSAL_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 | */ | ||
522 | OSAL_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 | */ | ||
538 | OSAL_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 | */ | ||
557 | void 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 | */ | ||
594 | const 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 | */ | ||
696 | const 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 | */ | ||
719 | void 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 | */ | ||
769 | void 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 | */ | ||
783 | void 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 | */ | ||
806 | void 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 | /** @} */ | ||