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