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