2 ******************************************************************************
3 * @file stm32f1xx_hal_dma.c
4 * @author MCD Application Team
6 * @date 15-December-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 or Normal mode, Channel Priority level, Source and Destination Increment mode,
27 using HAL_DMA_Init() function.
29 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
32 (#) Use HAL_DMA_Abort() function to abort the current transfer
34 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
35 *** Polling mode IO operation ***
36 =================================
38 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
39 address and destination address and the Length of data to be transferred
40 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
41 case a fixed Timeout can be configured by User depending from his application.
43 *** Interrupt mode IO operation ***
44 ===================================
46 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
47 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
48 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
49 Source address and destination address and the Length of data to be transferred.
50 In this case the DMA interrupt is configured
51 (+) Use HAL_DMAy_Channelx_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
52 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
53 add his own function by customization of function pointer XferCpltCallback and
54 XferErrorCallback (i.e a member of DMA handle structure).
56 *** DMA HAL driver macros list ***
57 =============================================
59 Below the list of most used macros in DMA HAL driver.
61 (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
62 (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
63 (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
64 (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
65 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
66 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
67 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not.
70 (@) You can refer to the DMA HAL driver header file for more useful macros
73 ******************************************************************************
76 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
78 * Redistribution and use in source and binary forms, with or without modification,
79 * are permitted provided that the following conditions are met:
80 * 1. Redistributions of source code must retain the above copyright notice,
81 * this list of conditions and the following disclaimer.
82 * 2. Redistributions in binary form must reproduce the above copyright notice,
83 * this list of conditions and the following disclaimer in the documentation
84 * and/or other materials provided with the distribution.
85 * 3. Neither the name of STMicroelectronics nor the names of its contributors
86 * may be used to endorse or promote products derived from this software
87 * without specific prior written permission.
89 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
90 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
91 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
92 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
93 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
94 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
95 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
96 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
97 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
98 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
100 ******************************************************************************
103 /* Includes ------------------------------------------------------------------*/
104 #include "stm32f1xx_hal.h"
106 /** @addtogroup STM32F1xx_HAL_Driver
110 /** @defgroup DMA DMA
111 * @brief DMA HAL module driver
115 #ifdef HAL_DMA_MODULE_ENABLED
117 /* Private typedef -----------------------------------------------------------*/
118 /* Private define ------------------------------------------------------------*/
119 /** @defgroup DMA_Private_Constants DMA Private Constants
122 #define HAL_TIMEOUT_DMA_ABORT ((uint32_t)1000) /* 1s */
127 /* Private macro -------------------------------------------------------------*/
128 /* Private variables ---------------------------------------------------------*/
129 /* Private function prototypes -----------------------------------------------*/
130 /** @defgroup DMA_Private_Functions DMA Private Functions
133 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
138 /* Exported functions ---------------------------------------------------------*/
140 /** @defgroup DMA_Exported_Functions DMA Exported Functions
144 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
145 * @brief Initialization and de-initialization functions
148 ===============================================================================
149 ##### Initialization and de-initialization functions #####
150 ===============================================================================
152 This section provides functions allowing to initialize the DMA Channel source
153 and destination addresses, incrementation and data sizes, transfer direction,
154 circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
156 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
164 * @brief Initializes the DMA according to the specified
165 * parameters in the DMA_InitTypeDef and create the associated handle.
166 * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
167 * the configuration information for the specified DMA Channel.
170 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
174 /* Check the DMA handle allocation */
180 /* Check the parameters */
181 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
182 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
183 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
184 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
185 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
186 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
187 assert_param(IS_DMA_MODE(hdma->Init.Mode));
188 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
190 if(hdma->State == HAL_DMA_STATE_RESET)
192 /* Allocate lock resource and initialize it */
193 hdma-> Lock = HAL_UNLOCKED;
196 /* Change DMA peripheral state */
197 hdma->State = HAL_DMA_STATE_BUSY;
199 /* Get the CR register value */
200 tmp = hdma->Instance->CCR;
202 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR bits */
203 tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \
204 DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \
207 /* Prepare the DMA Channel configuration */
208 tmp |= hdma->Init.Direction |
209 hdma->Init.PeriphInc | hdma->Init.MemInc |
210 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
211 hdma->Init.Mode | hdma->Init.Priority;
213 /* Write to DMA Channel CR register */
214 hdma->Instance->CCR = tmp;
216 /* Initialise the error code */
217 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
219 /* Initialize the DMA state*/
220 hdma->State = HAL_DMA_STATE_READY;
226 * @brief DeInitializes the DMA peripheral
227 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
228 * the configuration information for the specified DMA Channel.
231 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
233 /* Check the DMA handle allocation */
239 /* Check the parameters */
240 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
242 /* Check the DMA peripheral state */
243 if(hdma->State == HAL_DMA_STATE_BUSY)
248 /* Disable the selected DMA Channelx */
249 __HAL_DMA_DISABLE(hdma);
251 /* Reset DMA Channel control register */
252 hdma->Instance->CCR = 0;
254 /* Reset DMA Channel Number of Data to Transfer register */
255 hdma->Instance->CNDTR = 0;
257 /* Reset DMA Channel peripheral address register */
258 hdma->Instance->CPAR = 0;
260 /* Reset DMA Channel memory address register */
261 hdma->Instance->CMAR = 0;
263 /* Clear all flags */
264 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
265 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
266 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
268 /* Initialise the error code */
269 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
271 /* Initialize the DMA state */
272 hdma->State = HAL_DMA_STATE_RESET;
284 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
285 * @brief I/O operation functions
288 ===============================================================================
289 ##### IO operation functions #####
290 ===============================================================================
291 [..] This section provides functions allowing to:
292 (+) Configure the source, destination address and data length and Start DMA transfer
293 (+) Configure the source, destination address and data length and
294 Start DMA transfer with interrupt
295 (+) Abort DMA transfer
296 (+) Poll for transfer complete
297 (+) Handle DMA interrupt request
304 * @brief Starts the DMA Transfer.
305 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
306 * the configuration information for the specified DMA Channel.
307 * @param SrcAddress: The source memory Buffer address
308 * @param DstAddress: The destination memory Buffer address
309 * @param DataLength: The length of data to be transferred from source to destination
312 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
317 /* Change DMA peripheral state */
318 hdma->State = HAL_DMA_STATE_BUSY;
320 /* Check the parameters */
321 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
323 /* Disable the peripheral */
324 __HAL_DMA_DISABLE(hdma);
326 /* Configure the source, destination address and the data length */
327 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
329 /* Enable the Peripheral */
330 __HAL_DMA_ENABLE(hdma);
336 * @brief Start the DMA Transfer with interrupt enabled.
337 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
338 * the configuration information for the specified DMA Channel.
339 * @param SrcAddress: The source memory Buffer address
340 * @param DstAddress: The destination memory Buffer address
341 * @param DataLength: The length of data to be transferred from source to destination
344 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
349 /* Change DMA peripheral state */
350 hdma->State = HAL_DMA_STATE_BUSY;
352 /* Check the parameters */
353 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
355 /* Disable the peripheral */
356 __HAL_DMA_DISABLE(hdma);
358 /* Configure the source, destination address and the data length */
359 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
361 /* Enable the transfer complete interrupt */
362 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TC);
364 /* Enable the Half transfer complete interrupt */
365 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
367 /* Enable the transfer Error interrupt */
368 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TE);
370 /* Enable the Peripheral */
371 __HAL_DMA_ENABLE(hdma);
377 * @brief Aborts the DMA Transfer.
378 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
379 * the configuration information for the specified DMA Channel.
381 * @note After disabling a DMA Channel, a check for wait until the DMA Channel is
382 * effectively disabled is added. If a Channel is disabled
383 * while a data transfer is ongoing, the current data will be transferred
384 * and the Channel will be effectively disabled only after the transfer of
385 * this single data is finished.
388 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
390 uint32_t tickstart = 0x00;
392 /* Disable the channel */
393 __HAL_DMA_DISABLE(hdma);
396 tickstart = HAL_GetTick();
398 /* Check if the DMA Channel is effectively disabled */
399 while((hdma->Instance->CCR & DMA_CCR_EN) != 0)
401 /* Check for the Timeout */
402 if((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
404 /* Update error code */
405 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT);
407 /* Change the DMA state */
408 hdma->State = HAL_DMA_STATE_TIMEOUT;
410 /* Process Unlocked */
416 /* Change the DMA state*/
417 hdma->State = HAL_DMA_STATE_READY;
419 /* Process Unlocked */
426 * @brief Polling for transfer complete.
427 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
428 * the configuration information for the specified DMA Channel.
429 * @param CompleteLevel: Specifies the DMA level complete.
430 * @param Timeout: Timeout duration.
433 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
436 uint32_t tickstart = 0x00;
438 /* Get the level transfer complete flag */
439 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
441 /* Transfer Complete flag */
442 temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma);
446 /* Half Transfer Complete flag */
447 temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma);
451 tickstart = HAL_GetTick();
453 while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET)
455 if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET))
457 /* Clear the transfer error flags */
458 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
460 /* Update error code */
461 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
463 /* Change the DMA state */
464 hdma->State= HAL_DMA_STATE_ERROR;
466 /* Process Unlocked */
471 /* Check for the Timeout */
472 if(Timeout != HAL_MAX_DELAY)
474 if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout))
476 /* Update error code */
477 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT);
479 /* Change the DMA state */
480 hdma->State = HAL_DMA_STATE_TIMEOUT;
482 /* Process Unlocked */
490 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
492 /* Clear the transfer complete flag */
493 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
495 /* The selected Channelx EN bit is cleared (DMA is disabled and
496 all transfers are complete) */
497 hdma->State = HAL_DMA_STATE_READY;
502 /* Clear the half transfer complete flag */
503 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
505 /* The selected Channelx EN bit is cleared (DMA is disabled and
506 all transfers of half buffer are complete) */
507 hdma->State = HAL_DMA_STATE_READY_HALF;
510 /* Process unlocked */
517 * @brief Handles DMA interrupt request.
518 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
519 * the configuration information for the specified DMA Channel.
522 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
524 /* Transfer Error Interrupt management ***************************************/
525 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)
527 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET)
529 /* Disable the transfer error interrupt */
530 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE);
532 /* Clear the transfer error flag */
533 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
535 /* Update error code */
536 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
538 /* Change the DMA state */
539 hdma->State = HAL_DMA_STATE_ERROR;
541 /* Process Unlocked */
544 if (hdma->XferErrorCallback != NULL)
546 /* Transfer error callback */
547 hdma->XferErrorCallback(hdma);
552 /* Half Transfer Complete Interrupt management ******************************/
553 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET)
555 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET)
557 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
558 if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
560 /* Disable the half transfer interrupt */
561 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
563 /* Clear the half transfer complete flag */
564 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
566 /* Change DMA peripheral state */
567 hdma->State = HAL_DMA_STATE_READY_HALF;
569 if(hdma->XferHalfCpltCallback != NULL)
571 /* Half transfer callback */
572 hdma->XferHalfCpltCallback(hdma);
577 /* Transfer Complete Interrupt management ***********************************/
578 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET)
580 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET)
582 if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
584 /* Disable the transfer complete interrupt */
585 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC);
587 /* Clear the transfer complete flag */
588 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
590 /* Update error code */
591 SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_NONE);
593 /* Change the DMA state */
594 hdma->State = HAL_DMA_STATE_READY;
596 /* Process Unlocked */
599 if(hdma->XferCpltCallback != NULL)
601 /* Transfer complete callback */
602 hdma->XferCpltCallback(hdma);
612 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State functions
613 * @brief Peripheral State functions
616 ===============================================================================
617 ##### State and Errors functions #####
618 ===============================================================================
620 This subsection provides functions allowing to
621 (+) Check the DMA state
629 * @brief Returns the DMA state.
630 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
631 * the configuration information for the specified DMA Channel.
634 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
640 * @brief Return the DMA error code
641 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
642 * the configuration information for the specified DMA Channel.
643 * @retval DMA Error Code
645 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
647 return hdma->ErrorCode;
658 /** @addtogroup DMA_Private_Functions DMA Private Functions
663 * @brief Sets the DMA Transfer parameter.
664 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
665 * the configuration information for the specified DMA Channel.
666 * @param SrcAddress: The source memory Buffer address
667 * @param DstAddress: The destination memory Buffer address
668 * @param DataLength: The length of data to be transferred from source to destination
671 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
673 /* Configure DMA Channel data length */
674 hdma->Instance->CNDTR = DataLength;
676 /* Peripheral to Memory */
677 if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
679 /* Configure DMA Channel destination address */
680 hdma->Instance->CPAR = DstAddress;
682 /* Configure DMA Channel source address */
683 hdma->Instance->CMAR = SrcAddress;
685 /* Memory to Peripheral */
688 /* Configure DMA Channel source address */
689 hdma->Instance->CPAR = SrcAddress;
691 /* Configure DMA Channel destination address */
692 hdma->Instance->CMAR = DstAddress;
700 #endif /* HAL_DMA_MODULE_ENABLED */
709 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/