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 /* Change DMA peripheral state */
173 hdma->State = HAL_DMA_STATE_BUSY;
174
175 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
176 CLEAR_BIT(hdma->Instance->CCR, (DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \
177 DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \
178 DMA_CCR_DIR | DMA_CCR_MEM2MEM));
179
180 /* Set the DMA Channel configuration */
181 SET_BIT(hdma->Instance->CCR, (hdma->Init.Direction | \
182 hdma->Init.PeriphInc | hdma->Init.MemInc | \
183 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | \
184 hdma->Init.Mode | hdma->Init.Priority));
185
186 /* Initialize parameters for DMAMUX channel :
187 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
188 */
189 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
190
191 if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
192 {
193 /* if memory to memory force the request to 0*/
194 hdma->Init.Request = DMA_REQUEST_MEM2MEM;
195 }
196
197 /* Set peripheral request to DMAMUX channel */
198 hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
199
200 /* Clear the DMAMUX synchro overrun flag */
201 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
202
203 if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
204 {
205 /* Initialize parameters for DMAMUX request generator :
206 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
207 */
208 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
209
210 /* Reset the DMAMUX request generator register*/
211 hdma->DMAmuxRequestGen->RGCR = 0U;
212
213 /* Clear the DMAMUX request generator overrun flag */
214 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
215 }
216 else
217 {
218 hdma->DMAmuxRequestGen = 0U;
219 hdma->DMAmuxRequestGenStatus = 0U;
220 hdma->DMAmuxRequestGenStatusMask = 0U;
221 }
222
223 /* Initialize the error code */
224 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
225
226 /* Initialize the DMA state*/
227 hdma->State = HAL_DMA_STATE_READY;
228
229 /* Release Lock */
230 __HAL_UNLOCK(hdma);
231
232 return HAL_OK;
233 }
234
235 /**
236 * @brief DeInitialize the DMA peripheral.
237 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
238 * the configuration information for the specified DMA Channel.
239 * @retval HAL status
240 */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)241 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
242 {
243 /* Check the DMA handle allocation */
244 if (NULL == hdma)
245 {
246 return HAL_ERROR;
247 }
248
249 /* Check the parameters */
250 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
251
252 /* Disable the selected DMA Channelx */
253 __HAL_DMA_DISABLE(hdma);
254
255 /* calculation of the channel index */
256 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - \
257 (uint32_t)DMA1_Channel1)) << 2U;
258
259 /* Reset DMA Channel control register */
260 hdma->Instance->CCR = 0U;
261
262 /* Clear all flags */
263 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
264
265 /* Initialize parameters for DMAMUX channel :
266 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
267
268 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
269
270 /* Reset the DMAMUX channel that corresponds to the DMA channel */
271 hdma->DMAmuxChannel->CCR = 0U;
272
273 /* Clear the DMAMUX synchro overrun flag */
274 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
275
276 /* Reset Request generator parameters if any */
277 if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
278 {
279 /* Initialize parameters for DMAMUX request generator :
280 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
281 */
282 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
283
284 /* Reset the DMAMUX request generator register*/
285 hdma->DMAmuxRequestGen->RGCR = 0U;
286
287 /* Clear the DMAMUX request generator overrun flag */
288 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
289 }
290
291 /* Clean callbacks */
292 hdma->XferCpltCallback = NULL;
293 hdma->XferHalfCpltCallback = NULL;
294 hdma->XferErrorCallback = NULL;
295 hdma->XferAbortCallback = NULL;
296
297 hdma->DMAmuxRequestGen = 0U;
298 hdma->DMAmuxRequestGenStatus = 0U;
299 hdma->DMAmuxRequestGenStatusMask = 0U;
300
301 /* Initialize the error code */
302 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
303
304 /* Initialize the DMA state */
305 hdma->State = HAL_DMA_STATE_RESET;
306
307 /* Release Lock */
308 __HAL_UNLOCK(hdma);
309
310 return HAL_OK;
311 }
312
313 /**
314 * @}
315 */
316
317 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
318 * @brief Input and Output operation functions
319 *
320 @verbatim
321 ===============================================================================
322 ##### IO operation functions #####
323 ===============================================================================
324 [..] This section provides functions allowing to:
325 (+) Configure the source, destination address and data length and Start DMA transfer
326 (+) Configure the source, destination address and data length and
327 Start DMA transfer with interrupt
328 (+) Abort DMA transfer
329 (+) Poll for transfer complete
330 (+) Handle DMA interrupt request
331
332 @endverbatim
333 * @{
334 */
335
336 /**
337 * @brief Start the DMA Transfer.
338 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
339 * the configuration information for the specified DMA Channel.
340 * @param SrcAddress The source memory Buffer address
341 * @param DstAddress The destination memory Buffer address
342 * @param DataLength The length of data to be transferred from source to destination
343 * @retval HAL status
344 */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)345 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
346 {
347 HAL_StatusTypeDef status = HAL_OK;
348
349 /* Check the parameters */
350 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
351
352 /* Process locked */
353 __HAL_LOCK(hdma);
354
355 if (HAL_DMA_STATE_READY == hdma->State)
356 {
357 /* Change DMA peripheral state */
358 hdma->State = HAL_DMA_STATE_BUSY;
359 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
360
361 /* Disable the peripheral */
362 __HAL_DMA_DISABLE(hdma);
363
364 /* Configure the source, destination address and the data length & clear flags*/
365 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
366
367 /* Enable the Peripheral */
368 __HAL_DMA_ENABLE(hdma);
369 }
370 else
371 {
372 /* Process Unlocked */
373 __HAL_UNLOCK(hdma);
374 status = HAL_BUSY;
375 }
376
377 /* Process locked */
378 __HAL_UNLOCK(hdma);
379
380 return status;
381 }
382
383 /**
384 * @brief Start the DMA Transfer with interrupt enabled.
385 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
386 * the configuration information for the specified DMA Channel.
387 * @param SrcAddress The source memory Buffer address
388 * @param DstAddress The destination memory Buffer address
389 * @param DataLength The length of data to be transferred from source to destination
390 * @retval HAL status
391 */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)392 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress,
393 uint32_t DataLength)
394 {
395 HAL_StatusTypeDef status = HAL_OK;
396
397 /* Check the parameters */
398 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
399
400 /* Process locked */
401 __HAL_LOCK(hdma);
402
403 if (HAL_DMA_STATE_READY == hdma->State)
404 {
405 /* Change DMA peripheral state */
406 hdma->State = HAL_DMA_STATE_BUSY;
407 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
408
409 /* Disable the peripheral */
410 __HAL_DMA_DISABLE(hdma);
411
412 /* Configure the source, destination address and the data length & clear flags*/
413 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
414
415 /* Enable the transfer complete interrupt */
416 /* Enable the transfer Error interrupt */
417 if (NULL != hdma->XferHalfCpltCallback)
418 {
419 /* Enable the Half transfer complete interrupt as well */
420 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
421 }
422 else
423 {
424 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
425 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
426 }
427
428 /* Check if DMAMUX Synchronization is enabled*/
429 if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
430 {
431 /* Enable DMAMUX sync overrun IT*/
432 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
433 }
434
435 if (hdma->DMAmuxRequestGen != 0U)
436 {
437 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
438 /* enable the request gen overrun IT*/
439 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
440 }
441
442 /* Enable the Peripheral */
443 __HAL_DMA_ENABLE(hdma);
444 }
445 else
446 {
447 /* Process Unlocked */
448 __HAL_UNLOCK(hdma);
449
450 /* Remain BUSY */
451 status = HAL_BUSY;
452 }
453
454 /* Process unlocked */
455 __HAL_UNLOCK(hdma);
456
457 return status;
458 }
459
460 /**
461 * @brief Abort the DMA Transfer.
462 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
463 * the configuration information for the specified DMA Channel.
464 * @retval HAL status
465 */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)466 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
467 {
468 /* Check the DMA peripheral handle */
469 if (NULL == hdma)
470 {
471 return HAL_ERROR;
472 }
473
474 /* Check the DMA peripheral state */
475 if (hdma->State != HAL_DMA_STATE_BUSY)
476 {
477 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
478
479 /* Process Unlocked */
480 __HAL_UNLOCK(hdma);
481
482 return HAL_ERROR;
483 }
484 else
485 {
486 /* Disable DMA IT */
487 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
488
489 /* disable the DMAMUX sync overrun IT*/
490 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
491
492 /* Disable the channel */
493 __HAL_DMA_DISABLE(hdma);
494
495 /* Clear all flags */
496 __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
497
498 /* Clear the DMAMUX synchro overrun flag */
499 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
500
501 if (hdma->DMAmuxRequestGen != 0U)
502 {
503 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
504 /* disable the request gen overrun IT*/
505 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
506
507 /* Clear the DMAMUX request generator overrun flag */
508 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
509 }
510
511 /* Change the DMA state */
512 hdma->State = HAL_DMA_STATE_READY;
513
514 /* Process Unlocked */
515 __HAL_UNLOCK(hdma);
516 }
517
518 return HAL_OK;
519 }
520
521 /**
522 * @brief Aborts the DMA Transfer in Interrupt mode.
523 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
524 * the configuration information for the specified DMA Stream.
525 * @retval HAL status
526 */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)527 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
528 {
529 HAL_StatusTypeDef status = HAL_OK;
530
531 /* Process Unlocked/locked */
532 __HAL_UNLOCK(hdma);
533 __HAL_LOCK(hdma);
534
535 if (HAL_DMA_STATE_BUSY != hdma->State)
536 {
537 /* no transfer ongoing */
538 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
539
540 status = HAL_ERROR;
541 }
542 else
543 {
544 /* Disable DMA IT */
545 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
546
547 /* Disable the channel */
548 __HAL_DMA_DISABLE(hdma);
549
550 /* disable the DMAMUX sync overrun IT*/
551 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
552
553 /* Clear all flags */
554 __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
555
556 /* Clear the DMAMUX synchro overrun flag */
557 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
558
559 if (hdma->DMAmuxRequestGen != 0U)
560 {
561 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
562 /* disable the request gen overrun IT*/
563 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
564
565 /* Clear the DMAMUX request generator overrun flag */
566 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
567 }
568
569 /* Change the DMA state */
570 hdma->State = HAL_DMA_STATE_READY;
571
572 /* Process Unlocked */
573 __HAL_UNLOCK(hdma);
574
575 /* Call User Abort callback */
576 if (hdma->XferAbortCallback != NULL)
577 {
578 hdma->XferAbortCallback(hdma);
579 }
580 }
581 return status;
582 }
583
584 /**
585 * @brief Polling for transfer complete.
586 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
587 * the configuration information for the specified DMA Channel.
588 * @param CompleteLevel Specifies the DMA level complete.
589 * @param Timeout Timeout duration.
590 * @retval HAL status
591 */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)592 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel,
593 uint32_t Timeout)
594 {
595 uint32_t temp;
596 uint32_t tickstart;
597
598 /* Process unlocked */
599 __HAL_UNLOCK(hdma);
600
601 if (HAL_DMA_STATE_BUSY != hdma->State)
602 {
603 /* no transfer ongoing */
604 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
605 __HAL_UNLOCK(hdma);
606 return HAL_ERROR;
607 }
608
609 /* Polling mode not supported in circular mode */
610 if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
611 {
612 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
613 return HAL_ERROR;
614 }
615
616 /* Get the level transfer complete flag */
617 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
618 {
619 /* Transfer Complete flag */
620 temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
621 }
622 else
623 {
624 /* Half Transfer Complete flag */
625 temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU);
626 }
627
628 /* Get tick */
629 tickstart = HAL_GetTick();
630
631 while (0U == __HAL_DMA_GET_FLAG(hdma, temp))
632 {
633 if (0U != __HAL_DMA_GET_FLAG(hdma, (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))))
634 {
635 /* When a DMA transfer error occurs */
636 /* A hardware clear of its EN bits is performed */
637 /* Clear all flags */
638 __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
639
640 /* Update error code */
641 hdma->ErrorCode = HAL_DMA_ERROR_TE;
642
643 /* Change the DMA state */
644 hdma->State = HAL_DMA_STATE_READY;
645
646 /* Process Unlocked */
647 __HAL_UNLOCK(hdma);
648
649 return HAL_ERROR;
650 }
651 /* Check for the Timeout */
652 if (Timeout != HAL_MAX_DELAY)
653 {
654 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
655 {
656 /* Update error code */
657 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
658
659 /* Change the DMA state */
660 hdma->State = HAL_DMA_STATE_READY;
661
662 /* Process Unlocked */
663 __HAL_UNLOCK(hdma);
664
665 return HAL_ERROR;
666 }
667 }
668 }
669
670 /*Check for DMAMUX Request generator (if used) overrun status */
671 if (hdma->DMAmuxRequestGen != 0U)
672 {
673 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
674 if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
675 {
676 /* Disable the request gen overrun interrupt */
677 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
678
679 /* Clear the DMAMUX request generator overrun flag */
680 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
681
682 /* Update error code */
683 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
684 }
685 }
686
687 /* Check for DMAMUX Synchronization overrun */
688 if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
689 {
690 /* Clear the DMAMUX synchro overrun flag */
691 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
692
693 /* Update error code */
694 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
695 }
696
697 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
698 {
699 /* Clear the transfer complete flag */
700 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)));
701
702 /* The selected Channelx EN bit is cleared (DMA is disabled and
703 all transfers are complete) */
704 hdma->State = HAL_DMA_STATE_READY;
705 }
706 else
707 {
708 /* Clear the half transfer complete flag */
709 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU)));
710 }
711
712 /* Process unlocked */
713 __HAL_UNLOCK(hdma);
714
715 return HAL_OK;
716 }
717
718 /**
719 * @brief Handle DMA interrupt request.
720 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
721 * the configuration information for the specified DMA Channel.
722 * @retval None
723 */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)724 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
725 {
726 uint32_t flag_it = DMA1->ISR;
727 uint32_t source_it = hdma->Instance->CCR;
728
729 /* Half Transfer Complete Interrupt management ******************************/
730 if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
731 {
732 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
733 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
734 {
735 /* Disable the half transfer interrupt */
736 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
737 }
738 /* Clear the half transfer complete flag */
739 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU)));
740
741 /* DMA peripheral state is not updated in Half Transfer */
742 /* but in Transfer Complete case */
743
744 if (hdma->XferHalfCpltCallback != NULL)
745 {
746 /* Half transfer callback */
747 hdma->XferHalfCpltCallback(hdma);
748 }
749 }
750
751 /* Transfer Complete Interrupt management ***********************************/
752 else if ((0U != (flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)))) && (0U != (source_it & DMA_IT_TC)))
753 {
754 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
755 {
756 /* Disable the transfer complete and error interrupt */
757 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
758
759 /* Change the DMA state */
760 hdma->State = HAL_DMA_STATE_READY;
761 }
762 /* Clear the transfer complete flag */
763 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)));
764
765 /* Process Unlocked */
766 __HAL_UNLOCK(hdma);
767
768 if (hdma->XferCpltCallback != NULL)
769 {
770 /* Transfer complete callback */
771 hdma->XferCpltCallback(hdma);
772 }
773 }
774
775 /* Transfer Error Interrupt management **************************************/
776 else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
777 {
778 /* When a DMA transfer error occurs */
779 /* A hardware clear of its EN bits is performed */
780 /* Disable ALL DMA IT */
781 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
782
783 /* Clear all flags */
784 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
785
786 /* Update error code */
787 hdma->ErrorCode = HAL_DMA_ERROR_TE;
788
789 /* Change the DMA state */
790 hdma->State = HAL_DMA_STATE_READY;
791
792 /* Process Unlocked */
793 __HAL_UNLOCK(hdma);
794
795 if (hdma->XferErrorCallback != NULL)
796 {
797 /* Transfer error callback */
798 hdma->XferErrorCallback(hdma);
799 }
800 }
801 else
802 {
803 /* Nothing To Do */
804 }
805 return;
806 }
807
808 /**
809 * @brief Register callbacks
810 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
811 * the configuration information for the specified DMA Stream.
812 * @param CallbackID User Callback identifier
813 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
814 * @param pCallback pointer to private callback function which has pointer to
815 * a DMA_HandleTypeDef structure as parameter.
816 * @retval HAL status
817 */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))818 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID,
819 void (* pCallback)(DMA_HandleTypeDef *_hdma))
820 {
821 HAL_StatusTypeDef status = HAL_OK;
822
823 /* Process locked */
824 __HAL_LOCK(hdma);
825
826 if (HAL_DMA_STATE_READY == hdma->State)
827 {
828 switch (CallbackID)
829 {
830 case HAL_DMA_XFER_CPLT_CB_ID:
831 hdma->XferCpltCallback = pCallback;
832 break;
833
834 case HAL_DMA_XFER_HALFCPLT_CB_ID:
835 hdma->XferHalfCpltCallback = pCallback;
836 break;
837
838 case HAL_DMA_XFER_ERROR_CB_ID:
839 hdma->XferErrorCallback = pCallback;
840 break;
841
842 case HAL_DMA_XFER_ABORT_CB_ID:
843 hdma->XferAbortCallback = pCallback;
844 break;
845
846 default:
847 status = HAL_ERROR;
848 break;
849 }
850 }
851 else
852 {
853 status = HAL_ERROR;
854 }
855
856 /* Release Lock */
857 __HAL_UNLOCK(hdma);
858
859 return status;
860 }
861
862 /**
863 * @brief UnRegister callbacks
864 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
865 * the configuration information for the specified DMA Stream.
866 * @param CallbackID User Callback identifier
867 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
868 * @retval HAL status
869 */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)870 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
871 {
872 HAL_StatusTypeDef status = HAL_OK;
873
874 /* Process locked */
875 __HAL_LOCK(hdma);
876
877 if (HAL_DMA_STATE_READY == hdma->State)
878 {
879 switch (CallbackID)
880 {
881 case HAL_DMA_XFER_CPLT_CB_ID:
882 hdma->XferCpltCallback = NULL;
883 break;
884
885 case HAL_DMA_XFER_HALFCPLT_CB_ID:
886 hdma->XferHalfCpltCallback = NULL;
887 break;
888
889 case HAL_DMA_XFER_ERROR_CB_ID:
890 hdma->XferErrorCallback = NULL;
891 break;
892
893 case HAL_DMA_XFER_ABORT_CB_ID:
894 hdma->XferAbortCallback = NULL;
895 break;
896
897 case HAL_DMA_XFER_ALL_CB_ID:
898 hdma->XferCpltCallback = NULL;
899 hdma->XferHalfCpltCallback = NULL;
900 hdma->XferErrorCallback = NULL;
901 hdma->XferAbortCallback = NULL;
902 break;
903
904 default:
905 status = HAL_ERROR;
906 break;
907 }
908 }
909 else
910 {
911 status = HAL_ERROR;
912 }
913
914 /* Release Lock */
915 __HAL_UNLOCK(hdma);
916
917 return status;
918 }
919
920 /**
921 * @}
922 */
923
924 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
925 * @brief Peripheral State and Errors functions
926 *
927 @verbatim
928 ===============================================================================
929 ##### Peripheral State and Errors functions #####
930 ===============================================================================
931 [..]
932 This subsection provides functions allowing to
933 (+) Check the DMA state
934 (+) Get error code
935
936 @endverbatim
937 * @{
938 */
939
940 /**
941 * @brief Return the DMA handle state.
942 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
943 * the configuration information for the specified DMA Channel.
944 * @retval HAL state
945 */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)946 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
947 {
948 /* Return DMA handle state */
949 return hdma->State;
950 }
951
952 /**
953 * @brief Return the DMA error code.
954 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
955 * the configuration information for the specified DMA Channel.
956 * @retval DMA Error Code
957 */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)958 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
959 {
960 return hdma->ErrorCode;
961 }
962
963 /**
964 * @}
965 */
966
967 /**
968 * @}
969 */
970
971 /** @addtogroup DMA_Private_Functions
972 * @{
973 */
974
975 /**
976 * @brief Sets the DMA Transfer parameter.
977 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
978 * the configuration information for the specified DMA Channel.
979 * @param SrcAddress The source memory Buffer address
980 * @param DstAddress The destination memory Buffer address
981 * @param DataLength The length of data to be transferred from source to destination
982 * @retval HAL status
983 */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)984 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
985 {
986 /* Clear the DMAMUX synchro overrun flag */
987 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
988
989 if (hdma->DMAmuxRequestGen != 0U)
990 {
991 /* Clear the DMAMUX request generator overrun flag */
992 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
993 }
994
995 /* Clear all flags */
996 __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
997
998 /* Configure DMA Channel data length */
999 hdma->Instance->CNDTR = DataLength;
1000
1001 /* Peripheral to Memory */
1002 if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1003 {
1004 /* Configure DMA Channel destination address */
1005 hdma->Instance->CPAR = DstAddress;
1006
1007 /* Configure DMA Channel source address */
1008 hdma->Instance->CMAR = SrcAddress;
1009 }
1010 /* Memory to Peripheral */
1011 else
1012 {
1013 /* Configure DMA Channel source address */
1014 hdma->Instance->CPAR = SrcAddress;
1015
1016 /* Configure DMA Channel destination address */
1017 hdma->Instance->CMAR = DstAddress;
1018 }
1019 }
1020
1021 /**
1022 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number
1023 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1024 * the configuration information for the specified DMA Stream.
1025 * @retval None
1026 */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1027 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1028 {
1029 uint32_t channel_number;
1030
1031 channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
1032 hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)(uint32_t)((uint32_t)DMAMUX1_Channel0 + \
1033 ((hdma->ChannelIndex >> 2U) * \
1034 ((uint32_t)DMAMUX1_Channel1 - \
1035 (uint32_t)DMAMUX1_Channel0)));
1036 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1037 hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1cU);
1038 }
1039
1040 /**
1041 * @brief Updates the DMA handle with the DMAMUX request generator params
1042 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1043 * the configuration information for the specified DMA Stream.
1044 * @retval None
1045 */
1046
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1047 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1048 {
1049 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1050
1051 /* DMA Channels are connected to DMAMUX1 request generator blocks*/
1052 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + \
1053 ((request - 1U) * 4U)));
1054
1055 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1056
1057 /* here "Request" is either DMA_REQUEST_GENERATOR0 to 4, i.e. <= 4*/
1058 hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
1059 }
1060
1061 /**
1062 * @}
1063 */
1064
1065 /**
1066 * @}
1067 */
1068
1069 #endif /* HAL_DMA_MODULE_ENABLED */
1070 /**
1071 * @}
1072 */
1073
1074 /**
1075 * @}
1076 */
1077