2 ******************************************************************************
3 * @file stm32f7xx_hal_dma.c
4 * @author MCD Application Team
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 Stream
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 Stream, program the required configuration through the following parameters:
25 Transfer Direction, Source and Destination data formats,
26 Circular, Normal or peripheral flow control mode, Stream 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 -@- The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
59 possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
60 Half-Word data size for the peripheral to access its data register and set Word data size
61 for the Memory to gain in access time. Each two half words will be packed and written in
62 a single access to a Word in the Memory).
64 -@- When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
65 and Destination. In this case the Peripheral Data Size will be applied to both Source
68 *** DMA HAL driver macros list ***
69 =============================================
71 Below the list of most used macros in DMA HAL driver.
73 (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream.
74 (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream.
75 (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level.
76 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts.
77 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts.
78 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream interrupt has occurred or not.
81 (@) You can refer to the DMA HAL driver header file for more useful macros
84 ******************************************************************************
87 * <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
89 * Redistribution and use in source and binary forms, with or without modification,
90 * are permitted provided that the following conditions are met:
91 * 1. Redistributions of source code must retain the above copyright notice,
92 * this list of conditions and the following disclaimer.
93 * 2. Redistributions in binary form must reproduce the above copyright notice,
94 * this list of conditions and the following disclaimer in the documentation
95 * and/or other materials provided with the distribution.
96 * 3. Neither the name of STMicroelectronics nor the names of its contributors
97 * may be used to endorse or promote products derived from this software
98 * without specific prior written permission.
100 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
101 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
102 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
103 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
104 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
105 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
106 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
107 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
108 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
109 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
111 ******************************************************************************
114 /* Includes ------------------------------------------------------------------*/
115 #include "stm32f7xx_hal.h"
117 /** @addtogroup STM32F7xx_HAL_Driver
121 /** @defgroup DMA DMA
122 * @brief DMA HAL module driver
126 #ifdef HAL_DMA_MODULE_ENABLED
128 /* Private types -------------------------------------------------------------*/
131 __IO
uint32_t ISR
; /*!< DMA interrupt status register */
132 __IO
uint32_t Reserved0
;
133 __IO
uint32_t IFCR
; /*!< DMA interrupt flag clear register */
134 } DMA_Base_Registers
;
136 /* Private variables ---------------------------------------------------------*/
137 /* Private constants ---------------------------------------------------------*/
138 /** @addtogroup DMA_Private_Constants
141 #define HAL_TIMEOUT_DMA_ABORT ((uint32_t)5) /* 5 ms */
145 /* Private macros ------------------------------------------------------------*/
146 /* Private functions ---------------------------------------------------------*/
147 /** @addtogroup DMA_Private_Functions
150 static void DMA_SetConfig(DMA_HandleTypeDef
*hdma
, uint32_t SrcAddress
, uint32_t DstAddress
, uint32_t DataLength
);
151 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef
*hdma
);
152 static HAL_StatusTypeDef
DMA_CheckFifoParam(DMA_HandleTypeDef
*hdma
);
158 /* Exported functions ---------------------------------------------------------*/
159 /** @addtogroup DMA_Exported_Functions
163 /** @addtogroup DMA_Exported_Functions_Group1
166 ===============================================================================
167 ##### Initialization and de-initialization functions #####
168 ===============================================================================
170 This section provides functions allowing to initialize the DMA Stream source
171 and destination addresses, incrementation and data sizes, transfer direction,
172 circular/normal mode selection, memory-to-memory mode selection and Stream priority value.
174 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
182 * @brief Initialize the DMA according to the specified
183 * parameters in the DMA_InitTypeDef and create the associated handle.
184 * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
185 * the configuration information for the specified DMA Stream.
188 HAL_StatusTypeDef
HAL_DMA_Init(DMA_HandleTypeDef
*hdma
)
191 uint32_t tickstart
= HAL_GetTick();
192 DMA_Base_Registers
*regs
;
194 /* Check the DMA peripheral state */
200 /* Check the parameters */
201 assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma
->Instance
));
202 assert_param(IS_DMA_CHANNEL(hdma
->Init
.Channel
));
203 assert_param(IS_DMA_DIRECTION(hdma
->Init
.Direction
));
204 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma
->Init
.PeriphInc
));
205 assert_param(IS_DMA_MEMORY_INC_STATE(hdma
->Init
.MemInc
));
206 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma
->Init
.PeriphDataAlignment
));
207 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma
->Init
.MemDataAlignment
));
208 assert_param(IS_DMA_MODE(hdma
->Init
.Mode
));
209 assert_param(IS_DMA_PRIORITY(hdma
->Init
.Priority
));
210 assert_param(IS_DMA_FIFO_MODE_STATE(hdma
->Init
.FIFOMode
));
211 /* Check the memory burst, peripheral burst and FIFO threshold parameters only
212 when FIFO mode is enabled */
213 if(hdma
->Init
.FIFOMode
!= DMA_FIFOMODE_DISABLE
)
215 assert_param(IS_DMA_FIFO_THRESHOLD(hdma
->Init
.FIFOThreshold
));
216 assert_param(IS_DMA_MEMORY_BURST(hdma
->Init
.MemBurst
));
217 assert_param(IS_DMA_PERIPHERAL_BURST(hdma
->Init
.PeriphBurst
));
220 /* Allocate lock resource */
223 /* Change DMA peripheral state */
224 hdma
->State
= HAL_DMA_STATE_BUSY
;
226 /* Disable the peripheral */
227 __HAL_DMA_DISABLE(hdma
);
229 /* Check if the DMA Stream is effectively disabled */
230 while((hdma
->Instance
->CR
& DMA_SxCR_EN
) != RESET
)
232 /* Check for the Timeout */
233 if((HAL_GetTick() - tickstart
) > HAL_TIMEOUT_DMA_ABORT
)
235 /* Update error code */
236 hdma
->ErrorCode
= HAL_DMA_ERROR_TIMEOUT
;
238 /* Change the DMA state */
239 hdma
->State
= HAL_DMA_STATE_TIMEOUT
;
245 /* Get the CR register value */
246 tmp
= hdma
->Instance
->CR
;
248 /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
249 tmp
&= ((uint32_t)~(DMA_SxCR_CHSEL
| DMA_SxCR_MBURST
| DMA_SxCR_PBURST
| \
250 DMA_SxCR_PL
| DMA_SxCR_MSIZE
| DMA_SxCR_PSIZE
| \
251 DMA_SxCR_MINC
| DMA_SxCR_PINC
| DMA_SxCR_CIRC
| \
252 DMA_SxCR_DIR
| DMA_SxCR_CT
| DMA_SxCR_DBM
));
254 /* Prepare the DMA Stream configuration */
255 tmp
|= hdma
->Init
.Channel
| hdma
->Init
.Direction
|
256 hdma
->Init
.PeriphInc
| hdma
->Init
.MemInc
|
257 hdma
->Init
.PeriphDataAlignment
| hdma
->Init
.MemDataAlignment
|
258 hdma
->Init
.Mode
| hdma
->Init
.Priority
;
260 /* the Memory burst and peripheral burst are not used when the FIFO is disabled */
261 if(hdma
->Init
.FIFOMode
== DMA_FIFOMODE_ENABLE
)
263 /* Get memory burst and peripheral burst */
264 tmp
|= hdma
->Init
.MemBurst
| hdma
->Init
.PeriphBurst
;
267 /* Write to DMA Stream CR register */
268 hdma
->Instance
->CR
= tmp
;
270 /* Get the FCR register value */
271 tmp
= hdma
->Instance
->FCR
;
273 /* Clear Direct mode and FIFO threshold bits */
274 tmp
&= (uint32_t)~(DMA_SxFCR_DMDIS
| DMA_SxFCR_FTH
);
276 /* Prepare the DMA Stream FIFO configuration */
277 tmp
|= hdma
->Init
.FIFOMode
;
279 /* the FIFO threshold is not used when the FIFO mode is disabled */
280 if(hdma
->Init
.FIFOMode
== DMA_FIFOMODE_ENABLE
)
282 /* Get the FIFO threshold */
283 tmp
|= hdma
->Init
.FIFOThreshold
;
285 if (DMA_CheckFifoParam(hdma
) != HAL_OK
)
287 /* Update error code */
288 hdma
->ErrorCode
= HAL_DMA_ERROR_PARAM
;
290 /* Change the DMA state */
291 hdma
->State
= HAL_DMA_STATE_READY
;
297 /* Write to DMA Stream FCR */
298 hdma
->Instance
->FCR
= tmp
;
300 /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
301 DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
302 regs
= (DMA_Base_Registers
*)DMA_CalcBaseAndBitshift(hdma
);
304 /* Clear all interrupt flags */
305 regs
->IFCR
= 0x3FU
<< hdma
->StreamIndex
;
307 /* Initialize the error code */
308 hdma
->ErrorCode
= HAL_DMA_ERROR_NONE
;
310 /* Initialize the DMA state */
311 hdma
->State
= HAL_DMA_STATE_READY
;
317 * @brief DeInitializes the DMA peripheral
318 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
319 * the configuration information for the specified DMA Stream.
322 HAL_StatusTypeDef
HAL_DMA_DeInit(DMA_HandleTypeDef
*hdma
)
324 DMA_Base_Registers
*regs
;
326 /* Check the DMA peripheral state */
332 /* Check the DMA peripheral state */
333 if(hdma
->State
== HAL_DMA_STATE_BUSY
)
335 /* Return error status */
339 /* Disable the selected DMA Streamx */
340 __HAL_DMA_DISABLE(hdma
);
342 /* Reset DMA Streamx control register */
343 hdma
->Instance
->CR
= 0U;
345 /* Reset DMA Streamx number of data to transfer register */
346 hdma
->Instance
->NDTR
= 0U;
348 /* Reset DMA Streamx peripheral address register */
349 hdma
->Instance
->PAR
= 0U;
351 /* Reset DMA Streamx memory 0 address register */
352 hdma
->Instance
->M0AR
= 0U;
354 /* Reset DMA Streamx memory 1 address register */
355 hdma
->Instance
->M1AR
= 0U;
357 /* Reset DMA Streamx FIFO control register */
358 hdma
->Instance
->FCR
= (uint32_t)0x00000021U
;
360 /* Get DMA steam Base Address */
361 regs
= (DMA_Base_Registers
*)DMA_CalcBaseAndBitshift(hdma
);
363 /* Clear all interrupt flags at correct offset within the register */
364 regs
->IFCR
= 0x3FU
<< hdma
->StreamIndex
;
366 /* Initialize the error code */
367 hdma
->ErrorCode
= HAL_DMA_ERROR_NONE
;
369 /* Initialize the DMA state */
370 hdma
->State
= HAL_DMA_STATE_RESET
;
382 /** @addtogroup DMA_Exported_Functions_Group2
385 ===============================================================================
386 ##### IO operation functions #####
387 ===============================================================================
388 [..] This section provides functions allowing to:
389 (+) Configure the source, destination address and data length and Start DMA transfer
390 (+) Configure the source, destination address and data length and
391 Start DMA transfer with interrupt
392 (+) Abort DMA transfer
393 (+) Poll for transfer complete
394 (+) Handle DMA interrupt request
401 * @brief Starts the DMA Transfer.
402 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
403 * the configuration information for the specified DMA Stream.
404 * @param SrcAddress: The source memory Buffer address
405 * @param DstAddress: The destination memory Buffer address
406 * @param DataLength: The length of data to be transferred from source to destination
409 HAL_StatusTypeDef
HAL_DMA_Start(DMA_HandleTypeDef
*hdma
, uint32_t SrcAddress
, uint32_t DstAddress
, uint32_t DataLength
)
411 HAL_StatusTypeDef status
= HAL_OK
;
413 /* Check the parameters */
414 assert_param(IS_DMA_BUFFER_SIZE(DataLength
));
419 if(HAL_DMA_STATE_READY
== hdma
->State
)
421 /* Change DMA peripheral state */
422 hdma
->State
= HAL_DMA_STATE_BUSY
;
424 /* Initialize the error code */
425 hdma
->ErrorCode
= HAL_DMA_ERROR_NONE
;
427 /* Configure the source, destination address and the data length */
428 DMA_SetConfig(hdma
, SrcAddress
, DstAddress
, DataLength
);
430 /* Enable the Peripheral */
431 __HAL_DMA_ENABLE(hdma
);
435 /* Process unlocked */
438 /* Return error status */
445 * @brief Start the DMA Transfer with interrupt enabled.
446 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
447 * the configuration information for the specified DMA Stream.
448 * @param SrcAddress: The source memory Buffer address
449 * @param DstAddress: The destination memory Buffer address
450 * @param DataLength: The length of data to be transferred from source to destination
453 HAL_StatusTypeDef
HAL_DMA_Start_IT(DMA_HandleTypeDef
*hdma
, uint32_t SrcAddress
, uint32_t DstAddress
, uint32_t DataLength
)
455 HAL_StatusTypeDef status
= HAL_OK
;
457 /* calculate DMA base and stream number */
458 DMA_Base_Registers
*regs
= (DMA_Base_Registers
*)hdma
->StreamBaseAddress
;
460 /* Check the parameters */
461 assert_param(IS_DMA_BUFFER_SIZE(DataLength
));
466 if(HAL_DMA_STATE_READY
== hdma
->State
)
468 /* Change DMA peripheral state */
469 hdma
->State
= HAL_DMA_STATE_BUSY
;
471 /* Initialize the error code */
472 hdma
->ErrorCode
= HAL_DMA_ERROR_NONE
;
474 /* Configure the source, destination address and the data length */
475 DMA_SetConfig(hdma
, SrcAddress
, DstAddress
, DataLength
);
477 /* Clear all interrupt flags at correct offset within the register */
478 regs
->IFCR
= 0x3FU
<< hdma
->StreamIndex
;
480 /* Enable Common interrupts*/
481 hdma
->Instance
->CR
|= DMA_IT_TC
| DMA_IT_TE
| DMA_IT_DME
;
482 hdma
->Instance
->FCR
|= DMA_IT_FE
;
484 if(hdma
->XferHalfCpltCallback
!= NULL
)
486 hdma
->Instance
->CR
|= DMA_IT_HT
;
489 /* Enable the Peripheral */
490 __HAL_DMA_ENABLE(hdma
);
494 /* Process unlocked */
497 /* Return error status */
505 * @brief Aborts the DMA Transfer.
506 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
507 * the configuration information for the specified DMA Stream.
509 * @note After disabling a DMA Stream, a check for wait until the DMA Stream is
510 * effectively disabled is added. If a Stream is disabled
511 * while a data transfer is ongoing, the current data will be transferred
512 * and the Stream will be effectively disabled only after the transfer of
513 * this single data is finished.
516 HAL_StatusTypeDef
HAL_DMA_Abort(DMA_HandleTypeDef
*hdma
)
518 /* calculate DMA base and stream number */
519 DMA_Base_Registers
*regs
= (DMA_Base_Registers
*)hdma
->StreamBaseAddress
;
521 uint32_t tickstart
= HAL_GetTick();
523 if(hdma
->State
!= HAL_DMA_STATE_BUSY
)
525 hdma
->ErrorCode
= HAL_DMA_ERROR_NO_XFER
;
527 /* Process Unlocked */
534 /* Disable all the transfer interrupts */
535 hdma
->Instance
->CR
&= ~(DMA_IT_TC
| DMA_IT_TE
| DMA_IT_DME
);
536 hdma
->Instance
->FCR
&= ~(DMA_IT_FE
);
538 if((hdma
->XferHalfCpltCallback
!= NULL
) || (hdma
->XferM1HalfCpltCallback
!= NULL
))
540 hdma
->Instance
->CR
&= ~(DMA_IT_HT
);
543 /* Disable the stream */
544 __HAL_DMA_DISABLE(hdma
);
546 /* Check if the DMA Stream is effectively disabled */
547 while((hdma
->Instance
->CR
& DMA_SxCR_EN
) != RESET
)
549 /* Check for the Timeout */
550 if((HAL_GetTick() - tickstart
) > HAL_TIMEOUT_DMA_ABORT
)
552 /* Update error code */
553 hdma
->ErrorCode
= HAL_DMA_ERROR_TIMEOUT
;
555 /* Process Unlocked */
558 /* Change the DMA state */
559 hdma
->State
= HAL_DMA_STATE_TIMEOUT
;
565 /* Clear all interrupt flags at correct offset within the register */
566 regs
->IFCR
= 0x3FU
<< hdma
->StreamIndex
;
568 /* Process Unlocked */
571 /* Change the DMA state*/
572 hdma
->State
= HAL_DMA_STATE_READY
;
578 * @brief Aborts the DMA Transfer in Interrupt mode.
579 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
580 * the configuration information for the specified DMA Stream.
583 HAL_StatusTypeDef
HAL_DMA_Abort_IT(DMA_HandleTypeDef
*hdma
)
585 if(hdma
->State
!= HAL_DMA_STATE_BUSY
)
587 hdma
->ErrorCode
= HAL_DMA_ERROR_NO_XFER
;
592 /* Set Abort State */
593 hdma
->State
= HAL_DMA_STATE_ABORT
;
595 /* Disable the stream */
596 __HAL_DMA_DISABLE(hdma
);
603 * @brief Polling for transfer complete.
604 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
605 * the configuration information for the specified DMA Stream.
606 * @param CompleteLevel: Specifies the DMA level complete.
607 * @note The polling mode is kept in this version for legacy. it is recommanded to use the IT model instead.
608 * This model could be used for debug purpose.
609 * @note The HAL_DMA_PollForTransfer API cannot be used in circular and double buffering mode (automatic circular mode).
610 * @param Timeout: Timeout duration.
613 HAL_StatusTypeDef
HAL_DMA_PollForTransfer(DMA_HandleTypeDef
*hdma
, HAL_DMA_LevelCompleteTypeDef CompleteLevel
, uint32_t Timeout
)
615 HAL_StatusTypeDef status
= HAL_OK
;
617 uint32_t tickstart
= HAL_GetTick();
620 /* calculate DMA base and stream number */
621 DMA_Base_Registers
*regs
;
623 /* Polling mode not supported in circular mode and double buffering mode */
624 if ((hdma
->Instance
->CR
& DMA_SxCR_CIRC
) != RESET
)
626 hdma
->ErrorCode
= HAL_DMA_ERROR_NOT_SUPPORTED
;
630 /* Get the level transfer complete flag */
631 if(CompleteLevel
== HAL_DMA_FULL_TRANSFER
)
633 /* Transfer Complete flag */
634 temp
= DMA_FLAG_TCIF0_4
<< hdma
->StreamIndex
;
638 /* Half Transfer Complete flag */
639 temp
= DMA_FLAG_HTIF0_4
<< hdma
->StreamIndex
;
642 regs
= (DMA_Base_Registers
*)hdma
->StreamBaseAddress
;
645 while((tmpisr
& temp
) == RESET
)
647 /* Check for the Timeout (Not applicable in circular mode)*/
648 if(Timeout
!= HAL_MAX_DELAY
)
650 if((Timeout
== 0)||((HAL_GetTick() - tickstart
) > Timeout
))
652 /* Update error code */
653 hdma
->ErrorCode
= HAL_DMA_ERROR_TIMEOUT
;
655 /* Process Unlocked */
658 /* Change the DMA state */
659 hdma
->State
= HAL_DMA_STATE_READY
;
665 if((tmpisr
& (DMA_FLAG_TEIF0_4
<< hdma
->StreamIndex
)) != RESET
)
667 /* Update error code */
668 hdma
->ErrorCode
|= HAL_DMA_ERROR_TE
;
670 /* Clear the transfer error flag */
671 regs
->IFCR
= DMA_FLAG_TEIF0_4
<< hdma
->StreamIndex
;
674 if((tmpisr
& (DMA_FLAG_FEIF0_4
<< hdma
->StreamIndex
)) != RESET
)
676 /* Update error code */
677 hdma
->ErrorCode
|= HAL_DMA_ERROR_FE
;
679 /* Clear the FIFO error flag */
680 regs
->IFCR
= DMA_FLAG_FEIF0_4
<< hdma
->StreamIndex
;
683 if((tmpisr
& (DMA_FLAG_DMEIF0_4
<< hdma
->StreamIndex
)) != RESET
)
685 /* Update error code */
686 hdma
->ErrorCode
|= HAL_DMA_ERROR_DME
;
688 /* Clear the Direct Mode error flag */
689 regs
->IFCR
= DMA_FLAG_DMEIF0_4
<< hdma
->StreamIndex
;
693 if(hdma
->ErrorCode
!= HAL_DMA_ERROR_NONE
)
695 if((hdma
->ErrorCode
& HAL_DMA_ERROR_TE
) != RESET
)
699 /* Clear the half transfer and transfer complete flags */
700 regs
->IFCR
= (DMA_FLAG_HTIF0_4
| DMA_FLAG_TCIF0_4
) << hdma
->StreamIndex
;
702 /* Process Unlocked */
705 /* Change the DMA state */
706 hdma
->State
= HAL_DMA_STATE_READY
;
714 /* Get the level transfer complete flag */
715 if(CompleteLevel
== HAL_DMA_FULL_TRANSFER
)
717 /* Clear the half transfer and transfer complete flags */
718 regs
->IFCR
= (DMA_FLAG_HTIF0_4
| DMA_FLAG_TCIF0_4
) << hdma
->StreamIndex
;
720 /* Process Unlocked */
723 hdma
->State
= HAL_DMA_STATE_READY
;
727 /* Clear the half transfer and transfer complete flags */
728 regs
->IFCR
= (DMA_FLAG_HTIF0_4
) << hdma
->StreamIndex
;
735 * @brief Handles DMA interrupt request.
736 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
737 * the configuration information for the specified DMA Stream.
740 void HAL_DMA_IRQHandler(DMA_HandleTypeDef
*hdma
)
743 __IO
uint32_t count
= 0;
744 uint32_t timeout
= SystemCoreClock
/ 9600;
746 /* calculate DMA base and stream number */
747 DMA_Base_Registers
*regs
= (DMA_Base_Registers
*)hdma
->StreamBaseAddress
;
751 /* Transfer Error Interrupt management ***************************************/
752 if ((tmpisr
& (DMA_FLAG_TEIF0_4
<< hdma
->StreamIndex
)) != RESET
)
754 if(__HAL_DMA_GET_IT_SOURCE(hdma
, DMA_IT_TE
) != RESET
)
756 /* Disable the transfer error interrupt */
757 hdma
->Instance
->CR
&= ~(DMA_IT_TE
);
759 /* Clear the transfer error flag */
760 regs
->IFCR
= DMA_FLAG_TEIF0_4
<< hdma
->StreamIndex
;
762 /* Update error code */
763 hdma
->ErrorCode
|= HAL_DMA_ERROR_TE
;
766 /* FIFO Error Interrupt management ******************************************/
767 if ((tmpisr
& (DMA_FLAG_FEIF0_4
<< hdma
->StreamIndex
)) != RESET
)
769 if(__HAL_DMA_GET_IT_SOURCE(hdma
, DMA_IT_FE
) != RESET
)
771 /* Clear the FIFO error flag */
772 regs
->IFCR
= DMA_FLAG_FEIF0_4
<< hdma
->StreamIndex
;
774 /* Update error code */
775 hdma
->ErrorCode
|= HAL_DMA_ERROR_FE
;
778 /* Direct Mode Error Interrupt management ***********************************/
779 if ((tmpisr
& (DMA_FLAG_DMEIF0_4
<< hdma
->StreamIndex
)) != RESET
)
781 if(__HAL_DMA_GET_IT_SOURCE(hdma
, DMA_IT_DME
) != RESET
)
783 /* Clear the direct mode error flag */
784 regs
->IFCR
= DMA_FLAG_DMEIF0_4
<< hdma
->StreamIndex
;
786 /* Update error code */
787 hdma
->ErrorCode
|= HAL_DMA_ERROR_DME
;
790 /* Half Transfer Complete Interrupt management ******************************/
791 if ((tmpisr
& (DMA_FLAG_HTIF0_4
<< hdma
->StreamIndex
)) != RESET
)
793 if(__HAL_DMA_GET_IT_SOURCE(hdma
, DMA_IT_HT
) != RESET
)
795 /* Clear the half transfer complete flag */
796 regs
->IFCR
= DMA_FLAG_HTIF0_4
<< hdma
->StreamIndex
;
798 /* Multi_Buffering mode enabled */
799 if(((hdma
->Instance
->CR
) & (uint32_t)(DMA_SxCR_DBM
)) != RESET
)
801 /* Current memory buffer used is Memory 0 */
802 if((hdma
->Instance
->CR
& DMA_SxCR_CT
) == RESET
)
804 if(hdma
->XferHalfCpltCallback
!= NULL
)
806 /* Half transfer callback */
807 hdma
->XferHalfCpltCallback(hdma
);
810 /* Current memory buffer used is Memory 1 */
813 if(hdma
->XferM1HalfCpltCallback
!= NULL
)
815 /* Half transfer callback */
816 hdma
->XferM1HalfCpltCallback(hdma
);
822 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
823 if((hdma
->Instance
->CR
& DMA_SxCR_CIRC
) == RESET
)
825 /* Disable the half transfer interrupt */
826 hdma
->Instance
->CR
&= ~(DMA_IT_HT
);
829 if(hdma
->XferHalfCpltCallback
!= NULL
)
831 /* Half transfer callback */
832 hdma
->XferHalfCpltCallback(hdma
);
837 /* Transfer Complete Interrupt management ***********************************/
838 if ((tmpisr
& (DMA_FLAG_TCIF0_4
<< hdma
->StreamIndex
)) != RESET
)
840 if(__HAL_DMA_GET_IT_SOURCE(hdma
, DMA_IT_TC
) != RESET
)
842 /* Clear the transfer complete flag */
843 regs
->IFCR
= DMA_FLAG_TCIF0_4
<< hdma
->StreamIndex
;
845 if(HAL_DMA_STATE_ABORT
== hdma
->State
)
847 /* Disable all the transfer interrupts */
848 hdma
->Instance
->CR
&= ~(DMA_IT_TC
| DMA_IT_TE
| DMA_IT_DME
);
849 hdma
->Instance
->FCR
&= ~(DMA_IT_FE
);
851 if((hdma
->XferHalfCpltCallback
!= NULL
) || (hdma
->XferM1HalfCpltCallback
!= NULL
))
853 hdma
->Instance
->CR
&= ~(DMA_IT_HT
);
856 /* Clear all interrupt flags at correct offset within the register */
857 regs
->IFCR
= 0x3FU
<< hdma
->StreamIndex
;
859 /* Process Unlocked */
862 /* Change the DMA state */
863 hdma
->State
= HAL_DMA_STATE_READY
;
865 if(hdma
->XferAbortCallback
!= NULL
)
867 hdma
->XferAbortCallback(hdma
);
872 if(((hdma
->Instance
->CR
) & (uint32_t)(DMA_SxCR_DBM
)) != RESET
)
874 /* Current memory buffer used is Memory 0 */
875 if((hdma
->Instance
->CR
& DMA_SxCR_CT
) == RESET
)
877 if(hdma
->XferM1CpltCallback
!= NULL
)
879 /* Transfer complete Callback for memory1 */
880 hdma
->XferM1CpltCallback(hdma
);
883 /* Current memory buffer used is Memory 1 */
886 if(hdma
->XferCpltCallback
!= NULL
)
888 /* Transfer complete Callback for memory0 */
889 hdma
->XferCpltCallback(hdma
);
893 /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
896 if((hdma
->Instance
->CR
& DMA_SxCR_CIRC
) == RESET
)
898 /* Disable the transfer complete interrupt */
899 hdma
->Instance
->CR
&= ~(DMA_IT_TC
);
901 /* Process Unlocked */
904 /* Change the DMA state */
905 hdma
->State
= HAL_DMA_STATE_READY
;
908 if(hdma
->XferCpltCallback
!= NULL
)
910 /* Transfer complete callback */
911 hdma
->XferCpltCallback(hdma
);
917 /* manage error case */
918 if(hdma
->ErrorCode
!= HAL_DMA_ERROR_NONE
)
920 if((hdma
->ErrorCode
& HAL_DMA_ERROR_TE
) != RESET
)
922 hdma
->State
= HAL_DMA_STATE_ABORT
;
924 /* Disable the stream */
925 __HAL_DMA_DISABLE(hdma
);
929 if (++count
> timeout
)
934 while((hdma
->Instance
->CR
& DMA_SxCR_EN
) != RESET
);
936 /* Process Unlocked */
939 /* Change the DMA state */
940 hdma
->State
= HAL_DMA_STATE_READY
;
943 if(hdma
->XferErrorCallback
!= NULL
)
945 /* Transfer error callback */
946 hdma
->XferErrorCallback(hdma
);
952 * @brief Register callbacks
953 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
954 * the configuration information for the specified DMA Stream.
955 * @param CallbackID: User Callback identifer
956 * a DMA_HandleTypeDef structure as parameter.
957 * @param pCallback: pointer to private callbacsk function which has pointer to
958 * a DMA_HandleTypeDef structure as parameter.
961 HAL_StatusTypeDef
HAL_DMA_RegisterCallback(DMA_HandleTypeDef
*hdma
, HAL_DMA_CallbackIDTypeDef CallbackID
, void (* pCallback
)(DMA_HandleTypeDef
*_hdma
))
964 HAL_StatusTypeDef status
= HAL_OK
;
969 if(HAL_DMA_STATE_READY
== hdma
->State
)
973 case HAL_DMA_XFER_CPLT_CB_ID
:
974 hdma
->XferCpltCallback
= pCallback
;
977 case HAL_DMA_XFER_HALFCPLT_CB_ID
:
978 hdma
->XferHalfCpltCallback
= pCallback
;
981 case HAL_DMA_XFER_M1CPLT_CB_ID
:
982 hdma
->XferM1CpltCallback
= pCallback
;
985 case HAL_DMA_XFER_M1HALFCPLT_CB_ID
:
986 hdma
->XferM1HalfCpltCallback
= pCallback
;
989 case HAL_DMA_XFER_ERROR_CB_ID
:
990 hdma
->XferErrorCallback
= pCallback
;
993 case HAL_DMA_XFER_ABORT_CB_ID
:
994 hdma
->XferAbortCallback
= pCallback
;
1003 /* Return error status */
1014 * @brief UnRegister callbacks
1015 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1016 * the configuration information for the specified DMA Stream.
1017 * @param CallbackID: User Callback identifer
1018 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
1019 * @retval HAL status
1021 HAL_StatusTypeDef
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef
*hdma
, HAL_DMA_CallbackIDTypeDef CallbackID
)
1023 HAL_StatusTypeDef status
= HAL_OK
;
1025 /* Process locked */
1028 if(HAL_DMA_STATE_READY
== hdma
->State
)
1032 case HAL_DMA_XFER_CPLT_CB_ID
:
1033 hdma
->XferCpltCallback
= NULL
;
1036 case HAL_DMA_XFER_HALFCPLT_CB_ID
:
1037 hdma
->XferHalfCpltCallback
= NULL
;
1040 case HAL_DMA_XFER_M1CPLT_CB_ID
:
1041 hdma
->XferM1CpltCallback
= NULL
;
1044 case HAL_DMA_XFER_M1HALFCPLT_CB_ID
:
1045 hdma
->XferM1HalfCpltCallback
= NULL
;
1048 case HAL_DMA_XFER_ERROR_CB_ID
:
1049 hdma
->XferErrorCallback
= NULL
;
1052 case HAL_DMA_XFER_ABORT_CB_ID
:
1053 hdma
->XferAbortCallback
= NULL
;
1056 case HAL_DMA_XFER_ALL_CB_ID
:
1057 hdma
->XferCpltCallback
= NULL
;
1058 hdma
->XferHalfCpltCallback
= NULL
;
1059 hdma
->XferM1CpltCallback
= NULL
;
1060 hdma
->XferM1HalfCpltCallback
= NULL
;
1061 hdma
->XferErrorCallback
= NULL
;
1062 hdma
->XferAbortCallback
= NULL
;
1085 /** @addtogroup DMA_Exported_Functions_Group3
1088 ===============================================================================
1089 ##### State and Errors functions #####
1090 ===============================================================================
1092 This subsection provides functions allowing to
1093 (+) Check the DMA state
1101 * @brief Returns the DMA state.
1102 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1103 * the configuration information for the specified DMA Stream.
1106 HAL_DMA_StateTypeDef
HAL_DMA_GetState(DMA_HandleTypeDef
*hdma
)
1112 * @brief Return the DMA error code
1113 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
1114 * the configuration information for the specified DMA Stream.
1115 * @retval DMA Error Code
1117 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef
*hdma
)
1119 return hdma
->ErrorCode
;
1130 /** @addtogroup DMA_Private_Functions
1135 * @brief Sets the DMA Transfer parameter.
1136 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1137 * the configuration information for the specified DMA Stream.
1138 * @param SrcAddress: The source memory Buffer address
1139 * @param DstAddress: The destination memory Buffer address
1140 * @param DataLength: The length of data to be transferred from source to destination
1141 * @retval HAL status
1143 static void DMA_SetConfig(DMA_HandleTypeDef
*hdma
, uint32_t SrcAddress
, uint32_t DstAddress
, uint32_t DataLength
)
1146 hdma
->Instance
->CR
&= (uint32_t)(~DMA_SxCR_DBM
);
1148 /* Configure DMA Stream data length */
1149 hdma
->Instance
->NDTR
= DataLength
;
1151 /* Peripheral to Memory */
1152 if((hdma
->Init
.Direction
) == DMA_MEMORY_TO_PERIPH
)
1154 /* Configure DMA Stream destination address */
1155 hdma
->Instance
->PAR
= DstAddress
;
1157 /* Configure DMA Stream source address */
1158 hdma
->Instance
->M0AR
= SrcAddress
;
1160 /* Memory to Peripheral */
1163 /* Configure DMA Stream source address */
1164 hdma
->Instance
->PAR
= SrcAddress
;
1166 /* Configure DMA Stream destination address */
1167 hdma
->Instance
->M0AR
= DstAddress
;
1172 * @brief Returns the DMA Stream base address depending on stream number
1173 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1174 * the configuration information for the specified DMA Stream.
1175 * @retval Stream base address
1177 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef
*hdma
)
1179 uint32_t stream_number
= (((uint32_t)hdma
->Instance
& 0xFFU
) - 16U) / 24U;
1181 /* lookup table for necessary bitshift of flags within status registers */
1182 static const uint8_t flagBitshiftOffset
[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U};
1183 hdma
->StreamIndex
= flagBitshiftOffset
[stream_number
];
1185 if (stream_number
> 3U)
1187 /* return pointer to HISR and HIFCR */
1188 hdma
->StreamBaseAddress
= (((uint32_t)hdma
->Instance
& (uint32_t)(~0x3FFU
)) + 4U);
1192 /* return pointer to LISR and LIFCR */
1193 hdma
->StreamBaseAddress
= ((uint32_t)hdma
->Instance
& (uint32_t)(~0x3FFU
));
1196 return hdma
->StreamBaseAddress
;
1200 * @brief Check compatibility between FIFO threshold level and size of the memory burst
1201 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1202 * the configuration information for the specified DMA Stream.
1203 * @retval HAL status
1205 static HAL_StatusTypeDef
DMA_CheckFifoParam(DMA_HandleTypeDef
*hdma
)
1207 HAL_StatusTypeDef status
= HAL_OK
;
1208 uint32_t tmp
= hdma
->Init
.FIFOThreshold
;
1210 /* Memory Data size equal to Byte */
1211 if (hdma
->Init
.MemDataAlignment
== DMA_MDATAALIGN_BYTE
)
1215 case DMA_FIFO_THRESHOLD_1QUARTERFULL
:
1216 if ((hdma
->Init
.MemBurst
& DMA_SxCR_MBURST_1
) == DMA_SxCR_MBURST_1
)
1221 case DMA_FIFO_THRESHOLD_HALFFULL
:
1222 if (hdma
->Init
.MemBurst
== DMA_MBURST_INC16
)
1227 case DMA_FIFO_THRESHOLD_3QUARTERSFULL
:
1228 if ((hdma
->Init
.MemBurst
& DMA_SxCR_MBURST_1
) == DMA_SxCR_MBURST_1
)
1233 case DMA_FIFO_THRESHOLD_FULL
:
1240 /* Memory Data size equal to Half-Word */
1241 else if (hdma
->Init
.MemDataAlignment
== DMA_MDATAALIGN_HALFWORD
)
1245 case DMA_FIFO_THRESHOLD_1QUARTERFULL
:
1248 case DMA_FIFO_THRESHOLD_HALFFULL
:
1249 if ((hdma
->Init
.MemBurst
& DMA_SxCR_MBURST_1
) == DMA_SxCR_MBURST_1
)
1254 case DMA_FIFO_THRESHOLD_3QUARTERSFULL
:
1257 case DMA_FIFO_THRESHOLD_FULL
:
1258 if (hdma
->Init
.MemBurst
== DMA_MBURST_INC16
)
1268 /* Memory Data size equal to Word */
1273 case DMA_FIFO_THRESHOLD_1QUARTERFULL
:
1274 case DMA_FIFO_THRESHOLD_HALFFULL
:
1275 case DMA_FIFO_THRESHOLD_3QUARTERSFULL
:
1278 case DMA_FIFO_THRESHOLD_FULL
:
1279 if ((hdma
->Init
.MemBurst
& DMA_SxCR_MBURST_1
) == DMA_SxCR_MBURST_1
)
1296 #endif /* HAL_DMA_MODULE_ENABLED */
1305 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/