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