STM32H735xx HAL User Manual
stm32h7xx_hal_dma.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_dma.c
00004   * @author  MCD Application Team
00005   * @brief   DMA HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Direct Memory Access (DMA) peripheral:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *           + Peripheral State and errors functions
00011   ******************************************************************************
00012   * @attention
00013   *
00014   * Copyright (c) 2017 STMicroelectronics.
00015   * All rights reserved.
00016   *
00017   * This software is licensed under terms that can be found in the LICENSE file
00018   * in the root directory of this software component.
00019   * If no LICENSE file comes with this software, it is provided AS-IS.
00020   *
00021   ******************************************************************************
00022   @verbatim
00023   ==============================================================================
00024                         ##### How to use this driver #####
00025   ==============================================================================
00026   [..]
00027    (#) Enable and configure the peripheral to be connected to the DMA Stream
00028        (except for internal SRAM/FLASH memories: no initialization is
00029        necessary) please refer to Reference manual for connection between peripherals
00030        and DMA requests .
00031 
00032    (#) For a given Stream, program the required configuration through the following parameters:
00033        Transfer Direction, Source and Destination data formats,
00034        Circular, Normal or peripheral flow control mode, Stream Priority level,
00035        Source and Destination Increment mode, FIFO mode and its Threshold (if needed),
00036        Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function.
00037 
00038      *** Polling mode IO operation ***
00039      =================================
00040     [..]
00041           (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
00042               address and destination address and the Length of data to be transferred
00043           (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
00044               case a fixed Timeout can be configured by User depending from his application.
00045 
00046      *** Interrupt mode IO operation ***
00047      ===================================
00048     [..]
00049           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
00050           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
00051           (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
00052               Source address and destination address and the Length of data to be transferred. In this
00053               case the DMA interrupt is configured
00054           (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
00055           (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
00056               add his own function by customization of function pointer XferCpltCallback and
00057               XferErrorCallback (i.e a member of DMA handle structure).
00058     [..]
00059      (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
00060          detection.
00061 
00062      (#) Use HAL_DMA_Abort() function to abort the current transfer
00063 
00064      -@-   In Memory-to-Memory transfer mode, Circular mode is not allowed.
00065 
00066      -@-   The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
00067            possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
00068            Half-Word data size for the peripheral to access its data register and set Word data size
00069            for the Memory to gain in access time. Each two half words will be packed and written in
00070            a single access to a Word in the Memory).
00071 
00072      -@-   When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
00073            and Destination. In this case the Peripheral Data Size will be applied to both Source
00074            and Destination.
00075 
00076      *** DMA HAL driver macros list ***
00077      =============================================
00078      [..]
00079        Below the list of most used macros in DMA HAL driver.
00080 
00081       (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream.
00082       (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream.
00083       (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level.
00084       (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts.
00085       (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts.
00086       (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream interrupt has occurred or not.
00087 
00088      [..]
00089       (@) You can refer to the DMA HAL driver header file for more useful macros.
00090 
00091   @endverbatim
00092   */
00093 
00094 /* Includes ------------------------------------------------------------------*/
00095 #include "stm32h7xx_hal.h"
00096 
00097 /** @addtogroup STM32H7xx_HAL_Driver
00098   * @{
00099   */
00100 
00101 /** @defgroup DMA DMA
00102   * @brief DMA HAL module driver
00103   * @{
00104   */
00105 
00106 #ifdef HAL_DMA_MODULE_ENABLED
00107 
00108 /* Private types -------------------------------------------------------------*/
00109 typedef struct
00110 {
00111   __IO uint32_t ISR;   /*!< DMA interrupt status register */
00112   __IO uint32_t Reserved0;
00113   __IO uint32_t IFCR;  /*!< DMA interrupt flag clear register */
00114 } DMA_Base_Registers;
00115 
00116 typedef struct
00117 {
00118   __IO uint32_t ISR;   /*!< BDMA interrupt status register */
00119   __IO uint32_t IFCR;  /*!< BDMA interrupt flag clear register */
00120 } BDMA_Base_Registers;
00121 
00122 /* Private variables ---------------------------------------------------------*/
00123 /* Private constants ---------------------------------------------------------*/
00124 /** @addtogroup DMA_Private_Constants
00125  * @{
00126  */
00127 #define HAL_TIMEOUT_DMA_ABORT         (5U)  /* 5 ms */
00128 
00129 #define BDMA_PERIPH_TO_MEMORY         (0x00000000U)                /*!< Peripheral to memory direction */
00130 #define BDMA_MEMORY_TO_PERIPH         ((uint32_t)BDMA_CCR_DIR)     /*!< Memory to peripheral direction */
00131 #define BDMA_MEMORY_TO_MEMORY         ((uint32_t)BDMA_CCR_MEM2MEM) /*!< Memory to memory direction     */
00132 
00133 /* DMA to BDMA conversion */
00134 #define DMA_TO_BDMA_DIRECTION(__DMA_DIRECTION__) (((__DMA_DIRECTION__) == DMA_MEMORY_TO_PERIPH)? BDMA_MEMORY_TO_PERIPH: \
00135                                                   ((__DMA_DIRECTION__) == DMA_MEMORY_TO_MEMORY)? BDMA_MEMORY_TO_MEMORY: \
00136                                                   BDMA_PERIPH_TO_MEMORY)
00137 
00138 #define DMA_TO_BDMA_PERIPHERAL_INC(__DMA_PERIPHERAL_INC__) ((__DMA_PERIPHERAL_INC__) >> 3U)
00139 #define DMA_TO_BDMA_MEMORY_INC(__DMA_MEMORY_INC__) ((__DMA_MEMORY_INC__) >> 3U)
00140 
00141 #define DMA_TO_BDMA_PDATA_SIZE(__DMA_PDATA_SIZE__) ((__DMA_PDATA_SIZE__) >> 3U)
00142 #define DMA_TO_BDMA_MDATA_SIZE(__DMA_MDATA_SIZE__) ((__DMA_MDATA_SIZE__) >> 3U)
00143 
00144 #define DMA_TO_BDMA_MODE(__DMA_MODE__) ((__DMA_MODE__) >> 3U)
00145 
00146 #define DMA_TO_BDMA_PRIORITY(__DMA_PRIORITY__) ((__DMA_PRIORITY__) >> 4U)
00147 
00148 #if defined(UART9)
00149 #define IS_DMA_UART_USART_REQUEST(__REQUEST__) ((((__REQUEST__) >= DMA_REQUEST_USART1_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_USART3_TX)) || \
00150                                                  (((__REQUEST__) >= DMA_REQUEST_UART4_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_UART5_TX )) || \
00151                                                  (((__REQUEST__) >= DMA_REQUEST_USART6_RX) &&  ((__REQUEST__) <= DMA_REQUEST_USART6_TX)) || \
00152                                                  (((__REQUEST__) >= DMA_REQUEST_UART7_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_UART8_TX )) || \
00153                                                  (((__REQUEST__) >= DMA_REQUEST_UART9_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_USART10_TX )))
00154 #else
00155 #define IS_DMA_UART_USART_REQUEST(__REQUEST__) ((((__REQUEST__) >= DMA_REQUEST_USART1_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_USART3_TX)) || \
00156                                                  (((__REQUEST__) >= DMA_REQUEST_UART4_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_UART5_TX )) || \
00157                                                  (((__REQUEST__) >= DMA_REQUEST_USART6_RX) &&  ((__REQUEST__) <= DMA_REQUEST_USART6_TX)) || \
00158                                                  (((__REQUEST__) >= DMA_REQUEST_UART7_RX)  &&  ((__REQUEST__) <= DMA_REQUEST_UART8_TX )))
00159 
00160 #endif
00161 /**
00162   * @}
00163   */
00164 /* Private macros ------------------------------------------------------------*/
00165 /* Private functions ---------------------------------------------------------*/
00166 /** @addtogroup DMA_Private_Functions
00167   * @{
00168   */
00169 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
00170 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
00171 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma);
00172 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
00173 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
00174 
00175 /**
00176   * @}
00177   */
00178 
00179 /* Exported functions ---------------------------------------------------------*/
00180 /** @addtogroup DMA_Exported_Functions
00181   * @{
00182   */
00183 
00184 /** @addtogroup DMA_Exported_Functions_Group1
00185   *
00186 @verbatim
00187  ===============================================================================
00188              ##### Initialization and de-initialization functions  #####
00189  ===============================================================================
00190     [..]
00191     This section provides functions allowing to initialize the DMA Stream source
00192     and destination incrementation and data sizes, transfer direction,
00193     circular/normal mode selection, memory-to-memory mode selection and Stream priority value.
00194     [..]
00195     The HAL_DMA_Init() function follows the DMA configuration procedures as described in
00196     reference manual.
00197     The HAL_DMA_DeInit function allows to deinitialize the DMA stream.
00198 
00199 @endverbatim
00200   * @{
00201   */
00202 
00203 /**
00204   * @brief  Initialize the DMA according to the specified
00205   *         parameters in the DMA_InitTypeDef and create the associated handle.
00206   * @param  hdma: Pointer to a DMA_HandleTypeDef structure that contains
00207   *               the configuration information for the specified DMA Stream.
00208   * @retval HAL status
00209   */
00210 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
00211 {
00212   uint32_t registerValue;
00213   uint32_t tickstart = HAL_GetTick();
00214   DMA_Base_Registers *regs_dma;
00215   BDMA_Base_Registers *regs_bdma;
00216 
00217   /* Check the DMA peripheral handle */
00218   if(hdma == NULL)
00219   {
00220     return HAL_ERROR;
00221   }
00222 
00223   /* Check the parameters */
00224   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
00225   assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
00226   assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
00227   assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
00228   assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
00229   assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
00230   assert_param(IS_DMA_MODE(hdma->Init.Mode));
00231   assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
00232 
00233   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
00234   {
00235     assert_param(IS_DMA_REQUEST(hdma->Init.Request));
00236     assert_param(IS_DMA_FIFO_MODE_STATE(hdma->Init.FIFOMode));
00237     /* Check the memory burst, peripheral burst and FIFO threshold parameters only
00238        when FIFO mode is enabled */
00239     if(hdma->Init.FIFOMode != DMA_FIFOMODE_DISABLE)
00240     {
00241       assert_param(IS_DMA_FIFO_THRESHOLD(hdma->Init.FIFOThreshold));
00242       assert_param(IS_DMA_MEMORY_BURST(hdma->Init.MemBurst));
00243       assert_param(IS_DMA_PERIPHERAL_BURST(hdma->Init.PeriphBurst));
00244     }
00245 
00246     /* Change DMA peripheral state */
00247     hdma->State = HAL_DMA_STATE_BUSY;
00248 
00249     /* Allocate lock resource */
00250     __HAL_UNLOCK(hdma);
00251 
00252     /* Disable the peripheral */
00253     __HAL_DMA_DISABLE(hdma);
00254 
00255     /* Check if the DMA Stream is effectively disabled */
00256     while((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
00257     {
00258       /* Check for the Timeout */
00259       if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
00260       {
00261         /* Update error code */
00262         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
00263 
00264         /* Change the DMA state */
00265         hdma->State = HAL_DMA_STATE_ERROR;
00266 
00267         return HAL_ERROR;
00268       }
00269     }
00270 
00271     /* Get the CR register value */
00272     registerValue = ((DMA_Stream_TypeDef   *)hdma->Instance)->CR;
00273 
00274     /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
00275     registerValue &= ((uint32_t)~(DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
00276                         DMA_SxCR_PL    | DMA_SxCR_MSIZE  | DMA_SxCR_PSIZE  | \
00277                         DMA_SxCR_MINC  | DMA_SxCR_PINC   | DMA_SxCR_CIRC   | \
00278                         DMA_SxCR_DIR   | DMA_SxCR_CT     | DMA_SxCR_DBM));
00279 
00280     /* Prepare the DMA Stream configuration */
00281     registerValue |=  hdma->Init.Direction           |
00282             hdma->Init.PeriphInc           | hdma->Init.MemInc           |
00283             hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
00284             hdma->Init.Mode                | hdma->Init.Priority;
00285 
00286     /* the Memory burst and peripheral burst are not used when the FIFO is disabled */
00287     if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
00288     {
00289       /* Get memory burst and peripheral burst */
00290       registerValue |=  hdma->Init.MemBurst | hdma->Init.PeriphBurst;
00291     }
00292 
00293     /* Work around for Errata 2.22: UART/USART- DMA transfer lock: DMA stream could be
00294                                     lock when transferring data to/from USART/UART */
00295 #if (STM32H7_DEV_ID == 0x450UL)
00296     if((DBGMCU->IDCODE & 0xFFFF0000U) >= 0x20000000U)
00297     {
00298 #endif /* STM32H7_DEV_ID == 0x450UL */
00299       if(IS_DMA_UART_USART_REQUEST(hdma->Init.Request) != 0U)
00300       {
00301         registerValue |= DMA_SxCR_TRBUFF;
00302       }
00303 #if (STM32H7_DEV_ID == 0x450UL)
00304     }
00305 #endif /* STM32H7_DEV_ID == 0x450UL */
00306 
00307     /* Write to DMA Stream CR register */
00308     ((DMA_Stream_TypeDef   *)hdma->Instance)->CR = registerValue;
00309 
00310     /* Get the FCR register value */
00311     registerValue = ((DMA_Stream_TypeDef   *)hdma->Instance)->FCR;
00312 
00313     /* Clear Direct mode and FIFO threshold bits */
00314     registerValue &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
00315 
00316     /* Prepare the DMA Stream FIFO configuration */
00317     registerValue |= hdma->Init.FIFOMode;
00318 
00319     /* the FIFO threshold is not used when the FIFO mode is disabled */
00320     if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
00321     {
00322       /* Get the FIFO threshold */
00323       registerValue |= hdma->Init.FIFOThreshold;
00324 
00325       /* Check compatibility between FIFO threshold level and size of the memory burst */
00326       /* for INCR4, INCR8, INCR16 */
00327       if(hdma->Init.MemBurst != DMA_MBURST_SINGLE)
00328       {
00329         if (DMA_CheckFifoParam(hdma) != HAL_OK)
00330         {
00331           /* Update error code */
00332           hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
00333 
00334           /* Change the DMA state */
00335           hdma->State = HAL_DMA_STATE_READY;
00336 
00337           return HAL_ERROR;
00338         }
00339       }
00340     }
00341 
00342     /* Write to DMA Stream FCR */
00343     ((DMA_Stream_TypeDef   *)hdma->Instance)->FCR = registerValue;
00344 
00345     /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
00346        DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
00347     regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
00348 
00349     /* Clear all interrupt flags */
00350     regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
00351   }
00352   else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
00353   {
00354     if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U)
00355     {
00356       /* Check the request parameter */
00357       assert_param(IS_BDMA_REQUEST(hdma->Init.Request));
00358     }
00359 
00360     /* Change DMA peripheral state */
00361     hdma->State = HAL_DMA_STATE_BUSY;
00362 
00363     /* Allocate lock resource */
00364     __HAL_UNLOCK(hdma);
00365 
00366     /* Get the CR register value */
00367     registerValue = ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR;
00368 
00369     /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, MEM2MEM, DBM and CT bits */
00370     registerValue &= ((uint32_t)~(BDMA_CCR_PL    | BDMA_CCR_MSIZE   | BDMA_CCR_PSIZE  | \
00371                                   BDMA_CCR_MINC  | BDMA_CCR_PINC    | BDMA_CCR_CIRC   | \
00372                                   BDMA_CCR_DIR   | BDMA_CCR_MEM2MEM | BDMA_CCR_DBM    | \
00373                                   BDMA_CCR_CT));
00374 
00375     /* Prepare the DMA Channel configuration */
00376     registerValue |=  DMA_TO_BDMA_DIRECTION(hdma->Init.Direction)            |
00377                       DMA_TO_BDMA_PERIPHERAL_INC(hdma->Init.PeriphInc)       |
00378                       DMA_TO_BDMA_MEMORY_INC(hdma->Init.MemInc)              |
00379                       DMA_TO_BDMA_PDATA_SIZE(hdma->Init.PeriphDataAlignment) |
00380                       DMA_TO_BDMA_MDATA_SIZE(hdma->Init.MemDataAlignment)    |
00381                       DMA_TO_BDMA_MODE(hdma->Init.Mode)                      |
00382                       DMA_TO_BDMA_PRIORITY(hdma->Init.Priority);
00383 
00384     /* Write to DMA Channel CR register */
00385     ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR = registerValue;
00386 
00387     /* calculation of the channel index */
00388     hdma->StreamIndex = (((uint32_t)((uint32_t*)hdma->Instance) - (uint32_t)BDMA_Channel0) / ((uint32_t)BDMA_Channel1 - (uint32_t)BDMA_Channel0)) << 2U;
00389 
00390     /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
00391     DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
00392     regs_bdma = (BDMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
00393 
00394     /* Clear all interrupt flags */
00395     regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
00396   }
00397   else
00398   {
00399     hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
00400     hdma->State     = HAL_DMA_STATE_ERROR;
00401 
00402     return HAL_ERROR;
00403   }
00404 
00405   if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
00406   {
00407     /* Initialize parameters for DMAMUX channel :
00408     DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
00409     */
00410     DMA_CalcDMAMUXChannelBaseAndMask(hdma);
00411 
00412     if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
00413     {
00414       /* if memory to memory force the request to 0*/
00415       hdma->Init.Request = DMA_REQUEST_MEM2MEM;
00416     }
00417 
00418     /* Set peripheral request  to DMAMUX channel */
00419     hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
00420 
00421     /* Clear the DMAMUX synchro overrun flag */
00422     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
00423 
00424     /* Initialize parameters for DMAMUX request generator :
00425     if the DMA request is DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR7
00426     */
00427     if((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
00428     {
00429       /* Initialize parameters for DMAMUX request generator :
00430       DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
00431       DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
00432 
00433       /* Reset the DMAMUX request generator register */
00434       hdma->DMAmuxRequestGen->RGCR = 0U;
00435 
00436       /* Clear the DMAMUX request generator overrun flag */
00437       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
00438     }
00439     else
00440     {
00441       hdma->DMAmuxRequestGen = 0U;
00442       hdma->DMAmuxRequestGenStatus = 0U;
00443       hdma->DMAmuxRequestGenStatusMask = 0U;
00444     }
00445   }
00446 
00447   /* Initialize the error code */
00448   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00449 
00450   /* Initialize the DMA state */
00451   hdma->State = HAL_DMA_STATE_READY;
00452 
00453   return HAL_OK;
00454 }
00455 
00456 /**
00457   * @brief  DeInitializes the DMA peripheral
00458   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00459   *               the configuration information for the specified DMA Stream.
00460   * @retval HAL status
00461   */
00462 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
00463 {
00464   DMA_Base_Registers *regs_dma;
00465   BDMA_Base_Registers *regs_bdma;
00466 
00467   /* Check the DMA peripheral handle */
00468   if(hdma == NULL)
00469   {
00470     return HAL_ERROR;
00471   }
00472 
00473   /* Disable the selected DMA Streamx */
00474   __HAL_DMA_DISABLE(hdma);
00475 
00476   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
00477   {
00478     /* Reset DMA Streamx control register */
00479     ((DMA_Stream_TypeDef   *)hdma->Instance)->CR   = 0U;
00480 
00481     /* Reset DMA Streamx number of data to transfer register */
00482     ((DMA_Stream_TypeDef   *)hdma->Instance)->NDTR = 0U;
00483 
00484     /* Reset DMA Streamx peripheral address register */
00485     ((DMA_Stream_TypeDef   *)hdma->Instance)->PAR  = 0U;
00486 
00487     /* Reset DMA Streamx memory 0 address register */
00488     ((DMA_Stream_TypeDef   *)hdma->Instance)->M0AR = 0U;
00489 
00490     /* Reset DMA Streamx memory 1 address register */
00491     ((DMA_Stream_TypeDef   *)hdma->Instance)->M1AR = 0U;
00492 
00493     /* Reset DMA Streamx FIFO control register */
00494     ((DMA_Stream_TypeDef   *)hdma->Instance)->FCR  = (uint32_t)0x00000021U;
00495 
00496     /* Get DMA steam Base Address */
00497     regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
00498 
00499     /* Clear all interrupt flags at correct offset within the register */
00500     regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
00501   }
00502   else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
00503   {
00504     /* Reset DMA Channel control register */
00505     ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR  = 0U;
00506 
00507     /* Reset DMA Channel Number of Data to Transfer register */
00508     ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = 0U;
00509 
00510     /* Reset DMA Channel peripheral address register */
00511     ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR  = 0U;
00512 
00513     /* Reset DMA Channel memory 0 address register */
00514     ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = 0U;
00515 
00516     /* Reset DMA Channel memory 1 address register */
00517     ((BDMA_Channel_TypeDef *)hdma->Instance)->CM1AR = 0U;
00518 
00519     /* Get DMA steam Base Address */
00520     regs_bdma = (BDMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
00521 
00522     /* Clear all interrupt flags at correct offset within the register */
00523     regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
00524   }
00525   else
00526   {
00527     /* Return error status */
00528     return HAL_ERROR;
00529   }
00530 
00531 #if defined (BDMA1) /* No DMAMUX available for BDMA1 available on  STM32H7Ax/Bx devices only */
00532   if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
00533 #endif /* BDMA1 */
00534   {
00535     /* Initialize parameters for DMAMUX channel :
00536     DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
00537     DMA_CalcDMAMUXChannelBaseAndMask(hdma);
00538 
00539     if(hdma->DMAmuxChannel != 0U)
00540     {
00541       /* Resett he DMAMUX channel that corresponds to the DMA stream */
00542       hdma->DMAmuxChannel->CCR = 0U;
00543 
00544       /* Clear the DMAMUX synchro overrun flag */
00545       hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
00546     }
00547 
00548     if((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
00549     {
00550       /* Initialize parameters for DMAMUX request generator :
00551       DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
00552       DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
00553 
00554       /* Reset the DMAMUX request generator register */
00555       hdma->DMAmuxRequestGen->RGCR = 0U;
00556 
00557       /* Clear the DMAMUX request generator overrun flag */
00558       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
00559     }
00560 
00561     hdma->DMAmuxRequestGen = 0U;
00562     hdma->DMAmuxRequestGenStatus = 0U;
00563     hdma->DMAmuxRequestGenStatusMask = 0U;
00564   }
00565 
00566 
00567   /* Clean callbacks */
00568   hdma->XferCpltCallback       = NULL;
00569   hdma->XferHalfCpltCallback   = NULL;
00570   hdma->XferM1CpltCallback     = NULL;
00571   hdma->XferM1HalfCpltCallback = NULL;
00572   hdma->XferErrorCallback      = NULL;
00573   hdma->XferAbortCallback      = NULL;
00574 
00575   /* Initialize the error code */
00576   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00577 
00578   /* Initialize the DMA state */
00579   hdma->State = HAL_DMA_STATE_RESET;
00580 
00581   /* Release Lock */
00582   __HAL_UNLOCK(hdma);
00583 
00584   return HAL_OK;
00585 }
00586 
00587 /**
00588   * @}
00589   */
00590 
00591 /** @addtogroup DMA_Exported_Functions_Group2
00592   *
00593 @verbatim
00594  ===============================================================================
00595                       #####  IO operation functions  #####
00596  ===============================================================================
00597     [..]  This section provides functions allowing to:
00598       (+) Configure the source, destination address and data length and Start DMA transfer
00599       (+) Configure the source, destination address and data length and
00600           Start DMA transfer with interrupt
00601       (+) Register and Unregister DMA callbacks
00602       (+) Abort DMA transfer
00603       (+) Poll for transfer complete
00604       (+) Handle DMA interrupt request
00605 
00606 @endverbatim
00607   * @{
00608   */
00609 
00610 /**
00611   * @brief  Starts the DMA Transfer.
00612   * @param  hdma      : pointer to a DMA_HandleTypeDef structure that contains
00613   *                     the configuration information for the specified DMA Stream.
00614   * @param  SrcAddress: The source memory Buffer address
00615   * @param  DstAddress: The destination memory Buffer address
00616   * @param  DataLength: The length of data to be transferred from source to destination
00617   * @retval HAL status
00618   */
00619 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
00620 {
00621   HAL_StatusTypeDef status = HAL_OK;
00622 
00623   /* Check the parameters */
00624   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
00625 
00626   /* Check the DMA peripheral handle */
00627   if(hdma == NULL)
00628   {
00629     return HAL_ERROR;
00630   }
00631 
00632   /* Process locked */
00633   __HAL_LOCK(hdma);
00634 
00635   if(HAL_DMA_STATE_READY == hdma->State)
00636   {
00637     /* Change DMA peripheral state */
00638     hdma->State = HAL_DMA_STATE_BUSY;
00639 
00640     /* Initialize the error code */
00641     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00642 
00643     /* Disable the peripheral */
00644     __HAL_DMA_DISABLE(hdma);
00645 
00646     /* Configure the source, destination address and the data length */
00647     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
00648 
00649     /* Enable the Peripheral */
00650     __HAL_DMA_ENABLE(hdma);
00651   }
00652   else
00653   {
00654     /* Set the error code to busy */
00655     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
00656 
00657     /* Process unlocked */
00658     __HAL_UNLOCK(hdma);
00659 
00660     /* Return error status */
00661     status = HAL_ERROR;
00662   }
00663   return status;
00664 }
00665 
00666 /**
00667   * @brief  Start the DMA Transfer with interrupt enabled.
00668   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
00669   *                     the configuration information for the specified DMA Stream.
00670   * @param  SrcAddress: The source memory Buffer address
00671   * @param  DstAddress: The destination memory Buffer address
00672   * @param  DataLength: The length of data to be transferred from source to destination
00673   * @retval HAL status
00674   */
00675 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
00676 {
00677   HAL_StatusTypeDef status = HAL_OK;
00678 
00679   /* Check the parameters */
00680   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
00681 
00682   /* Check the DMA peripheral handle */
00683   if(hdma == NULL)
00684   {
00685     return HAL_ERROR;
00686   }
00687 
00688   /* Process locked */
00689   __HAL_LOCK(hdma);
00690 
00691   if(HAL_DMA_STATE_READY == hdma->State)
00692   {
00693     /* Change DMA peripheral state */
00694     hdma->State = HAL_DMA_STATE_BUSY;
00695 
00696     /* Initialize the error code */
00697     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00698 
00699     /* Disable the peripheral */
00700     __HAL_DMA_DISABLE(hdma);
00701 
00702     /* Configure the source, destination address and the data length */
00703     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
00704 
00705     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
00706     {
00707       /* Enable Common interrupts*/
00708       MODIFY_REG(((DMA_Stream_TypeDef   *)hdma->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
00709 
00710       if(hdma->XferHalfCpltCallback != NULL)
00711       {
00712         /* Enable Half Transfer IT if corresponding Callback is set */
00713         ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  |= DMA_IT_HT;
00714       }
00715     }
00716     else /* BDMA channel */
00717     {
00718       /* Enable Common interrupts */
00719       MODIFY_REG(((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR, (BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE), (BDMA_CCR_TCIE | BDMA_CCR_TEIE));
00720 
00721       if(hdma->XferHalfCpltCallback != NULL)
00722       {
00723         /*Enable Half Transfer IT if corresponding Callback is set */
00724         ((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR  |= BDMA_CCR_HTIE;
00725       }
00726     }
00727 
00728     if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
00729     {
00730       /* Check if DMAMUX Synchronization is enabled */
00731       if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
00732       {
00733         /* Enable DMAMUX sync overrun IT*/
00734         hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
00735       }
00736 
00737       if(hdma->DMAmuxRequestGen != 0U)
00738       {
00739         /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
00740         /* enable the request gen overrun IT */
00741         hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
00742       }
00743     }
00744 
00745     /* Enable the Peripheral */
00746     __HAL_DMA_ENABLE(hdma);
00747   }
00748   else
00749   {
00750     /* Set the error code to busy */
00751     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
00752 
00753     /* Process unlocked */
00754     __HAL_UNLOCK(hdma);
00755 
00756     /* Return error status */
00757     status = HAL_ERROR;
00758   }
00759 
00760   return status;
00761 }
00762 
00763 /**
00764   * @brief  Aborts the DMA Transfer.
00765   * @param  hdma  : pointer to a DMA_HandleTypeDef structure that contains
00766   *                 the configuration information for the specified DMA Stream.
00767   *
00768   * @note  After disabling a DMA Stream, a check for wait until the DMA Stream is
00769   *        effectively disabled is added. If a Stream is disabled
00770   *        while a data transfer is ongoing, the current data will be transferred
00771   *        and the Stream will be effectively disabled only after the transfer of
00772   *        this single data is finished.
00773   * @retval HAL status
00774   */
00775 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
00776 {
00777   /* calculate DMA base and stream number */
00778   DMA_Base_Registers *regs_dma;
00779   BDMA_Base_Registers *regs_bdma;
00780   const __IO uint32_t *enableRegister;
00781 
00782   uint32_t tickstart = HAL_GetTick();
00783 
00784  /* Check the DMA peripheral handle */
00785   if(hdma == NULL)
00786   {
00787     return HAL_ERROR;
00788   }
00789 
00790   /* Check the DMA peripheral state */
00791   if(hdma->State != HAL_DMA_STATE_BUSY)
00792   {
00793     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
00794 
00795     /* Process Unlocked */
00796     __HAL_UNLOCK(hdma);
00797 
00798     return HAL_ERROR;
00799   }
00800   else
00801   {
00802     /* Disable all the transfer interrupts */
00803     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
00804     {
00805        /* Disable DMA All Interrupts  */
00806       ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT);
00807       ((DMA_Stream_TypeDef   *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
00808 
00809       enableRegister = (__IO uint32_t *)(&(((DMA_Stream_TypeDef   *)hdma->Instance)->CR));
00810     }
00811     else /* BDMA channel */
00812     {
00813       /* Disable DMA All Interrupts */
00814       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR  &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE);
00815 
00816       enableRegister = (__IO uint32_t *)(&(((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR));
00817     }
00818 
00819     if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
00820     {
00821       /* disable the DMAMUX sync overrun IT */
00822       hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
00823     }
00824 
00825     /* Disable the stream */
00826     __HAL_DMA_DISABLE(hdma);
00827 
00828     /* Check if the DMA Stream is effectively disabled */
00829     while(((*enableRegister) & DMA_SxCR_EN) != 0U)
00830     {
00831       /* Check for the Timeout */
00832       if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
00833       {
00834         /* Update error code */
00835         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
00836 
00837         /* Change the DMA state */
00838         hdma->State = HAL_DMA_STATE_ERROR;
00839 
00840         /* Process Unlocked */
00841         __HAL_UNLOCK(hdma);
00842 
00843         return HAL_ERROR;
00844       }
00845     }
00846 
00847     /* Clear all interrupt flags at correct offset within the register */
00848     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
00849     {
00850       regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
00851       regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
00852     }
00853     else /* BDMA channel */
00854     {
00855       regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
00856       regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
00857     }
00858 
00859     if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
00860     {
00861       /* Clear the DMAMUX synchro overrun flag */
00862       hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
00863 
00864       if(hdma->DMAmuxRequestGen != 0U)
00865       {
00866         /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT */
00867         /* disable the request gen overrun IT */
00868         hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
00869 
00870         /* Clear the DMAMUX request generator overrun flag */
00871         hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
00872       }
00873     }
00874 
00875     /* Change the DMA state */
00876     hdma->State = HAL_DMA_STATE_READY;
00877 
00878     /* Process Unlocked */
00879     __HAL_UNLOCK(hdma);
00880   }
00881 
00882   return HAL_OK;
00883 }
00884 
00885 /**
00886   * @brief  Aborts the DMA Transfer in Interrupt mode.
00887   * @param  hdma  : pointer to a DMA_HandleTypeDef structure that contains
00888   *                 the configuration information for the specified DMA Stream.
00889   * @retval HAL status
00890   */
00891 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
00892 {
00893   BDMA_Base_Registers *regs_bdma;
00894 
00895   /* Check the DMA peripheral handle */
00896   if(hdma == NULL)
00897   {
00898     return HAL_ERROR;
00899   }
00900 
00901   if(hdma->State != HAL_DMA_STATE_BUSY)
00902   {
00903     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
00904     return HAL_ERROR;
00905   }
00906   else
00907   {
00908     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
00909     {
00910       /* Set Abort State  */
00911       hdma->State = HAL_DMA_STATE_ABORT;
00912 
00913       /* Disable the stream */
00914       __HAL_DMA_DISABLE(hdma);
00915     }
00916     else /* BDMA channel */
00917     {
00918       /* Disable DMA All Interrupts  */
00919       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR  &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE);
00920 
00921       /* Disable the channel */
00922       __HAL_DMA_DISABLE(hdma);
00923 
00924       if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
00925       {
00926         /* disable the DMAMUX sync overrun IT */
00927         hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
00928 
00929         /* Clear all flags */
00930         regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
00931         regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
00932 
00933         /* Clear the DMAMUX synchro overrun flag */
00934         hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
00935 
00936         if(hdma->DMAmuxRequestGen != 0U)
00937         {
00938           /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
00939           /* disable the request gen overrun IT */
00940           hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
00941 
00942           /* Clear the DMAMUX request generator overrun flag */
00943           hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
00944         }
00945       }
00946 
00947       /* Change the DMA state */
00948       hdma->State = HAL_DMA_STATE_READY;
00949 
00950       /* Process Unlocked */
00951       __HAL_UNLOCK(hdma);
00952 
00953       /* Call User Abort callback */
00954       if(hdma->XferAbortCallback != NULL)
00955       {
00956         hdma->XferAbortCallback(hdma);
00957       }
00958     }
00959   }
00960 
00961   return HAL_OK;
00962 }
00963 
00964 /**
00965   * @brief  Polling for transfer complete.
00966   * @param  hdma:          pointer to a DMA_HandleTypeDef structure that contains
00967   *                        the configuration information for the specified DMA Stream.
00968   * @param  CompleteLevel: Specifies the DMA level complete.
00969   * @note   The polling mode is kept in this version for legacy. it is recommended to use the IT model instead.
00970   *         This model could be used for debug purpose.
00971   * @note   The HAL_DMA_PollForTransfer API cannot be used in circular and double buffering mode (automatic circular mode).
00972   * @param  Timeout:       Timeout duration.
00973   * @retval HAL status
00974   */
00975 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
00976 {
00977   HAL_StatusTypeDef status = HAL_OK;
00978   uint32_t cpltlevel_mask;
00979   uint32_t tickstart = HAL_GetTick();
00980 
00981   /* IT status register */
00982   __IO uint32_t *isr_reg;
00983   /* IT clear flag register */
00984   __IO uint32_t *ifcr_reg;
00985 
00986   /* Check the DMA peripheral handle */
00987   if(hdma == NULL)
00988   {
00989     return HAL_ERROR;
00990   }
00991 
00992   if(HAL_DMA_STATE_BUSY != hdma->State)
00993   {
00994     /* No transfer ongoing */
00995     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
00996     __HAL_UNLOCK(hdma);
00997 
00998     return HAL_ERROR;
00999   }
01000 
01001   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
01002   {
01003     /* Polling mode not supported in circular mode and double buffering mode */
01004     if ((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_CIRC) != 0U)
01005     {
01006       hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
01007       return HAL_ERROR;
01008     }
01009 
01010     /* Get the level transfer complete flag */
01011     if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
01012     {
01013       /* Transfer Complete flag */
01014       cpltlevel_mask = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
01015     }
01016     else
01017     {
01018       /* Half Transfer Complete flag */
01019       cpltlevel_mask = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
01020     }
01021 
01022     isr_reg  = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->ISR);
01023     ifcr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR);
01024   }
01025   else /* BDMA channel */
01026   {
01027     /* Polling mode not supported in circular mode */
01028     if ((((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR & BDMA_CCR_CIRC) != 0U)
01029     {
01030       hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
01031       return HAL_ERROR;
01032     }
01033 
01034     /* Get the level transfer complete flag */
01035     if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
01036     {
01037       /* Transfer Complete flag */
01038       cpltlevel_mask = BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU);
01039     }
01040     else
01041     {
01042       /* Half Transfer Complete flag */
01043       cpltlevel_mask = BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU);
01044     }
01045 
01046     isr_reg  = &(((BDMA_Base_Registers *)hdma->StreamBaseAddress)->ISR);
01047     ifcr_reg = &(((BDMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR);
01048   }
01049 
01050   while(((*isr_reg) & cpltlevel_mask) == 0U)
01051   {
01052     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
01053     {
01054       if(((*isr_reg) & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01055       {
01056         /* Update error code */
01057         hdma->ErrorCode |= HAL_DMA_ERROR_FE;
01058 
01059         /* Clear the FIFO error flag */
01060         (*ifcr_reg) = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
01061       }
01062 
01063       if(((*isr_reg) & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01064       {
01065         /* Update error code */
01066         hdma->ErrorCode |= HAL_DMA_ERROR_DME;
01067 
01068         /* Clear the Direct Mode error flag */
01069         (*ifcr_reg) = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
01070       }
01071 
01072       if(((*isr_reg) & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01073       {
01074         /* Update error code */
01075         hdma->ErrorCode |= HAL_DMA_ERROR_TE;
01076 
01077         /* Clear the transfer error flag */
01078         (*ifcr_reg) = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
01079 
01080         /* Change the DMA state */
01081         hdma->State = HAL_DMA_STATE_READY;
01082 
01083         /* Process Unlocked */
01084         __HAL_UNLOCK(hdma);
01085 
01086         return HAL_ERROR;
01087       }
01088     }
01089     else /* BDMA channel */
01090     {
01091       if(((*isr_reg) & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U)
01092       {
01093         /* When a DMA transfer error occurs */
01094         /* A hardware clear of its EN bits is performed */
01095         /* Clear all flags */
01096         (*isr_reg) = ((BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU));
01097 
01098         /* Update error code */
01099         hdma->ErrorCode = HAL_DMA_ERROR_TE;
01100 
01101         /* Change the DMA state */
01102         hdma->State = HAL_DMA_STATE_READY;
01103 
01104         /* Process Unlocked */
01105         __HAL_UNLOCK(hdma);
01106 
01107         return HAL_ERROR;
01108       }
01109     }
01110 
01111     /* Check for the Timeout (Not applicable in circular mode)*/
01112     if(Timeout != HAL_MAX_DELAY)
01113     {
01114       if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
01115       {
01116         /* Update error code */
01117         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
01118 
01119         /* if timeout then abort the current transfer */
01120         /* No need to check return value: as in this case we will return HAL_ERROR with HAL_DMA_ERROR_TIMEOUT error code  */
01121         (void) HAL_DMA_Abort(hdma);
01122           /*
01123             Note that the Abort function will
01124               - Clear the transfer error flags
01125               - Unlock
01126               - Set the State
01127           */
01128 
01129         return HAL_ERROR;
01130       }
01131     }
01132 
01133     if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
01134     {
01135       /* Check for DMAMUX Request generator (if used) overrun status */
01136       if(hdma->DMAmuxRequestGen != 0U)
01137       {
01138         /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
01139         if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
01140         {
01141           /* Clear the DMAMUX request generator overrun flag */
01142           hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
01143 
01144           /* Update error code */
01145           hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
01146         }
01147       }
01148 
01149       /* Check for DMAMUX Synchronization overrun */
01150       if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
01151       {
01152         /* Clear the DMAMUX synchro overrun flag */
01153         hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
01154 
01155         /* Update error code */
01156         hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
01157       }
01158     }
01159   }
01160 
01161 
01162   /* Get the level transfer complete flag */
01163   if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
01164   {
01165     /* Clear the half transfer and transfer complete flags */
01166     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
01167     {
01168       (*ifcr_reg) = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << (hdma->StreamIndex & 0x1FU);
01169     }
01170     else /* BDMA channel */
01171     {
01172       (*ifcr_reg) = (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU));
01173     }
01174 
01175     hdma->State = HAL_DMA_STATE_READY;
01176 
01177     /* Process Unlocked */
01178     __HAL_UNLOCK(hdma);
01179   }
01180   else /*CompleteLevel = HAL_DMA_HALF_TRANSFER*/
01181   {
01182     /* Clear the half transfer and transfer complete flags */
01183     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
01184     {
01185       (*ifcr_reg) = (DMA_FLAG_HTIF0_4) << (hdma->StreamIndex & 0x1FU);
01186     }
01187     else /* BDMA channel */
01188     {
01189       (*ifcr_reg) = (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU));
01190     }
01191   }
01192 
01193   return status;
01194 }
01195 
01196 /**
01197   * @brief  Handles DMA interrupt request.
01198   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01199   *               the configuration information for the specified DMA Stream.
01200   * @retval None
01201   */
01202 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
01203 {
01204   uint32_t tmpisr_dma, tmpisr_bdma;
01205   uint32_t ccr_reg;
01206   __IO uint32_t count = 0U;
01207   uint32_t timeout = SystemCoreClock / 9600U;
01208 
01209   /* calculate DMA base and stream number */
01210   DMA_Base_Registers  *regs_dma  = (DMA_Base_Registers *)hdma->StreamBaseAddress;
01211   BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
01212 
01213   tmpisr_dma  = regs_dma->ISR;
01214   tmpisr_bdma = regs_bdma->ISR;
01215 
01216   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U)  /* DMA1 or DMA2 instance */
01217   {
01218     /* Transfer Error Interrupt management ***************************************/
01219     if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01220     {
01221       if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U)
01222       {
01223         /* Disable the transfer error interrupt */
01224         ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_TE);
01225 
01226         /* Clear the transfer error flag */
01227         regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
01228 
01229         /* Update error code */
01230         hdma->ErrorCode |= HAL_DMA_ERROR_TE;
01231       }
01232     }
01233     /* FIFO Error Interrupt management ******************************************/
01234     if ((tmpisr_dma & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01235     {
01236       if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != 0U)
01237       {
01238         /* Clear the FIFO error flag */
01239         regs_dma->IFCR = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
01240 
01241         /* Update error code */
01242         hdma->ErrorCode |= HAL_DMA_ERROR_FE;
01243       }
01244     }
01245     /* Direct Mode Error Interrupt management ***********************************/
01246     if ((tmpisr_dma & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01247     {
01248       if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != 0U)
01249       {
01250         /* Clear the direct mode error flag */
01251         regs_dma->IFCR = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
01252 
01253         /* Update error code */
01254         hdma->ErrorCode |= HAL_DMA_ERROR_DME;
01255       }
01256     }
01257     /* Half Transfer Complete Interrupt management ******************************/
01258     if ((tmpisr_dma & (DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01259     {
01260       if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U)
01261       {
01262         /* Clear the half transfer complete flag */
01263         regs_dma->IFCR = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
01264 
01265         /* Multi_Buffering mode enabled */
01266         if(((((DMA_Stream_TypeDef   *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
01267         {
01268           /* Current memory buffer used is Memory 0 */
01269           if((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
01270           {
01271             if(hdma->XferHalfCpltCallback != NULL)
01272             {
01273               /* Half transfer callback */
01274               hdma->XferHalfCpltCallback(hdma);
01275             }
01276           }
01277           /* Current memory buffer used is Memory 1 */
01278           else
01279           {
01280             if(hdma->XferM1HalfCpltCallback != NULL)
01281             {
01282               /* Half transfer callback */
01283               hdma->XferM1HalfCpltCallback(hdma);
01284             }
01285           }
01286         }
01287         else
01288         {
01289           /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
01290           if((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
01291           {
01292             /* Disable the half transfer interrupt */
01293             ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_HT);
01294           }
01295 
01296           if(hdma->XferHalfCpltCallback != NULL)
01297           {
01298             /* Half transfer callback */
01299             hdma->XferHalfCpltCallback(hdma);
01300           }
01301         }
01302       }
01303     }
01304     /* Transfer Complete Interrupt management ***********************************/
01305     if ((tmpisr_dma & (DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
01306     {
01307       if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U)
01308       {
01309         /* Clear the transfer complete flag */
01310         regs_dma->IFCR = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
01311 
01312         if(HAL_DMA_STATE_ABORT == hdma->State)
01313         {
01314           /* Disable all the transfer interrupts */
01315           ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME);
01316           ((DMA_Stream_TypeDef   *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
01317 
01318           if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
01319           {
01320             ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_HT);
01321           }
01322 
01323           /* Clear all interrupt flags at correct offset within the register */
01324           regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
01325 
01326           /* Change the DMA state */
01327           hdma->State = HAL_DMA_STATE_READY;
01328 
01329           /* Process Unlocked */
01330           __HAL_UNLOCK(hdma);
01331 
01332           if(hdma->XferAbortCallback != NULL)
01333           {
01334             hdma->XferAbortCallback(hdma);
01335           }
01336           return;
01337         }
01338 
01339         if(((((DMA_Stream_TypeDef   *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
01340         {
01341           /* Current memory buffer used is Memory 0 */
01342           if((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
01343           {
01344             if(hdma->XferM1CpltCallback != NULL)
01345             {
01346               /* Transfer complete Callback for memory1 */
01347               hdma->XferM1CpltCallback(hdma);
01348             }
01349           }
01350           /* Current memory buffer used is Memory 1 */
01351           else
01352           {
01353             if(hdma->XferCpltCallback != NULL)
01354             {
01355               /* Transfer complete Callback for memory0 */
01356               hdma->XferCpltCallback(hdma);
01357             }
01358           }
01359         }
01360         /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
01361         else
01362         {
01363           if((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
01364           {
01365             /* Disable the transfer complete interrupt */
01366             ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  &= ~(DMA_IT_TC);
01367 
01368             /* Change the DMA state */
01369             hdma->State = HAL_DMA_STATE_READY;
01370 
01371             /* Process Unlocked */
01372             __HAL_UNLOCK(hdma);
01373           }
01374 
01375           if(hdma->XferCpltCallback != NULL)
01376           {
01377             /* Transfer complete callback */
01378             hdma->XferCpltCallback(hdma);
01379           }
01380         }
01381       }
01382     }
01383 
01384     /* manage error case */
01385     if(hdma->ErrorCode != HAL_DMA_ERROR_NONE)
01386     {
01387       if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U)
01388       {
01389         hdma->State = HAL_DMA_STATE_ABORT;
01390 
01391         /* Disable the stream */
01392         __HAL_DMA_DISABLE(hdma);
01393 
01394         do
01395         {
01396           if (++count > timeout)
01397           {
01398             break;
01399           }
01400         }
01401         while((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);
01402 
01403         if((((DMA_Stream_TypeDef   *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
01404         {
01405           /* Change the DMA state to error if DMA disable fails */
01406           hdma->State = HAL_DMA_STATE_ERROR;
01407         }
01408         else
01409         {
01410           /* Change the DMA state to Ready if DMA disable success */
01411           hdma->State = HAL_DMA_STATE_READY;
01412         }
01413 
01414         /* Process Unlocked */
01415         __HAL_UNLOCK(hdma);
01416       }
01417 
01418       if(hdma->XferErrorCallback != NULL)
01419       {
01420         /* Transfer error callback */
01421         hdma->XferErrorCallback(hdma);
01422       }
01423     }
01424   }
01425   else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U)  /* BDMA instance(s) */
01426   {
01427     ccr_reg = (((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR);
01428 
01429     /* Half Transfer Complete Interrupt management ******************************/
01430     if (((tmpisr_bdma & (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_HTIE) != 0U))
01431     {
01432       /* Clear the half transfer complete flag */
01433       regs_bdma->IFCR = (BDMA_ISR_HTIF0 << (hdma->StreamIndex & 0x1FU));
01434 
01435       /* Disable the transfer complete interrupt if the DMA mode is Double Buffering */
01436       if((ccr_reg & BDMA_CCR_DBM) != 0U)
01437       {
01438         /* Current memory buffer used is Memory 0 */
01439         if((ccr_reg & BDMA_CCR_CT) == 0U)
01440         {
01441           if(hdma->XferM1HalfCpltCallback != NULL)
01442           {
01443             /* Half transfer Callback for Memory 1 */
01444             hdma->XferM1HalfCpltCallback(hdma);
01445           }
01446         }
01447         /* Current memory buffer used is Memory 1 */
01448         else
01449         {
01450           if(hdma->XferHalfCpltCallback != NULL)
01451           {
01452             /* Half transfer Callback for Memory 0 */
01453             hdma->XferHalfCpltCallback(hdma);
01454           }
01455         }
01456       }
01457       else
01458       {
01459         if((ccr_reg & BDMA_CCR_CIRC) == 0U)
01460         {
01461           /* Disable the half transfer interrupt */
01462           __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
01463         }
01464 
01465         /* DMA peripheral state is not updated in Half Transfer */
01466         /* but in Transfer Complete case */
01467 
01468        if(hdma->XferHalfCpltCallback != NULL)
01469         {
01470           /* Half transfer callback */
01471           hdma->XferHalfCpltCallback(hdma);
01472         }
01473       }
01474     }
01475 
01476     /* Transfer Complete Interrupt management ***********************************/
01477     else if (((tmpisr_bdma & (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TCIE) != 0U))
01478     {
01479       /* Clear the transfer complete flag */
01480       regs_bdma->IFCR = (BDMA_ISR_TCIF0) << (hdma->StreamIndex & 0x1FU);
01481 
01482       /* Disable the transfer complete interrupt if the DMA mode is Double Buffering */
01483       if((ccr_reg & BDMA_CCR_DBM) != 0U)
01484       {
01485         /* Current memory buffer used is Memory 0 */
01486         if((ccr_reg & BDMA_CCR_CT) == 0U)
01487         {
01488           if(hdma->XferM1CpltCallback != NULL)
01489           {
01490             /* Transfer complete Callback for Memory 1 */
01491             hdma->XferM1CpltCallback(hdma);
01492           }
01493         }
01494         /* Current memory buffer used is Memory 1 */
01495         else
01496         {
01497           if(hdma->XferCpltCallback != NULL)
01498           {
01499             /* Transfer complete Callback for Memory 0 */
01500             hdma->XferCpltCallback(hdma);
01501           }
01502         }
01503       }
01504       else
01505       {
01506         if((ccr_reg & BDMA_CCR_CIRC) == 0U)
01507         {
01508           /* Disable the transfer complete and error interrupt, if the DMA mode is not CIRCULAR */
01509           __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
01510 
01511           /* Change the DMA state */
01512           hdma->State = HAL_DMA_STATE_READY;
01513 
01514           /* Process Unlocked */
01515           __HAL_UNLOCK(hdma);
01516         }
01517 
01518         if(hdma->XferCpltCallback != NULL)
01519         {
01520           /* Transfer complete callback */
01521           hdma->XferCpltCallback(hdma);
01522         }
01523       }
01524     }
01525     /* Transfer Error Interrupt management **************************************/
01526     else if (((tmpisr_bdma & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TEIE) != 0U))
01527     {
01528       /* When a DMA transfer error occurs */
01529       /* A hardware clear of its EN bits is performed */
01530       /* Disable ALL DMA IT */
01531       __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
01532 
01533       /* Clear all flags */
01534       regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
01535 
01536       /* Update error code */
01537       hdma->ErrorCode = HAL_DMA_ERROR_TE;
01538 
01539       /* Change the DMA state */
01540       hdma->State = HAL_DMA_STATE_READY;
01541 
01542       /* Process Unlocked */
01543       __HAL_UNLOCK(hdma);
01544 
01545       if (hdma->XferErrorCallback != NULL)
01546       {
01547         /* Transfer error callback */
01548         hdma->XferErrorCallback(hdma);
01549       }
01550     }
01551     else
01552     {
01553       /* Nothing To Do */
01554     }
01555   }
01556   else
01557   {
01558     /* Nothing To Do */
01559   }
01560 }
01561 
01562 /**
01563   * @brief  Register callbacks
01564   * @param  hdma:                 pointer to a DMA_HandleTypeDef structure that contains
01565   *                               the configuration information for the specified DMA Stream.
01566   * @param  CallbackID:           User Callback identifier
01567   *                               a DMA_HandleTypeDef structure as parameter.
01568   * @param  pCallback:            pointer to private callback function which has pointer to
01569   *                               a DMA_HandleTypeDef structure as parameter.
01570   * @retval HAL status
01571   */
01572 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
01573 {
01574 
01575   HAL_StatusTypeDef status = HAL_OK;
01576 
01577   /* Check the DMA peripheral handle */
01578   if(hdma == NULL)
01579   {
01580     return HAL_ERROR;
01581   }
01582 
01583   /* Process locked */
01584   __HAL_LOCK(hdma);
01585 
01586   if(HAL_DMA_STATE_READY == hdma->State)
01587   {
01588     switch (CallbackID)
01589     {
01590     case  HAL_DMA_XFER_CPLT_CB_ID:
01591       hdma->XferCpltCallback = pCallback;
01592       break;
01593 
01594     case  HAL_DMA_XFER_HALFCPLT_CB_ID:
01595       hdma->XferHalfCpltCallback = pCallback;
01596       break;
01597 
01598     case  HAL_DMA_XFER_M1CPLT_CB_ID:
01599       hdma->XferM1CpltCallback = pCallback;
01600       break;
01601 
01602     case  HAL_DMA_XFER_M1HALFCPLT_CB_ID:
01603       hdma->XferM1HalfCpltCallback = pCallback;
01604       break;
01605 
01606     case  HAL_DMA_XFER_ERROR_CB_ID:
01607       hdma->XferErrorCallback = pCallback;
01608       break;
01609 
01610     case  HAL_DMA_XFER_ABORT_CB_ID:
01611       hdma->XferAbortCallback = pCallback;
01612       break;
01613 
01614     default:
01615       status =  HAL_ERROR;
01616       break;
01617     }
01618   }
01619   else
01620   {
01621     /* Return error status */
01622     status =  HAL_ERROR;
01623   }
01624 
01625   /* Release Lock */
01626   __HAL_UNLOCK(hdma);
01627 
01628   return status;
01629 }
01630 
01631 /**
01632   * @brief  UnRegister callbacks
01633   * @param  hdma:                 pointer to a DMA_HandleTypeDef structure that contains
01634   *                               the configuration information for the specified DMA Stream.
01635   * @param  CallbackID:           User Callback identifier
01636   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
01637   * @retval HAL status
01638   */
01639 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
01640 {
01641   HAL_StatusTypeDef status = HAL_OK;
01642 
01643   /* Check the DMA peripheral handle */
01644   if(hdma == NULL)
01645   {
01646     return HAL_ERROR;
01647   }
01648 
01649   /* Process locked */
01650   __HAL_LOCK(hdma);
01651 
01652   if(HAL_DMA_STATE_READY == hdma->State)
01653   {
01654     switch (CallbackID)
01655     {
01656     case  HAL_DMA_XFER_CPLT_CB_ID:
01657       hdma->XferCpltCallback = NULL;
01658       break;
01659 
01660     case  HAL_DMA_XFER_HALFCPLT_CB_ID:
01661       hdma->XferHalfCpltCallback = NULL;
01662       break;
01663 
01664     case  HAL_DMA_XFER_M1CPLT_CB_ID:
01665       hdma->XferM1CpltCallback = NULL;
01666       break;
01667 
01668     case  HAL_DMA_XFER_M1HALFCPLT_CB_ID:
01669       hdma->XferM1HalfCpltCallback = NULL;
01670       break;
01671 
01672     case  HAL_DMA_XFER_ERROR_CB_ID:
01673       hdma->XferErrorCallback = NULL;
01674       break;
01675 
01676     case  HAL_DMA_XFER_ABORT_CB_ID:
01677       hdma->XferAbortCallback = NULL;
01678       break;
01679 
01680     case   HAL_DMA_XFER_ALL_CB_ID:
01681       hdma->XferCpltCallback = NULL;
01682       hdma->XferHalfCpltCallback = NULL;
01683       hdma->XferM1CpltCallback = NULL;
01684       hdma->XferM1HalfCpltCallback = NULL;
01685       hdma->XferErrorCallback = NULL;
01686       hdma->XferAbortCallback = NULL;
01687       break;
01688 
01689     default:
01690       status = HAL_ERROR;
01691       break;
01692     }
01693   }
01694   else
01695   {
01696     status = HAL_ERROR;
01697   }
01698 
01699   /* Release Lock */
01700   __HAL_UNLOCK(hdma);
01701 
01702   return status;
01703 }
01704 
01705 /**
01706   * @}
01707   */
01708 
01709 /** @addtogroup DMA_Exported_Functions_Group3
01710   *
01711 @verbatim
01712  ===============================================================================
01713                     ##### State and Errors functions #####
01714  ===============================================================================
01715     [..]
01716     This subsection provides functions allowing to
01717       (+) Check the DMA state
01718       (+) Get error code
01719 
01720 @endverbatim
01721   * @{
01722   */
01723 
01724 /**
01725   * @brief  Returns the DMA state.
01726   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
01727   *               the configuration information for the specified DMA Stream.
01728   * @retval HAL state
01729   */
01730 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
01731 {
01732   return hdma->State;
01733 }
01734 
01735 /**
01736   * @brief  Return the DMA error code
01737   * @param  hdma : pointer to a DMA_HandleTypeDef structure that contains
01738   *              the configuration information for the specified DMA Stream.
01739   * @retval DMA Error Code
01740   */
01741 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
01742 {
01743   return hdma->ErrorCode;
01744 }
01745 
01746 /**
01747   * @}
01748   */
01749 
01750 /**
01751   * @}
01752   */
01753 
01754 /** @addtogroup DMA_Private_Functions
01755   * @{
01756   */
01757 
01758 /**
01759   * @brief  Sets the DMA Transfer parameter.
01760   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
01761   *                     the configuration information for the specified DMA Stream.
01762   * @param  SrcAddress: The source memory Buffer address
01763   * @param  DstAddress: The destination memory Buffer address
01764   * @param  DataLength: The length of data to be transferred from source to destination
01765   * @retval None
01766   */
01767 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
01768 {
01769   /* calculate DMA base and stream number */
01770   DMA_Base_Registers  *regs_dma  = (DMA_Base_Registers *)hdma->StreamBaseAddress;
01771   BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
01772 
01773   if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
01774   {
01775     /* Clear the DMAMUX synchro overrun flag */
01776     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
01777 
01778     if(hdma->DMAmuxRequestGen != 0U)
01779     {
01780       /* Clear the DMAMUX request generator overrun flag */
01781       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
01782     }
01783   }
01784 
01785   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
01786   {
01787     /* Clear all interrupt flags at correct offset within the register */
01788     regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
01789 
01790     /* Clear DBM bit */
01791     ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
01792 
01793     /* Configure DMA Stream data length */
01794     ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = DataLength;
01795 
01796     /* Peripheral to Memory */
01797     if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
01798     {
01799       /* Configure DMA Stream destination address */
01800       ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = DstAddress;
01801 
01802       /* Configure DMA Stream source address */
01803       ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = SrcAddress;
01804     }
01805     /* Memory to Peripheral */
01806     else
01807     {
01808       /* Configure DMA Stream source address */
01809       ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = SrcAddress;
01810 
01811       /* Configure DMA Stream destination address */
01812       ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = DstAddress;
01813     }
01814   }
01815   else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
01816   {
01817     /* Clear all flags */
01818     regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
01819 
01820     /* Configure DMA Channel data length */
01821     ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = DataLength;
01822 
01823     /* Peripheral to Memory */
01824     if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
01825     {
01826       /* Configure DMA Channel destination address */
01827       ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = DstAddress;
01828 
01829       /* Configure DMA Channel source address */
01830       ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = SrcAddress;
01831     }
01832     /* Memory to Peripheral */
01833     else
01834     {
01835       /* Configure DMA Channel source address */
01836       ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = SrcAddress;
01837 
01838       /* Configure DMA Channel destination address */
01839       ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = DstAddress;
01840     }
01841   }
01842   else
01843   {
01844     /* Nothing To Do */
01845   }
01846 }
01847 
01848 /**
01849   * @brief  Returns the DMA Stream base address depending on stream number
01850   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
01851   *                     the configuration information for the specified DMA Stream.
01852   * @retval Stream base address
01853   */
01854 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
01855 {
01856   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
01857   {
01858     uint32_t stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U;
01859 
01860     /* lookup table for necessary bitshift of flags within status registers */
01861     static const uint8_t flagBitshiftOffset[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U};
01862     hdma->StreamIndex = flagBitshiftOffset[stream_number & 0x7U];
01863 
01864     if (stream_number > 3U)
01865     {
01866       /* return pointer to HISR and HIFCR */
01867       hdma->StreamBaseAddress = (((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU)) + 4U);
01868     }
01869     else
01870     {
01871       /* return pointer to LISR and LIFCR */
01872       hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU));
01873     }
01874   }
01875   else /* BDMA instance(s) */
01876   {
01877     /* return pointer to ISR and IFCR */
01878     hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0xFFU));
01879   }
01880 
01881   return hdma->StreamBaseAddress;
01882 }
01883 
01884 /**
01885   * @brief  Check compatibility between FIFO threshold level and size of the memory burst
01886   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
01887   *                     the configuration information for the specified DMA Stream.
01888   * @retval HAL status
01889   */
01890 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma)
01891 {
01892   HAL_StatusTypeDef status = HAL_OK;
01893 
01894   /* Memory Data size equal to Byte */
01895   if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_BYTE)
01896   {
01897     switch (hdma->Init.FIFOThreshold)
01898     {
01899       case DMA_FIFO_THRESHOLD_1QUARTERFULL:
01900       case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
01901 
01902         if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
01903         {
01904           status = HAL_ERROR;
01905         }
01906         break;
01907 
01908       case DMA_FIFO_THRESHOLD_HALFFULL:
01909         if (hdma->Init.MemBurst == DMA_MBURST_INC16)
01910         {
01911           status = HAL_ERROR;
01912         }
01913         break;
01914 
01915       case DMA_FIFO_THRESHOLD_FULL:
01916         break;
01917 
01918       default:
01919         break;
01920     }
01921   }
01922 
01923   /* Memory Data size equal to Half-Word */
01924   else if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
01925   {
01926     switch (hdma->Init.FIFOThreshold)
01927     {
01928       case DMA_FIFO_THRESHOLD_1QUARTERFULL:
01929       case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
01930         status = HAL_ERROR;
01931         break;
01932 
01933       case DMA_FIFO_THRESHOLD_HALFFULL:
01934         if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
01935         {
01936           status = HAL_ERROR;
01937         }
01938         break;
01939 
01940       case DMA_FIFO_THRESHOLD_FULL:
01941         if (hdma->Init.MemBurst == DMA_MBURST_INC16)
01942         {
01943           status = HAL_ERROR;
01944         }
01945         break;
01946 
01947       default:
01948         break;
01949     }
01950   }
01951 
01952   /* Memory Data size equal to Word */
01953   else
01954   {
01955     switch (hdma->Init.FIFOThreshold)
01956     {
01957       case DMA_FIFO_THRESHOLD_1QUARTERFULL:
01958       case DMA_FIFO_THRESHOLD_HALFFULL:
01959       case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
01960         status = HAL_ERROR;
01961         break;
01962 
01963       case DMA_FIFO_THRESHOLD_FULL:
01964         if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
01965         {
01966           status = HAL_ERROR;
01967         }
01968     break;
01969 
01970       default:
01971         break;
01972     }
01973   }
01974 
01975   return status;
01976 }
01977 
01978 /**
01979   * @brief  Updates the DMA handle with the DMAMUX  channel and status mask depending on stream number
01980   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
01981   *                     the configuration information for the specified DMA Stream.
01982   * @retval HAL status
01983   */
01984 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
01985 {
01986   uint32_t stream_number;
01987   uint32_t stream_baseaddress = (uint32_t)((uint32_t*)hdma->Instance);
01988 
01989   if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U)
01990   {
01991     /* BDMA Channels are connected to DMAMUX2 channels */
01992     stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 8U) / 20U;
01993     hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX2_Channel0) + (stream_number * 4U)));
01994     hdma->DMAmuxChannelStatus = DMAMUX2_ChannelStatus;
01995     hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU);
01996   }
01997   else
01998   {
01999     /* DMA1/DMA2 Streams are connected to DMAMUX1 channels */
02000     stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U;
02001 
02002     if((stream_baseaddress <= ((uint32_t)DMA2_Stream7) ) && \
02003        (stream_baseaddress >= ((uint32_t)DMA2_Stream0)))
02004     {
02005       stream_number += 8U;
02006     }
02007     hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_Channel0) + (stream_number * 4U)));
02008     hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
02009     hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU);
02010   }
02011 }
02012 
02013 /**
02014   * @brief  Updates the DMA handle with the DMAMUX  request generator params
02015   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
02016   *                     the configuration information for the specified DMA Stream.
02017   * @retval HAL status
02018   */
02019 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
02020 {
02021   uint32_t request =  hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
02022 
02023   if((request >= DMA_REQUEST_GENERATOR0) && (request <= DMA_REQUEST_GENERATOR7))
02024   {
02025     if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U)
02026     {
02027       /* BDMA Channels are connected to DMAMUX2 request generator blocks */
02028       hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX2_RequestGenerator0) + ((request - 1U) * 4U)));
02029 
02030       hdma->DMAmuxRequestGenStatus = DMAMUX2_RequestGenStatus;
02031     }
02032     else
02033     {
02034       /* DMA1 and DMA2 Streams use DMAMUX1 request generator blocks */
02035       hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
02036 
02037       hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
02038     }
02039 
02040     hdma->DMAmuxRequestGenStatusMask = 1UL << (request - 1U);
02041   }
02042 }
02043 
02044 /**
02045   * @}
02046   */
02047 
02048 #endif /* HAL_DMA_MODULE_ENABLED */
02049 /**
02050   * @}
02051   */
02052 
02053 /**
02054   * @}
02055   */
02056