1 /**
2 ******************************************************************************
3 * @file stm32c0xx_hal_dma.c
4 * @author MCD Application Team
5 * @brief DMA HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the Direct Memory Access (DMA) peripheral:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral State and errors functions
11 ******************************************************************************
12 * @attention
13 *
14 * Copyright (c) 2022 STMicroelectronics.
15 * All rights reserved.
16 *
17 * This software is licensed under terms that can be found in the LICENSE file
18 * in the root directory of this software component.
19 * If no LICENSE file comes with this software, it is provided AS-IS.
20 *
21 ******************************************************************************
22 @verbatim
23 ==============================================================================
24 ##### How to use this driver #####
25 ==============================================================================
26 [..]
27 (#) Enable and configure the peripheral to be connected to the DMA Channel
28 (except for internal SRAM / FLASH memories: no initialization is
29 necessary). Please refer to the Reference manual for connection between peripherals
30 and DMA requests.
31
32 (#) For a given Channel, program the required configuration through the following parameters:
33 Channel request, Transfer Direction, Source and Destination data formats,
34 Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
35 using HAL_DMA_Init() function.
36
37 Prior to HAL_DMA_Init the CLK shall be enabled for both DMA & DMAMUX
38 thanks to:
39 DMA1 : __HAL_RCC_DMA1_CLK_ENABLE();
40
41 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
42 detection.
43
44 (#) Use HAL_DMA_Abort() function to abort the current transfer
45
46 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
47 *** Polling mode IO operation ***
48 =================================
49 [..]
50 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
51 address and destination address and the Length of data to be transferred
52 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
53 case a fixed Timeout can be configured by User depending from his application.
54
55 *** Interrupt mode IO operation ***
56 ===================================
57 [..]
58 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
59 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
60 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
61 Source address and destination address and the Length of data to be transferred.
62 In this case the DMA interrupt is configured
63 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
64 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
65 add his own function by customization of function pointer XferCpltCallback and
66 XferErrorCallback (i.e. a member of DMA handle structure).
67
68 *** DMA HAL driver macros list ***
69 =============================================
70 [..]
71 Below the list of most used macros in DMA HAL driver.
72
73 (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
74 (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
75 (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
76 (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
77 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
78 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
79 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not.
80
81 [..]
82 (@) You can refer to the DMA HAL driver header file for more useful macros
83
84 @endverbatim
85 ******************************************************************************
86 */
87
88 /* Includes ------------------------------------------------------------------*/
89 #include "stm32c0xx_hal.h"
90
91 /** @addtogroup STM32C0xx_HAL_Driver
92 * @{
93 */
94
95 /** @defgroup DMA DMA
96 * @brief DMA HAL module driver
97 * @{
98 */
99
100 #ifdef HAL_DMA_MODULE_ENABLED
101
102 /* Private typedef -----------------------------------------------------------*/
103 /* Private define ------------------------------------------------------------*/
104 /* Private macro -------------------------------------------------------------*/
105 /* Private variables ---------------------------------------------------------*/
106 /* Private function prototypes -----------------------------------------------*/
107
108 /** @defgroup DMA_Private_Functions DMA Private Functions
109 * @{
110 */
111 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
112 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
113 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
114
115 /**
116 * @}
117 */
118
119 /* Exported functions ---------------------------------------------------------*/
120
121 /** @defgroup DMA_Exported_Functions DMA Exported Functions
122 * @{
123 */
124
125 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
126 * @brief Initialization and de-initialization functions
127 *
128 @verbatim
129 ===============================================================================
130 ##### Initialization and de-initialization functions #####
131 ===============================================================================
132 [..]
133 This section provides functions allowing to initialize the DMA Channel source
134 and destination addresses, incrementation and data sizes, transfer direction,
135 circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
136 [..]
137 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
138 reference manual.
139
140 @endverbatim
141 * @{
142 */
143
144 /**
145 * @brief Initialize the DMA according to the specified
146 * parameters in the DMA_InitTypeDef and initialize the associated handle.
147 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
148 * the configuration information for the specified DMA Channel.
149 * @retval HAL status
150 */
HAL_DMA_Init(DMA_HandleTypeDef * hdma)151 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
152 {
153 /* Check the DMA handle allocation */
154 if (hdma == NULL)
155 {
156 return HAL_ERROR;
157 }
158
159 /* Check the parameters */
160 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
161 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
162 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
163 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
164 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
165 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
166 assert_param(IS_DMA_MODE(hdma->Init.Mode));
167 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
168
169 /* calculation of the channel index */
170 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - \
171 (uint32_t)DMA1_Channel1)) << 2U;
172
173 /* Change DMA peripheral state */
174 hdma->State = HAL_DMA_STATE_BUSY;
175
176 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
177 CLEAR_BIT(hdma->Instance->CCR, (DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \
178 DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \
179 DMA_CCR_DIR | DMA_CCR_MEM2MEM));
180
181 /* Set the DMA Channel configuration */
182 SET_BIT(hdma->Instance->CCR, (hdma->Init.Direction | \
183 hdma->Init.PeriphInc | hdma->Init.MemInc | \
184 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | \
185 hdma->Init.Mode | hdma->Init.Priority));
186
187 /* Initialize parameters for DMAMUX channel :
188 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
189 */
190 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
191
192 if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
193 {
194 /* if memory to memory force the request to 0*/
195 hdma->Init.Request = DMA_REQUEST_MEM2MEM;
196 }
197
198 /* Set peripheral request to DMAMUX channel */
199 hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
200
201 /* Clear the DMAMUX synchro overrun flag */
202 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
203
204 if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
205 {
206 /* Initialize parameters for DMAMUX request generator :
207 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
208 */
209 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
210
211 /* Reset the DMAMUX request generator register*/
212 hdma->DMAmuxRequestGen->RGCR = 0U;
213
214 /* Clear the DMAMUX request generator overrun flag */
215 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
216 }
217 else
218 {
219 hdma->DMAmuxRequestGen = 0U;
220 hdma->DMAmuxRequestGenStatus = 0U;
221 hdma->DMAmuxRequestGenStatusMask = 0U;
222 }
223
224 /* Initialize the error code */
225 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
226
227 /* Initialize the DMA state*/
228 hdma->State = HAL_DMA_STATE_READY;
229
230 /* Release Lock */
231 __HAL_UNLOCK(hdma);
232
233 return HAL_OK;
234 }
235
236 /**
237 * @brief DeInitialize the DMA peripheral.
238 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
239 * the configuration information for the specified DMA Channel.
240 * @retval HAL status
241 */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)242 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
243 {
244 /* Check the DMA handle allocation */
245 if (NULL == hdma)
246 {
247 return HAL_ERROR;
248 }
249
250 /* Check the parameters */
251 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
252
253 /* Disable the selected DMA Channelx */
254 __HAL_DMA_DISABLE(hdma);
255
256 /* calculation of the channel index */
257 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - \
258 (uint32_t)DMA1_Channel1)) << 2U;
259
260 /* Reset DMA Channel control register */
261 hdma->Instance->CCR = 0U;
262
263 /* Clear all flags */
264 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
265
266 /* Initialize parameters for DMAMUX channel :
267 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
268
269 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
270
271 /* Reset the DMAMUX channel that corresponds to the DMA channel */
272 hdma->DMAmuxChannel->CCR = 0U;
273
274 /* Clear the DMAMUX synchro overrun flag */
275 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
276
277 /* Reset Request generator parameters if any */
278 if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
279 {
280 /* Initialize parameters for DMAMUX request generator :
281 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
282 */
283 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
284
285 /* Reset the DMAMUX request generator register*/
286 hdma->DMAmuxRequestGen->RGCR = 0U;
287
288 /* Clear the DMAMUX request generator overrun flag */
289 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
290 }
291
292 /* Clean callbacks */
293 hdma->XferCpltCallback = NULL;
294 hdma->XferHalfCpltCallback = NULL;
295 hdma->XferErrorCallback = NULL;
296 hdma->XferAbortCallback = NULL;
297
298 hdma->DMAmuxRequestGen = 0U;
299 hdma->DMAmuxRequestGenStatus = 0U;
300 hdma->DMAmuxRequestGenStatusMask = 0U;
301
302 /* Initialize the error code */
303 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
304
305 /* Initialize the DMA state */
306 hdma->State = HAL_DMA_STATE_RESET;
307
308 /* Release Lock */
309 __HAL_UNLOCK(hdma);
310
311 return HAL_OK;
312 }
313
314 /**
315 * @}
316 */
317
318 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
319 * @brief Input and Output operation functions
320 *
321 @verbatim
322 ===============================================================================
323 ##### IO operation functions #####
324 ===============================================================================
325 [..] This section provides functions allowing to:
326 (+) Configure the source, destination address and data length and Start DMA transfer
327 (+) Configure the source, destination address and data length and
328 Start DMA transfer with interrupt
329 (+) Abort DMA transfer
330 (+) Poll for transfer complete
331 (+) Handle DMA interrupt request
332
333 @endverbatim
334 * @{
335 */
336
337 /**
338 * @brief Start the DMA Transfer.
339 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
340 * the configuration information for the specified DMA Channel.
341 * @param SrcAddress The source memory Buffer address
342 * @param DstAddress The destination memory Buffer address
343 * @param DataLength The length of data to be transferred from source to destination
344 * @retval HAL status
345 */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)346 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
347 {
348 HAL_StatusTypeDef status = HAL_OK;
349
350 /* Check the parameters */
351 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
352
353 /* Process locked */
354 __HAL_LOCK(hdma);
355
356 if (HAL_DMA_STATE_READY == hdma->State)
357 {
358 /* Change DMA peripheral state */
359 hdma->State = HAL_DMA_STATE_BUSY;
360 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
361
362 /* Disable the peripheral */
363 __HAL_DMA_DISABLE(hdma);
364
365 /* Configure the source, destination address and the data length & clear flags*/
366 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
367
368 /* Enable the Peripheral */
369 __HAL_DMA_ENABLE(hdma);
370 }
371 else
372 {
373 /* Process Unlocked */
374 __HAL_UNLOCK(hdma);
375 status = HAL_BUSY;
376 }
377
378 /* Process locked */
379 __HAL_UNLOCK(hdma);
380
381 return status;
382 }
383
384 /**
385 * @brief Start the DMA Transfer with interrupt enabled.
386 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
387 * the configuration information for the specified DMA Channel.
388 * @param SrcAddress The source memory Buffer address
389 * @param DstAddress The destination memory Buffer address
390 * @param DataLength The length of data to be transferred from source to destination
391 * @retval HAL status
392 */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)393 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress,
394 uint32_t DataLength)
395 {
396 HAL_StatusTypeDef status = HAL_OK;
397
398 /* Check the parameters */
399 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
400
401 /* Process locked */
402 __HAL_LOCK(hdma);
403
404 if (HAL_DMA_STATE_READY == hdma->State)
405 {
406 /* Change DMA peripheral state */
407 hdma->State = HAL_DMA_STATE_BUSY;
408 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
409
410 /* Disable the peripheral */
411 __HAL_DMA_DISABLE(hdma);
412
413 /* Configure the source, destination address and the data length & clear flags*/
414 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
415
416 /* Enable the transfer complete interrupt */
417 /* Enable the transfer Error interrupt */
418 if (NULL != hdma->XferHalfCpltCallback)
419 {
420 /* Enable the Half transfer complete interrupt as well */
421 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
422 }
423 else
424 {
425 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
426 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
427 }
428
429 /* Check if DMAMUX Synchronization is enabled*/
430 if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
431 {
432 /* Enable DMAMUX sync overrun IT*/
433 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
434 }
435
436 if (hdma->DMAmuxRequestGen != 0U)
437 {
438 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
439 /* enable the request gen overrun IT*/
440 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
441 }
442
443 /* Enable the Peripheral */
444 __HAL_DMA_ENABLE(hdma);
445 }
446 else
447 {
448 /* Process Unlocked */
449 __HAL_UNLOCK(hdma);
450
451 /* Remain BUSY */
452 status = HAL_BUSY;
453 }
454
455 /* Process unlocked */
456 __HAL_UNLOCK(hdma);
457
458 return status;
459 }
460
461 /**
462 * @brief Abort the DMA Transfer.
463 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
464 * the configuration information for the specified DMA Channel.
465 * @retval HAL status
466 */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)467 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
468 {
469 /* Check the DMA peripheral handle */
470 if (NULL == hdma)
471 {
472 return HAL_ERROR;
473 }
474
475 /* Check the DMA peripheral state */
476 if (hdma->State != HAL_DMA_STATE_BUSY)
477 {
478 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
479
480 /* Process Unlocked */
481 __HAL_UNLOCK(hdma);
482
483 return HAL_ERROR;
484 }
485 else
486 {
487 /* Disable DMA IT */
488 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
489
490 /* disable the DMAMUX sync overrun IT*/
491 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
492
493 /* Disable the channel */
494 __HAL_DMA_DISABLE(hdma);
495
496 /* Clear all flags */
497 __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
498
499 /* Clear the DMAMUX synchro overrun flag */
500 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
501
502 if (hdma->DMAmuxRequestGen != 0U)
503 {
504 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
505 /* disable the request gen overrun IT*/
506 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
507
508 /* Clear the DMAMUX request generator overrun flag */
509 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
510 }
511
512 /* Change the DMA state */
513 hdma->State = HAL_DMA_STATE_READY;
514
515 /* Process Unlocked */
516 __HAL_UNLOCK(hdma);
517 }
518
519 return HAL_OK;
520 }
521
522 /**
523 * @brief Aborts the DMA Transfer in Interrupt mode.
524 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
525 * the configuration information for the specified DMA Stream.
526 * @retval HAL status
527 */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)528 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
529 {
530 HAL_StatusTypeDef status = HAL_OK;
531
532 /* Process Unlocked/locked */
533 __HAL_UNLOCK(hdma);
534 __HAL_LOCK(hdma);
535
536 if (HAL_DMA_STATE_BUSY != hdma->State)
537 {
538 /* no transfer ongoing */
539 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
540
541 status = HAL_ERROR;
542 }
543 else
544 {
545 /* Disable DMA IT */
546 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
547
548 /* Disable the channel */
549 __HAL_DMA_DISABLE(hdma);
550
551 /* disable the DMAMUX sync overrun IT*/
552 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
553
554 /* Clear all flags */
555 __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
556
557 /* Clear the DMAMUX synchro overrun flag */
558 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
559
560 if (hdma->DMAmuxRequestGen != 0U)
561 {
562 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
563 /* disable the request gen overrun IT*/
564 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
565
566 /* Clear the DMAMUX request generator overrun flag */
567 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
568 }
569
570 /* Change the DMA state */
571 hdma->State = HAL_DMA_STATE_READY;
572
573 /* Process Unlocked */
574 __HAL_UNLOCK(hdma);
575
576 /* Call User Abort callback */
577 if (hdma->XferAbortCallback != NULL)
578 {
579 hdma->XferAbortCallback(hdma);
580 }
581 }
582 return status;
583 }
584
585 /**
586 * @brief Polling for transfer complete.
587 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
588 * the configuration information for the specified DMA Channel.
589 * @param CompleteLevel Specifies the DMA level complete.
590 * @param Timeout Timeout duration.
591 * @retval HAL status
592 */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)593 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel,
594 uint32_t Timeout)
595 {
596 uint32_t temp;
597 uint32_t tickstart;
598
599 /* Process unlocked */
600 __HAL_UNLOCK(hdma);
601
602 if (HAL_DMA_STATE_BUSY != hdma->State)
603 {
604 /* no transfer ongoing */
605 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
606 __HAL_UNLOCK(hdma);
607 return HAL_ERROR;
608 }
609
610 /* Polling mode not supported in circular mode */
611 if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
612 {
613 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
614 return HAL_ERROR;
615 }
616
617 /* Get the level transfer complete flag */
618 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
619 {
620 /* Transfer Complete flag */
621 temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
622 }
623 else
624 {
625 /* Half Transfer Complete flag */
626 temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU);
627 }
628
629 /* Get tick */
630 tickstart = HAL_GetTick();
631
632 while (0U == __HAL_DMA_GET_FLAG(hdma, temp))
633 {
634 if (0U != __HAL_DMA_GET_FLAG(hdma, (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))))
635 {
636 /* When a DMA transfer error occurs */
637 /* A hardware clear of its EN bits is performed */
638 /* Clear all flags */
639 __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
640
641 /* Update error code */
642 hdma->ErrorCode = HAL_DMA_ERROR_TE;
643
644 /* Change the DMA state */
645 hdma->State = HAL_DMA_STATE_READY;
646
647 /* Process Unlocked */
648 __HAL_UNLOCK(hdma);
649
650 return HAL_ERROR;
651 }
652 /* Check for the Timeout */
653 if (Timeout != HAL_MAX_DELAY)
654 {
655 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
656 {
657 /* Update error code */
658 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
659
660 /* Change the DMA state */
661 hdma->State = HAL_DMA_STATE_READY;
662
663 /* Process Unlocked */
664 __HAL_UNLOCK(hdma);
665
666 return HAL_ERROR;
667 }
668 }
669 }
670
671 /*Check for DMAMUX Request generator (if used) overrun status */
672 if (hdma->DMAmuxRequestGen != 0U)
673 {
674 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
675 if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
676 {
677 /* Disable the request gen overrun interrupt */
678 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
679
680 /* Clear the DMAMUX request generator overrun flag */
681 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
682
683 /* Update error code */
684 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
685 }
686 }
687
688 /* Check for DMAMUX Synchronization overrun */
689 if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
690 {
691 /* Clear the DMAMUX synchro overrun flag */
692 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
693
694 /* Update error code */
695 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
696 }
697
698 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
699 {
700 /* Clear the transfer complete flag */
701 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)));
702
703 /* The selected Channelx EN bit is cleared (DMA is disabled and
704 all transfers are complete) */
705 hdma->State = HAL_DMA_STATE_READY;
706 }
707 else
708 {
709 /* Clear the half transfer complete flag */
710 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU)));
711 }
712
713 /* Process unlocked */
714 __HAL_UNLOCK(hdma);
715
716 return HAL_OK;
717 }
718
719 /**
720 * @brief Handle DMA interrupt request.
721 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
722 * the configuration information for the specified DMA Channel.
723 * @retval None
724 */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)725 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
726 {
727 uint32_t flag_it = DMA1->ISR;
728 uint32_t source_it = hdma->Instance->CCR;
729
730 /* Half Transfer Complete Interrupt management ******************************/
731 if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
732 {
733 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
734 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
735 {
736 /* Disable the half transfer interrupt */
737 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
738 }
739 /* Clear the half transfer complete flag */
740 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU)));
741
742 /* DMA peripheral state is not updated in Half Transfer */
743 /* but in Transfer Complete case */
744
745 if (hdma->XferHalfCpltCallback != NULL)
746 {
747 /* Half transfer callback */
748 hdma->XferHalfCpltCallback(hdma);
749 }
750 }
751
752 /* Transfer Complete Interrupt management ***********************************/
753 else if ((0U != (flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)))) && (0U != (source_it & DMA_IT_TC)))
754 {
755 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
756 {
757 /* Disable the transfer complete and error interrupt */
758 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
759
760 /* Change the DMA state */
761 hdma->State = HAL_DMA_STATE_READY;
762 }
763 /* Clear the transfer complete flag */
764 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)));
765
766 /* Process Unlocked */
767 __HAL_UNLOCK(hdma);
768
769 if (hdma->XferCpltCallback != NULL)
770 {
771 /* Transfer complete callback */
772 hdma->XferCpltCallback(hdma);
773 }
774 }
775
776 /* Transfer Error Interrupt management **************************************/
777 else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
778 {
779 /* When a DMA transfer error occurs */
780 /* A hardware clear of its EN bits is performed */
781 /* Disable ALL DMA IT */
782 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
783
784 /* Clear all flags */
785 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
786
787 /* Update error code */
788 hdma->ErrorCode = HAL_DMA_ERROR_TE;
789
790 /* Change the DMA state */
791 hdma->State = HAL_DMA_STATE_READY;
792
793 /* Process Unlocked */
794 __HAL_UNLOCK(hdma);
795
796 if (hdma->XferErrorCallback != NULL)
797 {
798 /* Transfer error callback */
799 hdma->XferErrorCallback(hdma);
800 }
801 }
802 else
803 {
804 /* Nothing To Do */
805 }
806 return;
807 }
808
809 /**
810 * @brief Register callbacks
811 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
812 * the configuration information for the specified DMA Stream.
813 * @param CallbackID User Callback identifier
814 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
815 * @param pCallback pointer to private callback function which has pointer to
816 * a DMA_HandleTypeDef structure as parameter.
817 * @retval HAL status
818 */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))819 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID,
820 void (* pCallback)(DMA_HandleTypeDef *_hdma))
821 {
822 HAL_StatusTypeDef status = HAL_OK;
823
824 /* Process locked */
825 __HAL_LOCK(hdma);
826
827 if (HAL_DMA_STATE_READY == hdma->State)
828 {
829 switch (CallbackID)
830 {
831 case HAL_DMA_XFER_CPLT_CB_ID:
832 hdma->XferCpltCallback = pCallback;
833 break;
834
835 case HAL_DMA_XFER_HALFCPLT_CB_ID:
836 hdma->XferHalfCpltCallback = pCallback;
837 break;
838
839 case HAL_DMA_XFER_ERROR_CB_ID:
840 hdma->XferErrorCallback = pCallback;
841 break;
842
843 case HAL_DMA_XFER_ABORT_CB_ID:
844 hdma->XferAbortCallback = pCallback;
845 break;
846
847 default:
848 status = HAL_ERROR;
849 break;
850 }
851 }
852 else
853 {
854 status = HAL_ERROR;
855 }
856
857 /* Release Lock */
858 __HAL_UNLOCK(hdma);
859
860 return status;
861 }
862
863 /**
864 * @brief UnRegister callbacks
865 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
866 * the configuration information for the specified DMA Stream.
867 * @param CallbackID User Callback identifier
868 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
869 * @retval HAL status
870 */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)871 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
872 {
873 HAL_StatusTypeDef status = HAL_OK;
874
875 /* Process locked */
876 __HAL_LOCK(hdma);
877
878 if (HAL_DMA_STATE_READY == hdma->State)
879 {
880 switch (CallbackID)
881 {
882 case HAL_DMA_XFER_CPLT_CB_ID:
883 hdma->XferCpltCallback = NULL;
884 break;
885
886 case HAL_DMA_XFER_HALFCPLT_CB_ID:
887 hdma->XferHalfCpltCallback = NULL;
888 break;
889
890 case HAL_DMA_XFER_ERROR_CB_ID:
891 hdma->XferErrorCallback = NULL;
892 break;
893
894 case HAL_DMA_XFER_ABORT_CB_ID:
895 hdma->XferAbortCallback = NULL;
896 break;
897
898 case HAL_DMA_XFER_ALL_CB_ID:
899 hdma->XferCpltCallback = NULL;
900 hdma->XferHalfCpltCallback = NULL;
901 hdma->XferErrorCallback = NULL;
902 hdma->XferAbortCallback = NULL;
903 break;
904
905 default:
906 status = HAL_ERROR;
907 break;
908 }
909 }
910 else
911 {
912 status = HAL_ERROR;
913 }
914
915 /* Release Lock */
916 __HAL_UNLOCK(hdma);
917
918 return status;
919 }
920
921 /**
922 * @}
923 */
924
925
926
927 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
928 * @brief Peripheral State and Errors functions
929 *
930 @verbatim
931 ===============================================================================
932 ##### Peripheral State and Errors functions #####
933 ===============================================================================
934 [..]
935 This subsection provides functions allowing to
936 (+) Check the DMA state
937 (+) Get error code
938
939 @endverbatim
940 * @{
941 */
942
943 /**
944 * @brief Return the DMA handle state.
945 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
946 * the configuration information for the specified DMA Channel.
947 * @retval HAL state
948 */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)949 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
950 {
951 /* Return DMA handle state */
952 return hdma->State;
953 }
954
955 /**
956 * @brief Return the DMA error code.
957 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
958 * the configuration information for the specified DMA Channel.
959 * @retval DMA Error Code
960 */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)961 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
962 {
963 return hdma->ErrorCode;
964 }
965
966 /**
967 * @}
968 */
969
970 /**
971 * @}
972 */
973
974 /** @addtogroup DMA_Private_Functions
975 * @{
976 */
977
978 /**
979 * @brief Sets the DMA Transfer parameter.
980 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
981 * the configuration information for the specified DMA Channel.
982 * @param SrcAddress The source memory Buffer address
983 * @param DstAddress The destination memory Buffer address
984 * @param DataLength The length of data to be transferred from source to destination
985 * @retval HAL status
986 */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)987 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
988 {
989 /* Clear the DMAMUX synchro overrun flag */
990 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
991
992 if (hdma->DMAmuxRequestGen != 0U)
993 {
994 /* Clear the DMAMUX request generator overrun flag */
995 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
996 }
997
998 /* Clear all flags */
999 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
1000
1001 /* Configure DMA Channel data length */
1002 hdma->Instance->CNDTR = DataLength;
1003
1004 /* Peripheral to Memory */
1005 if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1006 {
1007 /* Configure DMA Channel destination address */
1008 hdma->Instance->CPAR = DstAddress;
1009
1010 /* Configure DMA Channel source address */
1011 hdma->Instance->CMAR = SrcAddress;
1012 }
1013 /* Memory to Peripheral */
1014 else
1015 {
1016 /* Configure DMA Channel source address */
1017 hdma->Instance->CPAR = SrcAddress;
1018
1019 /* Configure DMA Channel destination address */
1020 hdma->Instance->CMAR = DstAddress;
1021 }
1022 }
1023
1024 /**
1025 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number
1026 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1027 * the configuration information for the specified DMA Stream.
1028 * @retval None
1029 */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1030 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1031 {
1032 uint32_t channel_number;
1033
1034 channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
1035 hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)(uint32_t)((uint32_t)DMAMUX1_Channel0 + \
1036 ((hdma->ChannelIndex >> 2U) * \
1037 ((uint32_t)DMAMUX1_Channel1 - \
1038 (uint32_t)DMAMUX1_Channel0)));
1039 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1040 hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1cU);
1041 }
1042
1043 /**
1044 * @brief Updates the DMA handle with the DMAMUX request generator params
1045 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1046 * the configuration information for the specified DMA Stream.
1047 * @retval None
1048 */
1049
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1050 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1051 {
1052 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1053
1054 /* DMA Channels are connected to DMAMUX1 request generator blocks*/
1055 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + \
1056 ((request - 1U) * 4U)));
1057
1058 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1059
1060 /* here "Request" is either DMA_REQUEST_GENERATOR0 to 4, i.e. <= 4*/
1061 hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
1062 }
1063
1064 /**
1065 * @}
1066 */
1067
1068 /**
1069 * @}
1070 */
1071
1072 #endif /* HAL_DMA_MODULE_ENABLED */
1073 /**
1074 * @}
1075 */
1076
1077 /**
1078 * @}
1079 */
1080