2 ******************************************************************************
\r
3 * @file stm32l4xx_hal_dma.c
\r
4 * @author MCD Application Team
\r
5 * @brief DMA HAL module driver.
\r
6 * This file provides firmware functions to manage the following
\r
7 * functionalities of the Direct Memory Access (DMA) peripheral:
\r
8 * + Initialization and de-initialization functions
\r
9 * + IO operation functions
\r
10 * + Peripheral State and errors functions
\r
12 ==============================================================================
\r
13 ##### How to use this driver #####
\r
14 ==============================================================================
\r
16 (#) Enable and configure the peripheral to be connected to the DMA Channel
\r
17 (except for internal SRAM / FLASH memories: no initialization is
\r
18 necessary). Please refer to the Reference manual for connection between peripherals
\r
21 (#) For a given Channel, program the required configuration through the following parameters:
\r
22 Channel request, Transfer Direction, Source and Destination data formats,
\r
23 Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
\r
24 using HAL_DMA_Init() function.
\r
26 Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX
\r
28 (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ;
\r
29 (##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE();
\r
31 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
\r
34 (#) Use HAL_DMA_Abort() function to abort the current transfer
\r
36 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
\r
38 *** Polling mode IO operation ***
\r
39 =================================
\r
41 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
\r
42 address and destination address and the Length of data to be transferred
\r
43 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
\r
44 case a fixed Timeout can be configured by User depending from his application.
\r
46 *** Interrupt mode IO operation ***
\r
47 ===================================
\r
49 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
\r
50 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
\r
51 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
\r
52 Source address and destination address and the Length of data to be transferred.
\r
53 In this case the DMA interrupt is configured
\r
54 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
\r
55 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
\r
56 add his own function to register callbacks with HAL_DMA_RegisterCallback().
\r
58 *** DMA HAL driver macros list ***
\r
59 =============================================
\r
61 Below the list of macros in DMA HAL driver.
\r
63 (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
\r
64 (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
\r
65 (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
\r
66 (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
\r
67 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
\r
68 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
\r
69 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not.
\r
72 (@) You can refer to the DMA HAL driver header file for more useful macros
\r
75 ******************************************************************************
\r
78 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
\r
79 * All rights reserved.</center></h2>
\r
81 * This software component is licensed by ST under BSD 3-Clause license,
\r
82 * the "License"; You may not use this file except in compliance with the
\r
83 * License. You may obtain a copy of the License at:
\r
84 * opensource.org/licenses/BSD-3-Clause
\r
86 ******************************************************************************
\r
89 /* Includes ------------------------------------------------------------------*/
\r
90 #include "stm32l4xx_hal.h"
\r
92 /** @addtogroup STM32L4xx_HAL_Driver
\r
96 /** @defgroup DMA DMA
\r
97 * @brief DMA HAL module driver
\r
101 #ifdef HAL_DMA_MODULE_ENABLED
\r
103 /* Private typedef -----------------------------------------------------------*/
\r
104 /* Private define ------------------------------------------------------------*/
\r
105 /* Private macro -------------------------------------------------------------*/
\r
106 /* Private variables ---------------------------------------------------------*/
\r
107 /* Private function prototypes -----------------------------------------------*/
\r
108 /** @defgroup DMA_Private_Functions DMA Private Functions
\r
111 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
\r
112 #if defined(DMAMUX1)
\r
113 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
\r
114 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
\r
115 #endif /* DMAMUX1 */
\r
121 /* Exported functions ---------------------------------------------------------*/
\r
123 /** @defgroup DMA_Exported_Functions DMA Exported Functions
\r
127 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
\r
128 * @brief Initialization and de-initialization functions
\r
131 ===============================================================================
\r
132 ##### Initialization and de-initialization functions #####
\r
133 ===============================================================================
\r
135 This section provides functions allowing to initialize the DMA Channel source
\r
136 and destination addresses, incrementation and data sizes, transfer direction,
\r
137 circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
\r
139 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
\r
147 * @brief Initialize the DMA according to the specified
\r
148 * parameters in the DMA_InitTypeDef and initialize the associated handle.
\r
149 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
150 * the configuration information for the specified DMA Channel.
\r
151 * @retval HAL status
\r
153 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
\r
157 /* Check the DMA handle allocation */
\r
163 /* Check the parameters */
\r
164 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
\r
165 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
\r
166 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
\r
167 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
\r
168 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
\r
169 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
\r
170 assert_param(IS_DMA_MODE(hdma->Init.Mode));
\r
171 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
\r
173 assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));
\r
175 /* Compute the channel index */
\r
176 if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
\r
179 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
\r
180 hdma->DmaBaseAddress = DMA1;
\r
185 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
\r
186 hdma->DmaBaseAddress = DMA2;
\r
189 /* Change DMA peripheral state */
\r
190 hdma->State = HAL_DMA_STATE_BUSY;
\r
192 /* Get the CR register value */
\r
193 tmp = hdma->Instance->CCR;
\r
195 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
\r
196 tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE |
\r
197 DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC |
\r
198 DMA_CCR_DIR | DMA_CCR_MEM2MEM));
\r
200 /* Prepare the DMA Channel configuration */
\r
201 tmp |= hdma->Init.Direction |
\r
202 hdma->Init.PeriphInc | hdma->Init.MemInc |
\r
203 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
\r
204 hdma->Init.Mode | hdma->Init.Priority;
\r
206 /* Write to DMA Channel CR register */
\r
207 hdma->Instance->CCR = tmp;
\r
209 #if defined(DMAMUX1)
\r
210 /* Initialize parameters for DMAMUX channel :
\r
211 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
\r
213 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
\r
215 if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
\r
217 /* if memory to memory force the request to 0*/
\r
218 hdma->Init.Request = DMA_REQUEST_MEM2MEM;
\r
221 /* Set peripheral request to DMAMUX channel */
\r
222 hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
\r
224 /* Clear the DMAMUX synchro overrun flag */
\r
225 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
\r
227 if(((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
\r
229 /* Initialize parameters for DMAMUX request generator :
\r
230 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
\r
232 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
\r
234 /* Reset the DMAMUX request generator register*/
\r
235 hdma->DMAmuxRequestGen->RGCR = 0U;
\r
237 /* Clear the DMAMUX request generator overrun flag */
\r
238 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
\r
242 hdma->DMAmuxRequestGen = 0U;
\r
243 hdma->DMAmuxRequestGenStatus = 0U;
\r
244 hdma->DMAmuxRequestGenStatusMask = 0U;
\r
246 #endif /* DMAMUX1 */
\r
248 #if !defined (DMAMUX1)
\r
250 /* Set request selection */
\r
251 if(hdma->Init.Direction != DMA_MEMORY_TO_MEMORY)
\r
253 /* Write to DMA channel selection register */
\r
254 if (DMA1 == hdma->DmaBaseAddress)
\r
256 /* Reset request selection for DMA1 Channelx */
\r
257 DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
\r
259 /* Configure request selection for DMA1 Channelx */
\r
260 DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex & 0x1cU));
\r
264 /* Reset request selection for DMA2 Channelx */
\r
265 DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
\r
267 /* Configure request selection for DMA2 Channelx */
\r
268 DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex & 0x1cU));
\r
272 #endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */
\r
273 /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */
\r
274 /* STM32L496xx || STM32L4A6xx */
\r
276 /* Initialise the error code */
\r
277 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
\r
279 /* Initialize the DMA state*/
\r
280 hdma->State = HAL_DMA_STATE_READY;
\r
282 /* Allocate lock resource and initialize it */
\r
283 hdma->Lock = HAL_UNLOCKED;
\r
289 * @brief DeInitialize the DMA peripheral.
\r
290 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
291 * the configuration information for the specified DMA Channel.
\r
292 * @retval HAL status
\r
294 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
\r
297 /* Check the DMA handle allocation */
\r
303 /* Check the parameters */
\r
304 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
\r
306 /* Disable the selected DMA Channelx */
\r
307 __HAL_DMA_DISABLE(hdma);
\r
309 /* Compute the channel index */
\r
310 if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
\r
313 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
\r
314 hdma->DmaBaseAddress = DMA1;
\r
319 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
\r
320 hdma->DmaBaseAddress = DMA2;
\r
323 /* Reset DMA Channel control register */
\r
324 hdma->Instance->CCR = 0U;
\r
326 /* Clear all flags */
\r
327 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
329 #if !defined (DMAMUX1)
\r
331 /* Reset DMA channel selection register */
\r
332 if (DMA1 == hdma->DmaBaseAddress)
\r
335 DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
\r
340 DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
\r
342 #endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */
\r
343 /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */
\r
344 /* STM32L496xx || STM32L4A6xx */
\r
346 #if defined(DMAMUX1)
\r
348 /* Initialize parameters for DMAMUX channel :
\r
349 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
\r
351 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
\r
353 /* Reset the DMAMUX channel that corresponds to the DMA channel */
\r
354 hdma->DMAmuxChannel->CCR = 0U;
\r
356 /* Clear the DMAMUX synchro overrun flag */
\r
357 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
\r
359 /* Reset Request generator parameters if any */
\r
360 if(((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
\r
362 /* Initialize parameters for DMAMUX request generator :
\r
363 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
\r
365 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
\r
367 /* Reset the DMAMUX request generator register*/
\r
368 hdma->DMAmuxRequestGen->RGCR = 0U;
\r
370 /* Clear the DMAMUX request generator overrun flag */
\r
371 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
\r
374 hdma->DMAmuxRequestGen = 0U;
\r
375 hdma->DMAmuxRequestGenStatus = 0U;
\r
376 hdma->DMAmuxRequestGenStatusMask = 0U;
\r
378 #endif /* DMAMUX1 */
\r
380 /* Clean callbacks */
\r
381 hdma->XferCpltCallback = NULL;
\r
382 hdma->XferHalfCpltCallback = NULL;
\r
383 hdma->XferErrorCallback = NULL;
\r
384 hdma->XferAbortCallback = NULL;
\r
386 /* Initialise the error code */
\r
387 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
\r
389 /* Initialize the DMA state */
\r
390 hdma->State = HAL_DMA_STATE_RESET;
\r
393 __HAL_UNLOCK(hdma);
\r
402 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
\r
403 * @brief Input and Output operation functions
\r
406 ===============================================================================
\r
407 ##### IO operation functions #####
\r
408 ===============================================================================
\r
409 [..] This section provides functions allowing to:
\r
410 (+) Configure the source, destination address and data length and Start DMA transfer
\r
411 (+) Configure the source, destination address and data length and
\r
412 Start DMA transfer with interrupt
\r
413 (+) Abort DMA transfer
\r
414 (+) Poll for transfer complete
\r
415 (+) Handle DMA interrupt request
\r
422 * @brief Start the DMA Transfer.
\r
423 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
424 * the configuration information for the specified DMA Channel.
\r
425 * @param SrcAddress The source memory Buffer address
\r
426 * @param DstAddress The destination memory Buffer address
\r
427 * @param DataLength The length of data to be transferred from source to destination
\r
428 * @retval HAL status
\r
430 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
\r
432 HAL_StatusTypeDef status = HAL_OK;
\r
434 /* Check the parameters */
\r
435 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
\r
437 /* Process locked */
\r
440 if(HAL_DMA_STATE_READY == hdma->State)
\r
442 /* Change DMA peripheral state */
\r
443 hdma->State = HAL_DMA_STATE_BUSY;
\r
444 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
\r
446 /* Disable the peripheral */
\r
447 __HAL_DMA_DISABLE(hdma);
\r
449 /* Configure the source, destination address and the data length & clear flags*/
\r
450 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
\r
452 /* Enable the Peripheral */
\r
453 __HAL_DMA_ENABLE(hdma);
\r
457 /* Process Unlocked */
\r
458 __HAL_UNLOCK(hdma);
\r
465 * @brief Start the DMA Transfer with interrupt enabled.
\r
466 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
467 * the configuration information for the specified DMA Channel.
\r
468 * @param SrcAddress The source memory Buffer address
\r
469 * @param DstAddress The destination memory Buffer address
\r
470 * @param DataLength The length of data to be transferred from source to destination
\r
471 * @retval HAL status
\r
473 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
\r
475 HAL_StatusTypeDef status = HAL_OK;
\r
477 /* Check the parameters */
\r
478 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
\r
480 /* Process locked */
\r
483 if(HAL_DMA_STATE_READY == hdma->State)
\r
485 /* Change DMA peripheral state */
\r
486 hdma->State = HAL_DMA_STATE_BUSY;
\r
487 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
\r
489 /* Disable the peripheral */
\r
490 __HAL_DMA_DISABLE(hdma);
\r
492 /* Configure the source, destination address and the data length & clear flags*/
\r
493 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
\r
495 /* Enable the transfer complete interrupt */
\r
496 /* Enable the transfer Error interrupt */
\r
497 if(NULL != hdma->XferHalfCpltCallback )
\r
499 /* Enable the Half transfer complete interrupt as well */
\r
500 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
\r
504 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
\r
505 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
\r
510 /* Check if DMAMUX Synchronization is enabled*/
\r
511 if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
\r
513 /* Enable DMAMUX sync overrun IT*/
\r
514 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
\r
517 if(hdma->DMAmuxRequestGen != 0U)
\r
519 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
\r
520 /* enable the request gen overrun IT*/
\r
521 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
\r
524 #endif /* DMAMUX1 */
\r
526 /* Enable the Peripheral */
\r
527 __HAL_DMA_ENABLE(hdma);
\r
531 /* Process Unlocked */
\r
532 __HAL_UNLOCK(hdma);
\r
541 * @brief Abort the DMA Transfer.
\r
542 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
543 * the configuration information for the specified DMA Channel.
\r
544 * @retval HAL status
\r
546 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
\r
548 HAL_StatusTypeDef status = HAL_OK;
\r
550 /* Check the DMA peripheral state */
\r
551 if(hdma->State != HAL_DMA_STATE_BUSY)
\r
553 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
\r
555 /* Process Unlocked */
\r
556 __HAL_UNLOCK(hdma);
\r
562 /* Disable DMA IT */
\r
563 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
\r
565 #if defined(DMAMUX1)
\r
566 /* disable the DMAMUX sync overrun IT*/
\r
567 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
\r
568 #endif /* DMAMUX1 */
\r
570 /* Disable the channel */
\r
571 __HAL_DMA_DISABLE(hdma);
\r
573 /* Clear all flags */
\r
574 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
576 #if defined(DMAMUX1)
\r
577 /* Clear the DMAMUX synchro overrun flag */
\r
578 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
\r
580 if(hdma->DMAmuxRequestGen != 0U)
\r
582 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
\r
583 /* disable the request gen overrun IT*/
\r
584 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
\r
586 /* Clear the DMAMUX request generator overrun flag */
\r
587 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
\r
590 #endif /* DMAMUX1 */
\r
592 /* Change the DMA state */
\r
593 hdma->State = HAL_DMA_STATE_READY;
\r
595 /* Process Unlocked */
\r
596 __HAL_UNLOCK(hdma);
\r
603 * @brief Aborts the DMA Transfer in Interrupt mode.
\r
604 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
605 * the configuration information for the specified DMA Channel.
\r
606 * @retval HAL status
\r
608 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
\r
610 HAL_StatusTypeDef status = HAL_OK;
\r
612 if(HAL_DMA_STATE_BUSY != hdma->State)
\r
614 /* no transfer ongoing */
\r
615 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
\r
617 status = HAL_ERROR;
\r
621 /* Disable DMA IT */
\r
622 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
\r
624 /* Disable the channel */
\r
625 __HAL_DMA_DISABLE(hdma);
\r
627 #if defined(DMAMUX1)
\r
628 /* disable the DMAMUX sync overrun IT*/
\r
629 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
\r
631 /* Clear all flags */
\r
632 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
634 /* Clear the DMAMUX synchro overrun flag */
\r
635 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
\r
637 if(hdma->DMAmuxRequestGen != 0U)
\r
639 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
\r
640 /* disable the request gen overrun IT*/
\r
641 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
\r
643 /* Clear the DMAMUX request generator overrun flag */
\r
644 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
\r
648 /* Clear all flags */
\r
649 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
650 #endif /* DMAMUX1 */
\r
652 /* Change the DMA state */
\r
653 hdma->State = HAL_DMA_STATE_READY;
\r
655 /* Process Unlocked */
\r
656 __HAL_UNLOCK(hdma);
\r
658 /* Call User Abort callback */
\r
659 if(hdma->XferAbortCallback != NULL)
\r
661 hdma->XferAbortCallback(hdma);
\r
668 * @brief Polling for transfer complete.
\r
669 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
670 * the configuration information for the specified DMA Channel.
\r
671 * @param CompleteLevel Specifies the DMA level complete.
\r
672 * @param Timeout Timeout duration.
\r
673 * @retval HAL status
\r
675 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
\r
678 uint32_t tickstart;
\r
680 if(HAL_DMA_STATE_BUSY != hdma->State)
\r
682 /* no transfer ongoing */
\r
683 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
\r
684 __HAL_UNLOCK(hdma);
\r
688 /* Polling mode not supported in circular mode */
\r
689 if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
\r
691 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
\r
695 /* Get the level transfer complete flag */
\r
696 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
\r
698 /* Transfer Complete flag */
\r
699 temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU);
\r
703 /* Half Transfer Complete flag */
\r
704 temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU);
\r
708 tickstart = HAL_GetTick();
\r
710 while((hdma->DmaBaseAddress->ISR & temp) == 0U)
\r
712 if((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex& 0x1CU))) != 0U)
\r
714 /* When a DMA transfer error occurs */
\r
715 /* A hardware clear of its EN bits is performed */
\r
716 /* Clear all flags */
\r
717 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
719 /* Update error code */
\r
720 hdma->ErrorCode = HAL_DMA_ERROR_TE;
\r
722 /* Change the DMA state */
\r
723 hdma->State= HAL_DMA_STATE_READY;
\r
725 /* Process Unlocked */
\r
726 __HAL_UNLOCK(hdma);
\r
730 /* Check for the Timeout */
\r
731 if(Timeout != HAL_MAX_DELAY)
\r
733 if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
\r
735 /* Update error code */
\r
736 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
\r
738 /* Change the DMA state */
\r
739 hdma->State = HAL_DMA_STATE_READY;
\r
741 /* Process Unlocked */
\r
742 __HAL_UNLOCK(hdma);
\r
749 #if defined(DMAMUX1)
\r
750 /*Check for DMAMUX Request generator (if used) overrun status */
\r
751 if(hdma->DMAmuxRequestGen != 0U)
\r
753 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
\r
754 if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
\r
756 /* Disable the request gen overrun interrupt */
\r
757 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
\r
759 /* Clear the DMAMUX request generator overrun flag */
\r
760 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
\r
762 /* Update error code */
\r
763 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
\r
767 /* Check for DMAMUX Synchronization overrun */
\r
768 if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
\r
770 /* Clear the DMAMUX synchro overrun flag */
\r
771 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
\r
773 /* Update error code */
\r
774 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
\r
776 #endif /* DMAMUX1 */
\r
778 if(HAL_DMA_FULL_TRANSFER == CompleteLevel)
\r
780 /* Clear the transfer complete flag */
\r
781 hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex& 0x1CU));
\r
783 /* The selected Channelx EN bit is cleared (DMA is disabled and
\r
784 all transfers are complete) */
\r
785 hdma->State = HAL_DMA_STATE_READY;
\r
789 /* Clear the half transfer complete flag */
\r
790 hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU));
\r
793 /* Process unlocked */
\r
794 __HAL_UNLOCK(hdma);
\r
800 * @brief Handle DMA interrupt request.
\r
801 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
802 * the configuration information for the specified DMA Channel.
\r
805 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
\r
807 uint32_t flag_it = hdma->DmaBaseAddress->ISR;
\r
808 uint32_t source_it = hdma->Instance->CCR;
\r
810 /* Half Transfer Complete Interrupt management ******************************/
\r
811 if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
\r
813 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
\r
814 if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
\r
816 /* Disable the half transfer interrupt */
\r
817 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
\r
819 /* Clear the half transfer complete flag */
\r
820 hdma->DmaBaseAddress->IFCR = DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU);
\r
822 /* DMA peripheral state is not updated in Half Transfer */
\r
823 /* but in Transfer Complete case */
\r
825 if(hdma->XferHalfCpltCallback != NULL)
\r
827 /* Half transfer callback */
\r
828 hdma->XferHalfCpltCallback(hdma);
\r
832 /* Transfer Complete Interrupt management ***********************************/
\r
833 else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
\r
835 if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
\r
837 /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
\r
838 /* Disable the transfer complete and error interrupt */
\r
839 /* if the DMA mode is not CIRCULAR */
\r
840 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
\r
842 /* Change the DMA state */
\r
843 hdma->State = HAL_DMA_STATE_READY;
\r
845 /* Clear the transfer complete flag */
\r
846 hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1CU));
\r
848 /* Process Unlocked */
\r
849 __HAL_UNLOCK(hdma);
\r
851 if(hdma->XferCpltCallback != NULL)
\r
853 /* Transfer complete callback */
\r
854 hdma->XferCpltCallback(hdma);
\r
858 /* Transfer Error Interrupt management **************************************/
\r
859 else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
\r
861 /* When a DMA transfer error occurs */
\r
862 /* A hardware clear of its EN bits is performed */
\r
863 /* Disable ALL DMA IT */
\r
864 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
\r
866 /* Clear all flags */
\r
867 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
869 /* Update error code */
\r
870 hdma->ErrorCode = HAL_DMA_ERROR_TE;
\r
872 /* Change the DMA state */
\r
873 hdma->State = HAL_DMA_STATE_READY;
\r
875 /* Process Unlocked */
\r
876 __HAL_UNLOCK(hdma);
\r
878 if (hdma->XferErrorCallback != NULL)
\r
880 /* Transfer error callback */
\r
881 hdma->XferErrorCallback(hdma);
\r
886 /* Nothing To Do */
\r
892 * @brief Register callbacks
\r
893 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
894 * the configuration information for the specified DMA Channel.
\r
895 * @param CallbackID User Callback identifer
\r
896 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
\r
897 * @param pCallback pointer to private callbacsk function which has pointer to
\r
898 * a DMA_HandleTypeDef structure as parameter.
\r
899 * @retval HAL status
\r
901 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma))
\r
903 HAL_StatusTypeDef status = HAL_OK;
\r
905 /* Process locked */
\r
908 if(HAL_DMA_STATE_READY == hdma->State)
\r
910 switch (CallbackID)
\r
912 case HAL_DMA_XFER_CPLT_CB_ID:
\r
913 hdma->XferCpltCallback = pCallback;
\r
916 case HAL_DMA_XFER_HALFCPLT_CB_ID:
\r
917 hdma->XferHalfCpltCallback = pCallback;
\r
920 case HAL_DMA_XFER_ERROR_CB_ID:
\r
921 hdma->XferErrorCallback = pCallback;
\r
924 case HAL_DMA_XFER_ABORT_CB_ID:
\r
925 hdma->XferAbortCallback = pCallback;
\r
929 status = HAL_ERROR;
\r
935 status = HAL_ERROR;
\r
939 __HAL_UNLOCK(hdma);
\r
945 * @brief UnRegister callbacks
\r
946 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
947 * the configuration information for the specified DMA Channel.
\r
948 * @param CallbackID User Callback identifer
\r
949 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
\r
950 * @retval HAL status
\r
952 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
\r
954 HAL_StatusTypeDef status = HAL_OK;
\r
956 /* Process locked */
\r
959 if(HAL_DMA_STATE_READY == hdma->State)
\r
961 switch (CallbackID)
\r
963 case HAL_DMA_XFER_CPLT_CB_ID:
\r
964 hdma->XferCpltCallback = NULL;
\r
967 case HAL_DMA_XFER_HALFCPLT_CB_ID:
\r
968 hdma->XferHalfCpltCallback = NULL;
\r
971 case HAL_DMA_XFER_ERROR_CB_ID:
\r
972 hdma->XferErrorCallback = NULL;
\r
975 case HAL_DMA_XFER_ABORT_CB_ID:
\r
976 hdma->XferAbortCallback = NULL;
\r
979 case HAL_DMA_XFER_ALL_CB_ID:
\r
980 hdma->XferCpltCallback = NULL;
\r
981 hdma->XferHalfCpltCallback = NULL;
\r
982 hdma->XferErrorCallback = NULL;
\r
983 hdma->XferAbortCallback = NULL;
\r
987 status = HAL_ERROR;
\r
993 status = HAL_ERROR;
\r
997 __HAL_UNLOCK(hdma);
\r
1008 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
\r
1009 * @brief Peripheral State and Errors functions
\r
1012 ===============================================================================
\r
1013 ##### Peripheral State and Errors functions #####
\r
1014 ===============================================================================
\r
1016 This subsection provides functions allowing to
\r
1017 (+) Check the DMA state
\r
1018 (+) Get error code
\r
1025 * @brief Return the DMA handle state.
\r
1026 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
1027 * the configuration information for the specified DMA Channel.
\r
1028 * @retval HAL state
\r
1030 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
\r
1032 /* Return DMA handle state */
\r
1033 return hdma->State;
\r
1037 * @brief Return the DMA error code.
\r
1038 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
\r
1039 * the configuration information for the specified DMA Channel.
\r
1040 * @retval DMA Error Code
\r
1042 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
\r
1044 return hdma->ErrorCode;
\r
1055 /** @addtogroup DMA_Private_Functions
\r
1060 * @brief Sets the DMA Transfer parameter.
\r
1061 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
1062 * the configuration information for the specified DMA Channel.
\r
1063 * @param SrcAddress The source memory Buffer address
\r
1064 * @param DstAddress The destination memory Buffer address
\r
1065 * @param DataLength The length of data to be transferred from source to destination
\r
1066 * @retval HAL status
\r
1068 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
\r
1070 #if defined(DMAMUX1)
\r
1071 /* Clear the DMAMUX synchro overrun flag */
\r
1072 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
\r
1074 if(hdma->DMAmuxRequestGen != 0U)
\r
1076 /* Clear the DMAMUX request generator overrun flag */
\r
1077 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
\r
1081 /* Clear all flags */
\r
1082 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
\r
1084 /* Configure DMA Channel data length */
\r
1085 hdma->Instance->CNDTR = DataLength;
\r
1087 /* Memory to Peripheral */
\r
1088 if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
\r
1090 /* Configure DMA Channel destination address */
\r
1091 hdma->Instance->CPAR = DstAddress;
\r
1093 /* Configure DMA Channel source address */
\r
1094 hdma->Instance->CMAR = SrcAddress;
\r
1096 /* Peripheral to Memory */
\r
1099 /* Configure DMA Channel source address */
\r
1100 hdma->Instance->CPAR = SrcAddress;
\r
1102 /* Configure DMA Channel destination address */
\r
1103 hdma->Instance->CMAR = DstAddress;
\r
1107 #if defined(DMAMUX1)
\r
1110 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on channel number
\r
1111 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
1112 * the configuration information for the specified DMA Channel.
\r
1115 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
\r
1117 uint32_t channel_number;
\r
1119 /* check if instance is not outside the DMA channel range */
\r
1120 if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1)
\r
1123 hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
\r
1128 hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U));
\r
1131 channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
\r
1132 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
\r
1133 hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1CU);
\r
1137 * @brief Updates the DMA handle with the DMAMUX request generator params
\r
1138 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
\r
1139 * the configuration information for the specified DMA Channel.
\r
1143 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
\r
1145 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
\r
1147 /* DMA Channels are connected to DMAMUX1 request generator blocks*/
\r
1148 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
\r
1150 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
\r
1152 /* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/
\r
1153 hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
\r
1156 #endif /* DMAMUX1 */
\r
1166 #endif /* HAL_DMA_MODULE_ENABLED */
\r
1175 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\r