1 /*
2 * Copyright (c) 2019 Song Qiang <songqiang1304521@gmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @brief DMA low level driver implementation for F2/F4/F7 series SoCs.
9 */
10
11 #include "dma_stm32.h"
12
13 #define LOG_LEVEL CONFIG_DMA_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(dma_stm32_v1);
16
17 /* DMA burst length */
18 #define BURST_TRANS_LENGTH_1 0
19
dma_stm32_id_to_stream(uint32_t id)20 uint32_t dma_stm32_id_to_stream(uint32_t id)
21 {
22 static const uint32_t stream_nr[] = {
23 LL_DMA_STREAM_0,
24 LL_DMA_STREAM_1,
25 LL_DMA_STREAM_2,
26 LL_DMA_STREAM_3,
27 LL_DMA_STREAM_4,
28 LL_DMA_STREAM_5,
29 LL_DMA_STREAM_6,
30 LL_DMA_STREAM_7,
31 };
32
33 __ASSERT_NO_MSG(id < ARRAY_SIZE(stream_nr));
34
35 return stream_nr[id];
36 }
37
38 #if !defined(CONFIG_DMAMUX_STM32)
dma_stm32_slot_to_channel(uint32_t slot)39 uint32_t dma_stm32_slot_to_channel(uint32_t slot)
40 {
41 static const uint32_t channel_nr[] = {
42 LL_DMA_CHANNEL_0,
43 LL_DMA_CHANNEL_1,
44 LL_DMA_CHANNEL_2,
45 LL_DMA_CHANNEL_3,
46 LL_DMA_CHANNEL_4,
47 LL_DMA_CHANNEL_5,
48 LL_DMA_CHANNEL_6,
49 LL_DMA_CHANNEL_7,
50 };
51
52 __ASSERT_NO_MSG(slot < ARRAY_SIZE(channel_nr));
53
54 return channel_nr[slot];
55 }
56 #endif
57
dma_stm32_clear_ht(DMA_TypeDef * DMAx,uint32_t id)58 void dma_stm32_clear_ht(DMA_TypeDef *DMAx, uint32_t id)
59 {
60 static const dma_stm32_clear_flag_func func[] = {
61 LL_DMA_ClearFlag_HT0,
62 LL_DMA_ClearFlag_HT1,
63 LL_DMA_ClearFlag_HT2,
64 LL_DMA_ClearFlag_HT3,
65 LL_DMA_ClearFlag_HT4,
66 LL_DMA_ClearFlag_HT5,
67 LL_DMA_ClearFlag_HT6,
68 LL_DMA_ClearFlag_HT7,
69 };
70
71 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
72
73 func[id](DMAx);
74 }
75
dma_stm32_clear_tc(DMA_TypeDef * DMAx,uint32_t id)76 void dma_stm32_clear_tc(DMA_TypeDef *DMAx, uint32_t id)
77 {
78 static const dma_stm32_clear_flag_func func[] = {
79 LL_DMA_ClearFlag_TC0,
80 LL_DMA_ClearFlag_TC1,
81 LL_DMA_ClearFlag_TC2,
82 LL_DMA_ClearFlag_TC3,
83 LL_DMA_ClearFlag_TC4,
84 LL_DMA_ClearFlag_TC5,
85 LL_DMA_ClearFlag_TC6,
86 LL_DMA_ClearFlag_TC7,
87 };
88
89 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
90
91 func[id](DMAx);
92 }
93
dma_stm32_is_ht_active(DMA_TypeDef * DMAx,uint32_t id)94 bool dma_stm32_is_ht_active(DMA_TypeDef *DMAx, uint32_t id)
95 {
96 static const dma_stm32_check_flag_func func[] = {
97 LL_DMA_IsActiveFlag_HT0,
98 LL_DMA_IsActiveFlag_HT1,
99 LL_DMA_IsActiveFlag_HT2,
100 LL_DMA_IsActiveFlag_HT3,
101 LL_DMA_IsActiveFlag_HT4,
102 LL_DMA_IsActiveFlag_HT5,
103 LL_DMA_IsActiveFlag_HT6,
104 LL_DMA_IsActiveFlag_HT7,
105 };
106
107 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
108
109 return func[id](DMAx);
110 }
111
dma_stm32_is_tc_active(DMA_TypeDef * DMAx,uint32_t id)112 bool dma_stm32_is_tc_active(DMA_TypeDef *DMAx, uint32_t id)
113 {
114 static const dma_stm32_check_flag_func func[] = {
115 LL_DMA_IsActiveFlag_TC0,
116 LL_DMA_IsActiveFlag_TC1,
117 LL_DMA_IsActiveFlag_TC2,
118 LL_DMA_IsActiveFlag_TC3,
119 LL_DMA_IsActiveFlag_TC4,
120 LL_DMA_IsActiveFlag_TC5,
121 LL_DMA_IsActiveFlag_TC6,
122 LL_DMA_IsActiveFlag_TC7,
123 };
124
125 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
126
127 return func[id](DMAx);
128 }
129
dma_stm32_clear_te(DMA_TypeDef * DMAx,uint32_t id)130 void dma_stm32_clear_te(DMA_TypeDef *DMAx, uint32_t id)
131 {
132 static const dma_stm32_clear_flag_func func[] = {
133 LL_DMA_ClearFlag_TE0,
134 LL_DMA_ClearFlag_TE1,
135 LL_DMA_ClearFlag_TE2,
136 LL_DMA_ClearFlag_TE3,
137 LL_DMA_ClearFlag_TE4,
138 LL_DMA_ClearFlag_TE5,
139 LL_DMA_ClearFlag_TE6,
140 LL_DMA_ClearFlag_TE7,
141 };
142
143 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
144
145 func[id](DMAx);
146 }
147
dma_stm32_clear_dme(DMA_TypeDef * DMAx,uint32_t id)148 void dma_stm32_clear_dme(DMA_TypeDef *DMAx, uint32_t id)
149 {
150 static const dma_stm32_clear_flag_func func[] = {
151 LL_DMA_ClearFlag_DME0,
152 LL_DMA_ClearFlag_DME1,
153 LL_DMA_ClearFlag_DME2,
154 LL_DMA_ClearFlag_DME3,
155 LL_DMA_ClearFlag_DME4,
156 LL_DMA_ClearFlag_DME5,
157 LL_DMA_ClearFlag_DME6,
158 LL_DMA_ClearFlag_DME7,
159 };
160
161 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
162
163 func[id](DMAx);
164 }
165
dma_stm32_clear_fe(DMA_TypeDef * DMAx,uint32_t id)166 void dma_stm32_clear_fe(DMA_TypeDef *DMAx, uint32_t id)
167 {
168 static const dma_stm32_clear_flag_func func[] = {
169 LL_DMA_ClearFlag_FE0,
170 LL_DMA_ClearFlag_FE1,
171 LL_DMA_ClearFlag_FE2,
172 LL_DMA_ClearFlag_FE3,
173 LL_DMA_ClearFlag_FE4,
174 LL_DMA_ClearFlag_FE5,
175 LL_DMA_ClearFlag_FE6,
176 LL_DMA_ClearFlag_FE7,
177 };
178
179 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
180
181 func[id](DMAx);
182 }
183
dma_stm32_is_te_active(DMA_TypeDef * DMAx,uint32_t id)184 bool dma_stm32_is_te_active(DMA_TypeDef *DMAx, uint32_t id)
185 {
186 static const dma_stm32_check_flag_func func[] = {
187 LL_DMA_IsActiveFlag_TE0,
188 LL_DMA_IsActiveFlag_TE1,
189 LL_DMA_IsActiveFlag_TE2,
190 LL_DMA_IsActiveFlag_TE3,
191 LL_DMA_IsActiveFlag_TE4,
192 LL_DMA_IsActiveFlag_TE5,
193 LL_DMA_IsActiveFlag_TE6,
194 LL_DMA_IsActiveFlag_TE7,
195 };
196
197 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
198
199 return func[id](DMAx);
200 }
201
dma_stm32_is_dme_active(DMA_TypeDef * DMAx,uint32_t id)202 bool dma_stm32_is_dme_active(DMA_TypeDef *DMAx, uint32_t id)
203 {
204 static const dma_stm32_check_flag_func func[] = {
205 LL_DMA_IsActiveFlag_DME0,
206 LL_DMA_IsActiveFlag_DME1,
207 LL_DMA_IsActiveFlag_DME2,
208 LL_DMA_IsActiveFlag_DME3,
209 LL_DMA_IsActiveFlag_DME4,
210 LL_DMA_IsActiveFlag_DME5,
211 LL_DMA_IsActiveFlag_DME6,
212 LL_DMA_IsActiveFlag_DME7,
213 };
214
215 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
216
217 return func[id](DMAx);
218 }
219
dma_stm32_is_fe_active(DMA_TypeDef * DMAx,uint32_t id)220 bool dma_stm32_is_fe_active(DMA_TypeDef *DMAx, uint32_t id)
221 {
222 static const dma_stm32_check_flag_func func[] = {
223 LL_DMA_IsActiveFlag_FE0,
224 LL_DMA_IsActiveFlag_FE1,
225 LL_DMA_IsActiveFlag_FE2,
226 LL_DMA_IsActiveFlag_FE3,
227 LL_DMA_IsActiveFlag_FE4,
228 LL_DMA_IsActiveFlag_FE5,
229 LL_DMA_IsActiveFlag_FE6,
230 LL_DMA_IsActiveFlag_FE7,
231 };
232
233 __ASSERT_NO_MSG(id < ARRAY_SIZE(func));
234
235 return func[id](DMAx);
236 }
237
stm32_dma_dump_stream_irq(DMA_TypeDef * dma,uint32_t id)238 void stm32_dma_dump_stream_irq(DMA_TypeDef *dma, uint32_t id)
239 {
240 LOG_INF("tc: %d, ht: %d, te: %d, dme: %d, fe: %d",
241 dma_stm32_is_tc_active(dma, id),
242 dma_stm32_is_ht_active(dma, id),
243 dma_stm32_is_te_active(dma, id),
244 dma_stm32_is_dme_active(dma, id),
245 dma_stm32_is_fe_active(dma, id));
246 }
247
stm32_dma_is_tc_irq_active(DMA_TypeDef * dma,uint32_t id)248 inline bool stm32_dma_is_tc_irq_active(DMA_TypeDef *dma, uint32_t id)
249 {
250 return LL_DMA_IsEnabledIT_TC(dma, dma_stm32_id_to_stream(id)) &&
251 dma_stm32_is_tc_active(dma, id);
252 }
253
stm32_dma_is_ht_irq_active(DMA_TypeDef * dma,uint32_t id)254 inline bool stm32_dma_is_ht_irq_active(DMA_TypeDef *dma, uint32_t id)
255 {
256 return LL_DMA_IsEnabledIT_HT(dma, dma_stm32_id_to_stream(id)) &&
257 dma_stm32_is_ht_active(dma, id);
258 }
259
stm32_dma_is_te_irq_active(DMA_TypeDef * dma,uint32_t id)260 static inline bool stm32_dma_is_te_irq_active(DMA_TypeDef *dma, uint32_t id)
261 {
262 return LL_DMA_IsEnabledIT_TE(dma, dma_stm32_id_to_stream(id)) &&
263 dma_stm32_is_te_active(dma, id);
264 }
265
stm32_dma_is_dme_irq_active(DMA_TypeDef * dma,uint32_t id)266 static inline bool stm32_dma_is_dme_irq_active(DMA_TypeDef *dma, uint32_t id)
267 {
268 return LL_DMA_IsEnabledIT_DME(dma, dma_stm32_id_to_stream(id)) &&
269 dma_stm32_is_dme_active(dma, id);
270 }
271
stm32_dma_is_fe_irq_active(DMA_TypeDef * dma,uint32_t id)272 static inline bool stm32_dma_is_fe_irq_active(DMA_TypeDef *dma, uint32_t id)
273 {
274 return LL_DMA_IsEnabledIT_FE(dma, dma_stm32_id_to_stream(id)) &&
275 dma_stm32_is_fe_active(dma, id);
276 }
277
stm32_dma_is_irq_active(DMA_TypeDef * dma,uint32_t id)278 bool stm32_dma_is_irq_active(DMA_TypeDef *dma, uint32_t id)
279 {
280 return stm32_dma_is_tc_irq_active(dma, id) ||
281 stm32_dma_is_ht_irq_active(dma, id) ||
282 stm32_dma_is_te_irq_active(dma, id) ||
283 stm32_dma_is_dme_irq_active(dma, id) ||
284 stm32_dma_is_fe_irq_active(dma, id);
285 }
286
stm32_dma_clear_stream_irq(DMA_TypeDef * dma,uint32_t id)287 void stm32_dma_clear_stream_irq(DMA_TypeDef *dma, uint32_t id)
288 {
289 dma_stm32_clear_te(dma, id);
290 dma_stm32_clear_dme(dma, id);
291 dma_stm32_clear_fe(dma, id);
292 }
293
stm32_dma_is_irq_happened(DMA_TypeDef * dma,uint32_t id)294 bool stm32_dma_is_irq_happened(DMA_TypeDef *dma, uint32_t id)
295 {
296 if (LL_DMA_IsEnabledIT_FE(dma, dma_stm32_id_to_stream(id)) &&
297 dma_stm32_is_fe_active(dma, id)) {
298 return true;
299 }
300
301 return false;
302 }
303
stm32_dma_is_unexpected_irq_happened(DMA_TypeDef * dma,uint32_t id)304 bool stm32_dma_is_unexpected_irq_happened(DMA_TypeDef *dma, uint32_t id)
305 {
306 if (LL_DMA_IsEnabledIT_FE(dma, dma_stm32_id_to_stream(id)) &&
307 dma_stm32_is_fe_active(dma, id)) {
308 LOG_ERR("FiFo error.");
309 stm32_dma_dump_stream_irq(dma, id);
310 stm32_dma_clear_stream_irq(dma, id);
311
312 return true;
313 }
314
315 return false;
316 }
317
stm32_dma_enable_stream(DMA_TypeDef * dma,uint32_t id)318 void stm32_dma_enable_stream(DMA_TypeDef *dma, uint32_t id)
319 {
320 LL_DMA_EnableStream(dma, dma_stm32_id_to_stream(id));
321 }
322
stm32_dma_is_enabled_stream(DMA_TypeDef * dma,uint32_t id)323 bool stm32_dma_is_enabled_stream(DMA_TypeDef *dma, uint32_t id)
324 {
325 if (LL_DMA_IsEnabledStream(dma, dma_stm32_id_to_stream(id)) == 1) {
326 return true;
327 }
328 return false;
329 }
330
stm32_dma_disable_stream(DMA_TypeDef * dma,uint32_t id)331 int stm32_dma_disable_stream(DMA_TypeDef *dma, uint32_t id)
332 {
333 LL_DMA_DisableStream(dma, dma_stm32_id_to_stream(id));
334
335 while (stm32_dma_is_enabled_stream(dma, id)) {
336 }
337
338 dma_stm32_clear_tc(dma, id);
339
340 return 0;
341 }
342
stm32_dma_disable_fifo_irq(DMA_TypeDef * dma,uint32_t id)343 void stm32_dma_disable_fifo_irq(DMA_TypeDef *dma, uint32_t id)
344 {
345 LL_DMA_DisableIT_FE(dma, dma_stm32_id_to_stream(id));
346 }
347
348 #if !defined(CONFIG_DMAMUX_STM32)
stm32_dma_config_channel_function(DMA_TypeDef * dma,uint32_t id,uint32_t slot)349 void stm32_dma_config_channel_function(DMA_TypeDef *dma, uint32_t id,
350 uint32_t slot)
351 {
352 LL_DMA_SetChannelSelection(dma, dma_stm32_id_to_stream(id),
353 dma_stm32_slot_to_channel(slot));
354 }
355 #endif
356
stm32_dma_get_mburst(struct dma_config * config,bool source_periph)357 uint32_t stm32_dma_get_mburst(struct dma_config *config, bool source_periph)
358 {
359 uint32_t memory_burst;
360
361 if (source_periph) {
362 memory_burst = config->dest_burst_length;
363 } else {
364 memory_burst = config->source_burst_length;
365 }
366
367 switch (memory_burst) {
368 case 1:
369 return LL_DMA_MBURST_SINGLE;
370 case 4:
371 return LL_DMA_MBURST_INC4;
372 case 8:
373 return LL_DMA_MBURST_INC8;
374 case 16:
375 return LL_DMA_MBURST_INC16;
376 default:
377 LOG_ERR("Memory burst size error,"
378 "using single burst as default");
379 return LL_DMA_MBURST_SINGLE;
380 }
381 }
382
stm32_dma_get_pburst(struct dma_config * config,bool source_periph)383 uint32_t stm32_dma_get_pburst(struct dma_config *config, bool source_periph)
384 {
385 uint32_t periph_burst;
386
387 if (source_periph) {
388 periph_burst = config->source_burst_length;
389 } else {
390 periph_burst = config->dest_burst_length;
391 }
392
393 switch (periph_burst) {
394 case 1:
395 return LL_DMA_PBURST_SINGLE;
396 case 4:
397 return LL_DMA_PBURST_INC4;
398 case 8:
399 return LL_DMA_PBURST_INC8;
400 case 16:
401 return LL_DMA_PBURST_INC16;
402 default:
403 LOG_ERR("Peripheral burst size error,"
404 "using single burst as default");
405 return LL_DMA_PBURST_SINGLE;
406 }
407 }
408
409 /*
410 * This function checks if the msize, mburst and fifo level is
411 * compatible. If they are not compatible, refer to the 'FIFO'
412 * section in the 'DMA' chapter in the Reference Manual for more
413 * information.
414 * This function does not have the obligation of checking the parameters.
415 */
stm32_dma_check_fifo_mburst(LL_DMA_InitTypeDef * DMAx)416 bool stm32_dma_check_fifo_mburst(LL_DMA_InitTypeDef *DMAx)
417 {
418 uint32_t msize = DMAx->MemoryOrM2MDstDataSize;
419 uint32_t fifo_level = DMAx->FIFOThreshold;
420 uint32_t mburst = DMAx->MemBurst;
421
422 switch (msize) {
423 case LL_DMA_MDATAALIGN_BYTE:
424 switch (mburst) {
425 case LL_DMA_MBURST_INC4:
426 return true;
427 case LL_DMA_MBURST_INC8:
428 if (fifo_level == LL_DMA_FIFOTHRESHOLD_1_2 ||
429 fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
430 return true;
431 }
432 break;
433 case LL_DMA_MBURST_INC16:
434 if (fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
435 return true;
436 }
437 break;
438 }
439 break;
440 case LL_DMA_MDATAALIGN_HALFWORD:
441 switch (mburst) {
442 case LL_DMA_MBURST_INC4:
443 if (fifo_level == LL_DMA_FIFOTHRESHOLD_1_2 ||
444 fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
445 return true;
446 }
447 break;
448 case LL_DMA_MBURST_INC8:
449 if (fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
450 return true;
451 }
452 break;
453 }
454 break;
455 case LL_DMA_MDATAALIGN_WORD:
456 if (mburst == LL_DMA_MBURST_INC4 &&
457 fifo_level == LL_DMA_FIFOTHRESHOLD_FULL) {
458 return true;
459 }
460 }
461
462 /* Other combinations are forbidden. */
463 return false;
464 }
465
stm32_dma_get_fifo_threshold(uint16_t fifo_mode_control)466 uint32_t stm32_dma_get_fifo_threshold(uint16_t fifo_mode_control)
467 {
468 switch (fifo_mode_control) {
469 case 0:
470 return LL_DMA_FIFOTHRESHOLD_1_4;
471 case 1:
472 return LL_DMA_FIFOTHRESHOLD_1_2;
473 case 2:
474 return LL_DMA_FIFOTHRESHOLD_3_4;
475 case 3:
476 return LL_DMA_FIFOTHRESHOLD_FULL;
477 default:
478 LOG_WRN("FIFO threshold parameter error, reset to 1/4");
479 return LL_DMA_FIFOTHRESHOLD_1_4;
480 }
481 }
482