STM32F103xB HAL User Manual
stm32f1xx_hal_dma.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f1xx_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   @verbatim
00012   ==============================================================================
00013                         ##### How to use this driver #####
00014   ==============================================================================
00015   [..]
00016    (#) Enable and configure the peripheral to be connected to the DMA Channel
00017        (except for internal SRAM / FLASH memories: no initialization is 
00018        necessary). Please refer to the Reference manual for connection between peripherals
00019        and DMA requests.
00020 
00021    (#) For a given Channel, program the required configuration through the following parameters:
00022        Channel request, Transfer Direction, Source and Destination data formats,
00023        Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
00024        using HAL_DMA_Init() function.
00025 
00026    (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error 
00027        detection.
00028                     
00029    (#) Use HAL_DMA_Abort() function to abort the current transfer
00030                    
00031      -@-   In Memory-to-Memory transfer mode, Circular mode is not allowed.
00032      *** Polling mode IO operation ***
00033      =================================
00034     [..]
00035           (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
00036               address and destination address and the Length of data to be transferred
00037           (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
00038               case a fixed Timeout can be configured by User depending from his application.
00039 
00040      *** Interrupt mode IO operation ***
00041      ===================================
00042     [..]
00043           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
00044           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
00045           (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
00046               Source address and destination address and the Length of data to be transferred.
00047               In this case the DMA interrupt is configured
00048           (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
00049           (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
00050               add his own function by customization of function pointer XferCpltCallback and
00051               XferErrorCallback (i.e. a member of DMA handle structure).
00052 
00053      *** DMA HAL driver macros list ***
00054      ============================================= 
00055       [..]
00056        Below the list of most used macros in DMA HAL driver.
00057 
00058        (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
00059        (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
00060        (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
00061        (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
00062        (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
00063        (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
00064        (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not. 
00065 
00066      [..] 
00067       (@) You can refer to the DMA HAL driver header file for more useful macros  
00068 
00069   @endverbatim
00070   ******************************************************************************
00071   * @attention
00072   *
00073   * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
00074   * All rights reserved.</center></h2>
00075   *
00076   * This software component is licensed by ST under BSD 3-Clause license,
00077   * the "License"; You may not use this file except in compliance with the
00078   * License. You may obtain a copy of the License at:
00079   *                        opensource.org/licenses/BSD-3-Clause
00080   *
00081   ******************************************************************************
00082   */
00083 
00084 /* Includes ------------------------------------------------------------------*/
00085 #include "stm32f1xx_hal.h"
00086 
00087 /** @addtogroup STM32F1xx_HAL_Driver
00088   * @{
00089   */
00090 
00091 /** @defgroup DMA DMA
00092   * @brief DMA HAL module driver
00093   * @{
00094   */
00095 
00096 #ifdef HAL_DMA_MODULE_ENABLED
00097 
00098 /* Private typedef -----------------------------------------------------------*/
00099 /* Private define ------------------------------------------------------------*/
00100 /* Private macro -------------------------------------------------------------*/
00101 /* Private variables ---------------------------------------------------------*/
00102 /* Private function prototypes -----------------------------------------------*/
00103 /** @defgroup DMA_Private_Functions DMA Private Functions
00104   * @{
00105   */
00106 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
00107 /**
00108   * @}
00109   */
00110 
00111 /* Exported functions ---------------------------------------------------------*/
00112 
00113 /** @defgroup DMA_Exported_Functions DMA Exported Functions
00114   * @{
00115   */
00116 
00117 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
00118   *  @brief   Initialization and de-initialization functions 
00119   *
00120 @verbatim
00121  ===============================================================================
00122              ##### Initialization and de-initialization functions  #####
00123  ===============================================================================
00124     [..]
00125     This section provides functions allowing to initialize the DMA Channel source
00126     and destination addresses, incrementation and data sizes, transfer direction, 
00127     circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
00128     [..]
00129     The HAL_DMA_Init() function follows the DMA configuration procedures as described in
00130     reference manual.  
00131 
00132 @endverbatim
00133   * @{
00134   */
00135 
00136 /**
00137   * @brief  Initialize the DMA according to the specified
00138   *         parameters in the DMA_InitTypeDef and initialize the associated handle.
00139   * @param  hdma: Pointer to a DMA_HandleTypeDef structure that contains
00140   *               the configuration information for the specified DMA Channel.
00141   * @retval HAL status
00142   */
00143 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
00144 {
00145   uint32_t tmp = 0U;
00146 
00147   /* Check the DMA handle allocation */
00148   if(hdma == NULL)
00149   {
00150     return HAL_ERROR;
00151   }
00152 
00153   /* Check the parameters */
00154   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
00155   assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
00156   assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
00157   assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
00158   assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
00159   assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
00160   assert_param(IS_DMA_MODE(hdma->Init.Mode));
00161   assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
00162 
00163 #if defined (DMA2)
00164   /* calculation of the channel index */
00165   if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
00166   {
00167     /* DMA1 */
00168     hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
00169     hdma->DmaBaseAddress = DMA1;
00170   }
00171   else 
00172   {
00173     /* DMA2 */
00174     hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2;
00175     hdma->DmaBaseAddress = DMA2;
00176   }
00177 #else
00178   /* DMA1 */
00179   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
00180   hdma->DmaBaseAddress = DMA1;
00181 #endif /* DMA2 */
00182 
00183   /* Change DMA peripheral state */
00184   hdma->State = HAL_DMA_STATE_BUSY;
00185 
00186   /* Get the CR register value */
00187   tmp = hdma->Instance->CCR;
00188 
00189   /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
00190   tmp &= ((uint32_t)~(DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  | \
00191                       DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   | \
00192                       DMA_CCR_DIR));
00193 
00194   /* Prepare the DMA Channel configuration */
00195   tmp |=  hdma->Init.Direction        |
00196           hdma->Init.PeriphInc           | hdma->Init.MemInc           |
00197           hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
00198           hdma->Init.Mode                | hdma->Init.Priority;
00199 
00200   /* Write to DMA Channel CR register */
00201   hdma->Instance->CCR = tmp;
00202 
00203   /* Initialise the error code */
00204   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00205 
00206   /* Initialize the DMA state*/
00207   hdma->State = HAL_DMA_STATE_READY;
00208   /* Allocate lock resource and initialize it */
00209   hdma->Lock = HAL_UNLOCKED;
00210 
00211   return HAL_OK;
00212 }
00213 
00214 /**
00215   * @brief  DeInitialize the DMA peripheral.
00216   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00217   *               the configuration information for the specified DMA Channel.
00218   * @retval HAL status
00219   */
00220 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
00221 {
00222   /* Check the DMA handle allocation */
00223   if(hdma == NULL)
00224   {
00225     return HAL_ERROR;
00226   }
00227 
00228   /* Check the parameters */
00229   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
00230 
00231   /* Disable the selected DMA Channelx */
00232   __HAL_DMA_DISABLE(hdma);
00233 
00234   /* Reset DMA Channel control register */
00235   hdma->Instance->CCR  = 0U;
00236 
00237   /* Reset DMA Channel Number of Data to Transfer register */
00238   hdma->Instance->CNDTR = 0U;
00239 
00240   /* Reset DMA Channel peripheral address register */
00241   hdma->Instance->CPAR  = 0U;
00242 
00243   /* Reset DMA Channel memory address register */
00244   hdma->Instance->CMAR = 0U;
00245 
00246 #if defined (DMA2)
00247   /* calculation of the channel index */
00248   if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
00249   {
00250     /* DMA1 */
00251     hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
00252     hdma->DmaBaseAddress = DMA1;
00253   }
00254   else
00255   {
00256     /* DMA2 */
00257     hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2;
00258     hdma->DmaBaseAddress = DMA2;
00259   }
00260 #else
00261   /* DMA1 */
00262   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
00263   hdma->DmaBaseAddress = DMA1;
00264 #endif /* DMA2 */
00265 
00266   /* Clear all flags */
00267   hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex));
00268 
00269   /* Clean all callbacks */
00270   hdma->XferCpltCallback = NULL;
00271   hdma->XferHalfCpltCallback = NULL;
00272   hdma->XferErrorCallback = NULL;
00273   hdma->XferAbortCallback = NULL;
00274 
00275   /* Reset the error code */
00276   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00277 
00278   /* Reset the DMA state */
00279   hdma->State = HAL_DMA_STATE_RESET;
00280 
00281   /* Release Lock */
00282   __HAL_UNLOCK(hdma);
00283 
00284   return HAL_OK;
00285 }
00286 
00287 /**
00288   * @}
00289   */
00290 
00291 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
00292   *  @brief   Input and Output operation functions
00293   *
00294 @verbatim
00295  ===============================================================================
00296                       #####  IO operation functions  #####
00297  ===============================================================================
00298     [..]  This section provides functions allowing to:
00299       (+) Configure the source, destination address and data length and Start DMA transfer
00300       (+) Configure the source, destination address and data length and
00301           Start DMA transfer with interrupt
00302       (+) Abort DMA transfer
00303       (+) Poll for transfer complete
00304       (+) Handle DMA interrupt request
00305 
00306 @endverbatim
00307   * @{
00308   */
00309 
00310 /**
00311   * @brief  Start the DMA Transfer.
00312   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00313   *               the configuration information for the specified DMA Channel.
00314   * @param  SrcAddress: The source memory Buffer address
00315   * @param  DstAddress: The destination memory Buffer address
00316   * @param  DataLength: The length of data to be transferred from source to destination
00317   * @retval HAL status
00318   */
00319 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
00320 {
00321   HAL_StatusTypeDef status = HAL_OK;
00322 
00323   /* Check the parameters */
00324   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
00325 
00326   /* Process locked */
00327   __HAL_LOCK(hdma);
00328 
00329   if(HAL_DMA_STATE_READY == hdma->State)
00330   {
00331     /* Change DMA peripheral state */
00332     hdma->State = HAL_DMA_STATE_BUSY;
00333     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00334             
00335     /* Disable the peripheral */
00336     __HAL_DMA_DISABLE(hdma);
00337     
00338     /* Configure the source, destination address and the data length & clear flags*/
00339     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
00340     
00341     /* Enable the Peripheral */
00342     __HAL_DMA_ENABLE(hdma);
00343   }
00344   else
00345   {
00346    /* Process Unlocked */
00347    __HAL_UNLOCK(hdma);  
00348    status = HAL_BUSY;
00349   }  
00350   return status;
00351 }
00352 
00353 /**
00354   * @brief  Start the DMA Transfer with interrupt enabled.
00355   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00356   *               the configuration information for the specified DMA Channel.
00357   * @param  SrcAddress: The source memory Buffer address
00358   * @param  DstAddress: The destination memory Buffer address
00359   * @param  DataLength: The length of data to be transferred from source to destination
00360   * @retval HAL status
00361   */
00362 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
00363 {
00364   HAL_StatusTypeDef status = HAL_OK;
00365 
00366   /* Check the parameters */
00367   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
00368 
00369   /* Process locked */
00370   __HAL_LOCK(hdma);
00371   
00372   if(HAL_DMA_STATE_READY == hdma->State)
00373   {
00374     /* Change DMA peripheral state */
00375     hdma->State = HAL_DMA_STATE_BUSY;
00376     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
00377     
00378     /* Disable the peripheral */
00379     __HAL_DMA_DISABLE(hdma);
00380     
00381     /* Configure the source, destination address and the data length & clear flags*/
00382     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
00383     
00384     /* Enable the transfer complete interrupt */
00385     /* Enable the transfer Error interrupt */
00386     if(NULL != hdma->XferHalfCpltCallback)
00387     {
00388       /* Enable the Half transfer complete interrupt as well */
00389       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
00390     }
00391     else
00392     {
00393       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
00394       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
00395     }
00396     /* Enable the Peripheral */
00397     __HAL_DMA_ENABLE(hdma);
00398   }
00399   else
00400   {      
00401     /* Process Unlocked */
00402     __HAL_UNLOCK(hdma); 
00403 
00404     /* Remain BUSY */
00405     status = HAL_BUSY;
00406   }    
00407   return status;
00408 }
00409 
00410 /**
00411   * @brief  Abort the DMA Transfer.
00412   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00413   *               the configuration information for the specified DMA Channel.
00414   * @retval HAL status
00415   */
00416 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
00417 {
00418   HAL_StatusTypeDef status = HAL_OK;
00419   
00420   if(hdma->State != HAL_DMA_STATE_BUSY)
00421   {
00422     /* no transfer ongoing */
00423     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
00424     
00425     /* Process Unlocked */
00426     __HAL_UNLOCK(hdma);
00427     
00428     return HAL_ERROR;
00429   }
00430   else
00431 
00432   {
00433     /* Disable DMA IT */
00434     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
00435       
00436     /* Disable the channel */
00437     __HAL_DMA_DISABLE(hdma);
00438       
00439     /* Clear all flags */
00440     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
00441   }
00442   /* Change the DMA state */
00443   hdma->State = HAL_DMA_STATE_READY;
00444 
00445   /* Process Unlocked */
00446   __HAL_UNLOCK(hdma);      
00447   
00448   return status; 
00449 }
00450 
00451 /**
00452   * @brief  Aborts the DMA Transfer in Interrupt mode.
00453   * @param  hdma  : pointer to a DMA_HandleTypeDef structure that contains
00454   *                 the configuration information for the specified DMA Channel.
00455   * @retval HAL status
00456   */
00457 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
00458 {  
00459   HAL_StatusTypeDef status = HAL_OK;
00460   
00461   if(HAL_DMA_STATE_BUSY != hdma->State)
00462   {
00463     /* no transfer ongoing */
00464     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
00465         
00466     status = HAL_ERROR;
00467   }
00468   else
00469   { 
00470     /* Disable DMA IT */
00471     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
00472 
00473     /* Disable the channel */
00474     __HAL_DMA_DISABLE(hdma);
00475 
00476     /* Clear all flags */
00477     __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_GI_FLAG_INDEX(hdma));
00478 
00479     /* Change the DMA state */
00480     hdma->State = HAL_DMA_STATE_READY;
00481 
00482     /* Process Unlocked */
00483     __HAL_UNLOCK(hdma);
00484 
00485     /* Call User Abort callback */
00486     if(hdma->XferAbortCallback != NULL)
00487     {
00488       hdma->XferAbortCallback(hdma);
00489     } 
00490   }
00491   return status;
00492 }
00493 
00494 /**
00495   * @brief  Polling for transfer complete.
00496   * @param  hdma:    pointer to a DMA_HandleTypeDef structure that contains
00497   *                  the configuration information for the specified DMA Channel.
00498   * @param  CompleteLevel: Specifies the DMA level complete.
00499   * @param  Timeout:       Timeout duration.
00500   * @retval HAL status
00501   */
00502 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
00503 {
00504   uint32_t temp;
00505   uint32_t tickstart = 0U;
00506 
00507   if(HAL_DMA_STATE_BUSY != hdma->State)
00508   {
00509     /* no transfer ongoing */
00510     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
00511     __HAL_UNLOCK(hdma);
00512     return HAL_ERROR;
00513   }
00514 
00515   /* Polling mode not supported in circular mode */
00516   if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC))
00517   {
00518     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
00519     return HAL_ERROR;
00520   }
00521   
00522   /* Get the level transfer complete flag */
00523   if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
00524   {
00525     /* Transfer Complete flag */
00526     temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma);
00527   }
00528   else
00529   {
00530     /* Half Transfer Complete flag */
00531     temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma);
00532   }
00533 
00534   /* Get tick */
00535   tickstart = HAL_GetTick();
00536 
00537   while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET)
00538   {
00539     if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET))
00540     {
00541       /* When a DMA transfer error occurs */
00542       /* A hardware clear of its EN bits is performed */
00543       /* Clear all flags */
00544       hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
00545 
00546       /* Update error code */
00547       SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
00548 
00549       /* Change the DMA state */
00550       hdma->State= HAL_DMA_STATE_READY;
00551 
00552       /* Process Unlocked */
00553       __HAL_UNLOCK(hdma);
00554 
00555       return HAL_ERROR;
00556     }
00557     /* Check for the Timeout */
00558     if(Timeout != HAL_MAX_DELAY)
00559     {
00560       if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
00561       {
00562         /* Update error code */
00563         SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT);
00564 
00565         /* Change the DMA state */
00566         hdma->State = HAL_DMA_STATE_READY;
00567 
00568         /* Process Unlocked */
00569         __HAL_UNLOCK(hdma);
00570 
00571         return HAL_ERROR;
00572       }
00573     }
00574   }
00575 
00576   if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
00577   {
00578     /* Clear the transfer complete flag */
00579     __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
00580 
00581     /* The selected Channelx EN bit is cleared (DMA is disabled and
00582     all transfers are complete) */
00583     hdma->State = HAL_DMA_STATE_READY;
00584   }
00585   else
00586   {
00587     /* Clear the half transfer complete flag */
00588     __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
00589   }
00590   
00591   /* Process unlocked */
00592   __HAL_UNLOCK(hdma);
00593 
00594   return HAL_OK;
00595 }
00596 
00597 /**
00598   * @brief  Handles DMA interrupt request.
00599   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00600   *               the configuration information for the specified DMA Channel.  
00601   * @retval None
00602   */
00603 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
00604 {
00605   uint32_t flag_it = hdma->DmaBaseAddress->ISR;
00606   uint32_t source_it = hdma->Instance->CCR;
00607   
00608   /* Half Transfer Complete Interrupt management ******************************/
00609   if (((flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_HT) != RESET))
00610   {
00611     /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
00612     if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
00613     {
00614       /* Disable the half transfer interrupt */
00615       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
00616     }
00617     /* Clear the half transfer complete flag */
00618     __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
00619 
00620     /* DMA peripheral state is not updated in Half Transfer */
00621     /* but in Transfer Complete case */
00622 
00623     if(hdma->XferHalfCpltCallback != NULL)
00624     {
00625       /* Half transfer callback */
00626       hdma->XferHalfCpltCallback(hdma);
00627     }
00628   }
00629 
00630   /* Transfer Complete Interrupt management ***********************************/
00631   else if (((flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_TC) != RESET))
00632   {
00633     if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
00634     {
00635       /* Disable the transfer complete and error interrupt */
00636       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);  
00637 
00638       /* Change the DMA state */
00639       hdma->State = HAL_DMA_STATE_READY;
00640     }
00641     /* Clear the transfer complete flag */
00642       __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
00643 
00644     /* Process Unlocked */
00645     __HAL_UNLOCK(hdma);
00646 
00647     if(hdma->XferCpltCallback != NULL)
00648     {
00649       /* Transfer complete callback */
00650       hdma->XferCpltCallback(hdma);
00651     }
00652   }
00653 
00654   /* Transfer Error Interrupt management **************************************/
00655   else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE)))
00656   {
00657     /* When a DMA transfer error occurs */
00658     /* A hardware clear of its EN bits is performed */
00659     /* Disable ALL DMA IT */
00660     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
00661 
00662     /* Clear all flags */
00663     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
00664 
00665     /* Update error code */
00666     hdma->ErrorCode = HAL_DMA_ERROR_TE;
00667 
00668     /* Change the DMA state */
00669     hdma->State = HAL_DMA_STATE_READY;
00670 
00671     /* Process Unlocked */
00672     __HAL_UNLOCK(hdma);
00673 
00674     if (hdma->XferErrorCallback != NULL)
00675     {
00676       /* Transfer error callback */
00677       hdma->XferErrorCallback(hdma);
00678     }
00679   }
00680   return;
00681 }
00682 
00683 /**
00684   * @brief Register callbacks
00685   * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
00686   *              the configuration information for the specified DMA Channel.
00687   * @param CallbackID: User Callback identifer
00688   *                    a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
00689   * @param pCallback: pointer to private callbacsk function which has pointer to 
00690   *                   a DMA_HandleTypeDef structure as parameter.
00691   * @retval HAL status
00692   */                          
00693 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma))
00694 {
00695   HAL_StatusTypeDef status = HAL_OK;
00696   
00697   /* Process locked */
00698   __HAL_LOCK(hdma);
00699   
00700   if(HAL_DMA_STATE_READY == hdma->State)
00701   {
00702     switch (CallbackID)
00703     {
00704     case  HAL_DMA_XFER_CPLT_CB_ID:
00705       hdma->XferCpltCallback = pCallback;
00706       break;
00707       
00708     case  HAL_DMA_XFER_HALFCPLT_CB_ID:
00709       hdma->XferHalfCpltCallback = pCallback;
00710       break;         
00711 
00712     case  HAL_DMA_XFER_ERROR_CB_ID:
00713       hdma->XferErrorCallback = pCallback;
00714       break;         
00715       
00716     case  HAL_DMA_XFER_ABORT_CB_ID:
00717       hdma->XferAbortCallback = pCallback;
00718       break; 
00719       
00720     default:
00721       status = HAL_ERROR;
00722       break;                                                            
00723     }
00724   }
00725   else
00726   {
00727     status = HAL_ERROR;
00728   } 
00729   
00730   /* Release Lock */
00731   __HAL_UNLOCK(hdma);
00732   
00733   return status;
00734 }
00735 
00736 /**
00737   * @brief UnRegister callbacks
00738   * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
00739   *              the configuration information for the specified DMA Channel.
00740   * @param CallbackID: User Callback identifer
00741   *                    a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
00742   * @retval HAL status
00743   */              
00744 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
00745 {
00746   HAL_StatusTypeDef status = HAL_OK;
00747 
00748   /* Process locked */
00749   __HAL_LOCK(hdma);
00750   
00751   if(HAL_DMA_STATE_READY == hdma->State)
00752   {
00753     switch (CallbackID)
00754     {
00755     case  HAL_DMA_XFER_CPLT_CB_ID:
00756       hdma->XferCpltCallback = NULL;
00757       break;
00758 
00759     case  HAL_DMA_XFER_HALFCPLT_CB_ID:
00760       hdma->XferHalfCpltCallback = NULL;
00761       break;         
00762 
00763     case  HAL_DMA_XFER_ERROR_CB_ID:
00764       hdma->XferErrorCallback = NULL;
00765       break;         
00766 
00767     case  HAL_DMA_XFER_ABORT_CB_ID:
00768       hdma->XferAbortCallback = NULL;
00769       break; 
00770 
00771     case   HAL_DMA_XFER_ALL_CB_ID:
00772       hdma->XferCpltCallback = NULL;
00773       hdma->XferHalfCpltCallback = NULL;
00774       hdma->XferErrorCallback = NULL;
00775       hdma->XferAbortCallback = NULL;
00776       break; 
00777 
00778     default:
00779       status = HAL_ERROR;
00780       break;
00781     }
00782   }
00783   else
00784   {
00785     status = HAL_ERROR;
00786   } 
00787   
00788   /* Release Lock */
00789   __HAL_UNLOCK(hdma);
00790   
00791   return status;
00792 }
00793   
00794 /**
00795   * @}
00796   */
00797 
00798 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
00799   *  @brief    Peripheral State and Errors functions
00800   *
00801 @verbatim
00802  ===============================================================================
00803             ##### Peripheral State and Errors functions #####
00804  ===============================================================================  
00805     [..]
00806     This subsection provides functions allowing to
00807       (+) Check the DMA state
00808       (+) Get error code
00809 
00810 @endverbatim
00811   * @{
00812   */
00813 
00814 /**
00815   * @brief  Return the DMA hande state.
00816   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
00817   *               the configuration information for the specified DMA Channel.
00818   * @retval HAL state
00819   */
00820 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
00821 {
00822   /* Return DMA handle state */
00823   return hdma->State;
00824 }
00825 
00826 /**
00827   * @brief  Return the DMA error code.
00828   * @param  hdma : pointer to a DMA_HandleTypeDef structure that contains
00829   *              the configuration information for the specified DMA Channel.
00830   * @retval DMA Error Code
00831   */
00832 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
00833 {
00834   return hdma->ErrorCode;
00835 }
00836 
00837 /**
00838   * @}
00839   */
00840 
00841 /**
00842   * @}
00843   */
00844 
00845 /** @addtogroup DMA_Private_Functions
00846   * @{
00847   */
00848 
00849 /**
00850   * @brief  Sets the DMA Transfer parameter.
00851   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
00852   *                     the configuration information for the specified DMA Channel.
00853   * @param  SrcAddress: The source memory Buffer address
00854   * @param  DstAddress: The destination memory Buffer address
00855   * @param  DataLength: The length of data to be transferred from source to destination
00856   * @retval HAL status
00857   */
00858 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
00859 {
00860   /* Clear all flags */
00861   hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
00862 
00863   /* Configure DMA Channel data length */
00864   hdma->Instance->CNDTR = DataLength;
00865 
00866   /* Memory to Peripheral */
00867   if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
00868   {
00869     /* Configure DMA Channel destination address */
00870     hdma->Instance->CPAR = DstAddress;
00871 
00872     /* Configure DMA Channel source address */
00873     hdma->Instance->CMAR = SrcAddress;
00874   }
00875   /* Peripheral to Memory */
00876   else
00877   {
00878     /* Configure DMA Channel source address */
00879     hdma->Instance->CPAR = SrcAddress;
00880 
00881     /* Configure DMA Channel destination address */
00882     hdma->Instance->CMAR = DstAddress;
00883   }
00884 }
00885 
00886 /**
00887   * @}
00888   */
00889 
00890 #endif /* HAL_DMA_MODULE_ENABLED */
00891 /**
00892   * @}
00893   */
00894 
00895 /**
00896   * @}
00897   */
00898 
00899 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/