2 ******************************************************************************
3 * @file stm32l1xx_hal_dma.c
4 * @author MCD Application Team
6 * @date 5-September-2014
7 * @brief DMA HAL module driver.
9 * This file provides firmware functions to manage the following
10 * functionalities of the Direct Memory Access (DMA) peripheral:
11 * + Initialization and de-initialization functions
12 * + IO operation functions
13 * + Peripheral State and errors functions
15 ==============================================================================
16 ##### How to use this driver #####
17 ==============================================================================
19 (#) Enable and configure the peripheral to be connected to the DMA Channel
20 (except for internal SRAM / FLASH memories: no initialization is
21 necessary) please refer to Reference manual for connection between peripherals
24 (#) For a given Channel, program the required configuration through the following parameters:
25 Transfer Direction, Source and Destination data formats,
26 Circular, Normal or peripheral flow control mode, Channel Priority level,
27 Source and Destination Increment mode, FIFO mode and its Threshold (if needed),
28 Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function.
30 *** Polling mode IO operation ***
31 =================================
33 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
34 address and destination address and the Length of data to be transferred
35 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
36 case a fixed Timeout can be configured by User depending from his application.
38 *** Interrupt mode IO operation ***
39 ===================================
41 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
42 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
43 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
44 Source address and destination address and the Length of data to be transferred. In this
45 case the DMA interrupt is configured
46 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
47 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
48 add his own function by customization of function pointer XferCpltCallback and
49 XferErrorCallback (i.e a member of DMA handle structure).
51 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
54 (#) Use HAL_DMA_Abort() function to abort the current transfer
56 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
58 *** DMA HAL driver macros list ***
59 =============================================
61 Below the list of most used macros in DMA HAL driver.
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 has occurred or not.
72 (@) You can refer to the DMA HAL driver header file for more useful macros
75 ******************************************************************************
78 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
80 * Redistribution and use in source and binary forms, with or without modification,
81 * are permitted provided that the following conditions are met:
82 * 1. Redistributions of source code must retain the above copyright notice,
83 * this list of conditions and the following disclaimer.
84 * 2. Redistributions in binary form must reproduce the above copyright notice,
85 * this list of conditions and the following disclaimer in the documentation
86 * and/or other materials provided with the distribution.
87 * 3. Neither the name of STMicroelectronics nor the names of its contributors
88 * may be used to endorse or promote products derived from this software
89 * without specific prior written permission.
91 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
92 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
94 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
95 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
97 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
98 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
99 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
100 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
102 ******************************************************************************
105 /* Includes ------------------------------------------------------------------*/
106 #include "stm32l1xx_hal.h"
108 /** @addtogroup STM32L1xx_HAL_Driver
112 /** @defgroup DMA DMA
113 * @brief DMA HAL module driver
117 #ifdef HAL_DMA_MODULE_ENABLED
119 /* Private typedef -----------------------------------------------------------*/
120 /* Private define ------------------------------------------------------------*/
121 /** @defgroup DMA_Private_Constants DMA Private Constants
124 #define HAL_TIMEOUT_DMA_ABORT ((uint32_t)1000) /* 1s */
130 /* Private macro -------------------------------------------------------------*/
131 /* Private variables ---------------------------------------------------------*/
132 /* Private function prototypes -----------------------------------------------*/
133 /** @defgroup DMA_Private_Functions DMA Private Functions
136 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
141 /* Private functions ---------------------------------------------------------*/
143 /** @defgroup DMA_Exported_Functions DMA Exported Functions
147 /** @defgroup DMA_Group1 Initialization and de-initialization functions
148 * @brief Initialization and de-initialization functions
151 ===============================================================================
152 ##### Initialization and de-initialization functions #####
153 ===============================================================================
155 This section provides functions allowing to initialize the DMA Channel source
156 and destination addresses, incrementation and data sizes, transfer direction,
157 circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
159 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
167 * @brief Initializes the DMA according to the specified
168 * parameters in the DMA_InitTypeDef and create the associated handle.
169 * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
170 * the configuration information for the specified DMA Channel.
173 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
177 /* Check the DMA peripheral state */
183 /* Check the parameters */
184 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
185 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
186 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
187 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
188 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
189 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
190 assert_param(IS_DMA_MODE(hdma->Init.Mode));
191 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
193 /* Change DMA peripheral state */
194 hdma->State = HAL_DMA_STATE_BUSY;
196 /* Get the CR register value */
197 tmp = hdma->Instance->CCR;
199 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR bits */
200 tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \
201 DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \
204 /* Prepare the DMA Channel configuration */
205 tmp |= hdma->Init.Direction |
206 hdma->Init.PeriphInc | hdma->Init.MemInc |
207 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
208 hdma->Init.Mode | hdma->Init.Priority;
210 /* Write to DMA Channel CR register */
211 hdma->Instance->CCR = tmp;
213 /* Initialise the error code */
214 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
216 /* Initialize the DMA state*/
217 hdma->State = HAL_DMA_STATE_READY;
223 * @brief DeInitializes the DMA peripheral
224 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
225 * the configuration information for the specified DMA Channel.
228 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
230 /* Check the DMA peripheral state */
236 /* Check the DMA peripheral handle */
237 if(hdma->State == HAL_DMA_STATE_BUSY)
242 /* Disable the selected DMA Channelx */
243 __HAL_DMA_DISABLE(hdma);
245 /* Reset DMA Channel control register */
246 hdma->Instance->CCR = 0;
248 /* Reset DMA Channel Number of Data to Transfer register */
249 hdma->Instance->CNDTR = 0;
251 /* Reset DMA Channel peripheral address register */
252 hdma->Instance->CPAR = 0;
254 /* Reset DMA Channel memory address register */
255 hdma->Instance->CMAR = 0;
257 /* Clear all flags */
258 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
259 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
260 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
262 /* Initialise the error code */
263 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
265 /* Initialize the DMA state */
266 hdma->State = HAL_DMA_STATE_RESET;
278 /** @defgroup DMA_Group2 I/O operation functions
279 * @brief I/O operation functions
282 ===============================================================================
283 ##### IO operation functions #####
284 ===============================================================================
285 [..] This section provides functions allowing to:
286 (+) Configure the source, destination address and data length and Start DMA transfer
287 (+) Configure the source, destination address and data length and
288 Start DMA transfer with interrupt
289 (+) Abort DMA transfer
290 (+) Poll for transfer complete
291 (+) Handle DMA interrupt request
298 * @brief Starts the DMA Transfer.
299 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
300 * the configuration information for the specified DMA Channel.
301 * @param SrcAddress: The source memory Buffer address
302 * @param DstAddress: The destination memory Buffer address
303 * @param DataLength: The length of data to be transferred from source to destination
306 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
311 /* Change DMA peripheral state */
312 hdma->State = HAL_DMA_STATE_BUSY;
314 /* Check the parameters */
315 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
317 /* Disable the peripheral */
318 __HAL_DMA_DISABLE(hdma);
320 /* Configure the source, destination address and the data length */
321 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
323 /* Enable the Peripheral */
324 __HAL_DMA_ENABLE(hdma);
330 * @brief Start the DMA Transfer with interrupt enabled.
331 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
332 * the configuration information for the specified DMA Channel.
333 * @param SrcAddress: The source memory Buffer address
334 * @param DstAddress: The destination memory Buffer address
335 * @param DataLength: The length of data to be transferred from source to destination
338 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
343 /* Change DMA peripheral state */
344 hdma->State = HAL_DMA_STATE_BUSY;
346 /* Check the parameters */
347 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
349 /* Disable the peripheral */
350 __HAL_DMA_DISABLE(hdma);
352 /* Configure the source, destination address and the data length */
353 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
355 /* Enable the transfer complete interrupt */
356 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TC);
358 /* Enable the Half transfer complete interrupt */
359 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
361 /* Enable the transfer Error interrupt */
362 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TE);
364 /* Enable the Peripheral */
365 __HAL_DMA_ENABLE(hdma);
371 * @brief Aborts the DMA Transfer.
372 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
373 * the configuration information for the specified DMA Channel.
375 * @note After disabling a DMA Channel, a check for wait until the DMA Channel is
376 * effectively disabled is added. If a Channel is disabled
377 * while a data transfer is ongoing, the current data will be transferred
378 * and the Channel will be effectively disabled only after the transfer of
379 * this single data is finished.
382 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
384 uint32_t tickstart = 0x00;
386 /* Disable the channel */
387 __HAL_DMA_DISABLE(hdma);
390 tickstart = HAL_GetTick();
392 /* Check if the DMA Channel is effectively disabled */
393 while((hdma->Instance->CCR & DMA_CCR_EN) != 0)
395 /* Check for the Timeout */
396 if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
398 /* Update error code */
399 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT);
401 /* Process Unlocked */
404 /* Change the DMA state */
405 hdma->State = HAL_DMA_STATE_TIMEOUT;
410 /* Process Unlocked */
413 /* Change the DMA state*/
414 hdma->State = HAL_DMA_STATE_READY;
420 * @brief Polling for transfer complete.
421 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
422 * the configuration information for the specified DMA Channel.
423 * @param CompleteLevel: Specifies the DMA level complete.
424 * @param Timeout: Timeout duration.
427 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
430 uint32_t tickstart = 0x00;
432 /* Get the level transfer complete flag */
433 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
435 /* Transfer Complete flag */
436 temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma);
440 /* Half Transfer Complete flag */
441 temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma);
445 tickstart = HAL_GetTick();
447 while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET)
449 if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET))
451 /* Clear the transfer error flags */
452 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
454 /* Update error code */
455 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
457 /* Change the DMA state */
458 hdma->State= HAL_DMA_STATE_ERROR;
460 /* Process Unlocked */
465 /* Check for the Timeout */
466 if(Timeout != HAL_MAX_DELAY)
468 if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
470 /* Update error code */
471 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT);
473 /* Change the DMA state */
474 hdma->State= HAL_DMA_STATE_TIMEOUT;
476 /* Process Unlocked */
484 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
486 /* Clear the transfer complete flag */
487 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
489 /* The selected Channelx EN bit is cleared (DMA is disabled and
490 all transfers are complete) */
491 hdma->State = HAL_DMA_STATE_READY;
493 /* Process unlocked */
498 /* Clear the half transfer complete flag */
499 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
501 /* The selected Channelx EN bit is cleared (DMA is disabled and
502 all transfers are complete) */
503 hdma->State = HAL_DMA_STATE_READY_HALF;
504 /* Process unlocked */
512 * @brief Handles DMA interrupt request.
513 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
514 * the configuration information for the specified DMA Channel.
517 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
519 /* Transfer Error Interrupt management ***************************************/
520 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)
522 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET)
524 /* Disable the transfer error interrupt */
525 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE);
527 /* Clear the transfer error flag */
528 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
530 /* Update error code */
531 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
533 /* Change the DMA state */
534 hdma->State = HAL_DMA_STATE_ERROR;
536 /* Process Unlocked */
539 if (hdma->XferErrorCallback != HAL_NULL)
541 /* Transfer error callback */
542 hdma->XferErrorCallback(hdma);
547 /* Half Transfer Complete Interrupt management ******************************/
548 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET)
550 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET)
552 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
553 if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
555 /* Disable the half transfer interrupt */
556 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
558 /* Clear the half transfer complete flag */
559 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
561 /* Change DMA peripheral state */
562 hdma->State = HAL_DMA_STATE_READY_HALF;
564 if(hdma->XferHalfCpltCallback != HAL_NULL)
566 /* Half transfer callback */
567 hdma->XferHalfCpltCallback(hdma);
572 /* Transfer Complete Interrupt management ***********************************/
573 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET)
575 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET)
577 if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
579 /* Disable the transfer complete interrupt */
580 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC);
582 /* Clear the transfer complete flag */
583 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
585 /* Update error code */
586 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_NONE);
588 /* Change the DMA state */
589 hdma->State = HAL_DMA_STATE_READY;
591 /* Process Unlocked */
594 if(hdma->XferCpltCallback != HAL_NULL)
596 /* Transfer complete callback */
597 hdma->XferCpltCallback(hdma);
607 /** @defgroup DMA_Group3 Peripheral State functions
608 * @brief Peripheral State functions
611 ===============================================================================
612 ##### State and Errors functions #####
613 ===============================================================================
615 This subsection provides functions allowing to
616 (+) Check the DMA state
624 * @brief Returns the DMA state.
625 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
626 * the configuration information for the specified DMA Channel.
629 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
635 * @brief Return the DMA error code
636 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
637 * the configuration information for the specified DMA Channel.
638 * @retval DMA Error Code
640 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
642 return hdma->ErrorCode;
653 /** @addtogroup DMA_Private_Functions
658 * @brief Sets the DMA Transfer parameter.
659 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
660 * the configuration information for the specified DMA Channel.
661 * @param SrcAddress: The source memory Buffer address
662 * @param DstAddress: The destination memory Buffer address
663 * @param DataLength: The length of data to be transferred from source to destination
666 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
668 /* Configure DMA Channel data length */
669 hdma->Instance->CNDTR = DataLength;
671 /* Peripheral to Memory */
672 if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
674 /* Configure DMA Channel destination address */
675 hdma->Instance->CPAR = DstAddress;
677 /* Configure DMA Channel source address */
678 hdma->Instance->CMAR = SrcAddress;
680 /* Memory to Peripheral */
683 /* Configure DMA Channel source address */
684 hdma->Instance->CPAR = SrcAddress;
686 /* Configure DMA Channel destination address */
687 hdma->Instance->CMAR = DstAddress;
696 #endif /* HAL_DMA_MODULE_ENABLED */
707 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/