STM32H735xx HAL User Manual
stm32h7xx_hal_mdma.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_mdma.c
00004   * @author  MCD Application Team
00005   * @brief  This file provides firmware functions to manage the following
00006   *         functionalities of the Master Direct Memory Access (MDMA) peripheral:
00007   *           + Initialization/de-initialization functions
00008   *           + I/O operation functions
00009   *           + Peripheral State and errors functions
00010   ******************************************************************************
00011   * @attention
00012   *
00013   * Copyright (c) 2017 STMicroelectronics.
00014   * All rights reserved.
00015   *
00016   * This software is licensed under terms that can be found in the LICENSE file
00017   * in the root directory of this software component.
00018   * If no LICENSE file comes with this software, it is provided AS-IS.
00019   *
00020   ******************************************************************************
00021   @verbatim
00022   ==============================================================================
00023                         ##### How to use this driver #####
00024   ==============================================================================
00025   [..]
00026    (#) Enable and configure the peripheral to be connected to the MDMA Channel
00027        (except for internal SRAM/FLASH memories: no initialization is
00028        necessary) please refer to Reference manual for connection between peripherals
00029        and MDMA requests.
00030 
00031    (#)
00032        For a given Channel use HAL_MDMA_Init function to program the required configuration through the following parameters:
00033        transfer request , channel priority, data endianness, Source increment, destination increment ,
00034        source data size, destination data size, data alignment, source Burst, destination Burst ,
00035        buffer Transfer Length, Transfer Trigger Mode (buffer transfer, block transfer, repeated block transfer
00036        or full transfer) source and destination block address offset, mask address and data.
00037 
00038        If using the MDMA in linked list mode then use function HAL_MDMA_LinkedList_CreateNode to fill a transfer node.
00039        Note that parameters given to the function HAL_MDMA_Init corresponds always to the node zero.
00040        Use function HAL_MDMA_LinkedList_AddNode to connect the created node to the linked list at a given position.
00041        User can make a linked list circular using function HAL_MDMA_LinkedList_EnableCircularMode , this function will automatically connect the
00042        last node of the list to the first one in order to make the list circular.
00043        In this case the linked list will loop on node 1 : first node connected after the initial transfer defined by the HAL_MDMA_Init
00044 
00045       -@-   The initial transfer itself (node 0 corresponding to the Init).
00046             User can disable the circular mode using function HAL_MDMA_LinkedList_DisableCircularMode, this function will then remove
00047             the connection between last node and first one.
00048 
00049        Function HAL_MDMA_LinkedList_RemoveNode can be used to remove (disconnect) a node from the transfer linked list.
00050        When a linked list is circular (last node connected to first one), if removing node1  (node where the linked list loops),
00051        the linked list remains circular and node 2 becomes the first one.
00052        Note that if the linked list is made circular the transfer will loop infinitely (or until aborted by the user).
00053 
00054     [..]
00055        (+) User can select the transfer trigger mode (parameter TransferTriggerMode) to define the amount of data to be
00056            transfer upon a request :
00057              (++) MDMA_BUFFER_TRANSFER : each request triggers a transfer of BufferTransferLength data
00058                with BufferTransferLength defined within the HAL_MDMA_Init.
00059              (++) MDMA_BLOCK_TRANSFER : each request triggers a transfer of a block
00060                with block size defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
00061                or within the current linked list node parameters.
00062              (++) MDMA_REPEAT_BLOCK_TRANSFER : each request triggers a transfer of a number of blocks
00063                with block size and number of blocks defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
00064                or within the current linked list node parameters.
00065              (++) MDMA_FULL_TRANSFER : each request triggers a full transfer
00066               all blocks and all nodes(if a linked list has been created using HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode).
00067 
00068      *** Polling mode IO operation ***
00069      =================================
00070     [..]
00071           (+) Use HAL_MDMA_Start() to start MDMA transfer after the configuration of Source
00072               address and destination address and the Length of data to be transferred.
00073           (+) Use HAL_MDMA_PollForTransfer() to poll for the end of current transfer or a transfer level
00074              In this case a fixed Timeout can be configured by User depending from his application.
00075           (+) Use HAL_MDMA_Abort() function to abort the current transfer : blocking method this API returns
00076               when the abort ends or timeout (should not be called from an interrupt service routine).
00077 
00078      *** Interrupt mode IO operation ***
00079      ===================================
00080     [..]
00081           (+) Configure the MDMA interrupt priority using HAL_NVIC_SetPriority()
00082           (+) Enable the MDMA IRQ handler using HAL_NVIC_EnableIRQ()
00083           (+) Use HAL_MDMA_Start_IT() to start MDMA transfer after the configuration of
00084               Source address and destination address and the Length of data to be transferred. In this
00085               case the MDMA interrupt is configured.
00086           (+) Use HAL_MDMA_IRQHandler() called under MDMA_IRQHandler() Interrupt subroutine
00087           (+) At the end of data transfer HAL_MDMA_IRQHandler() function is executed and user can
00088               add his own function by customization of function pointer XferCpltCallback and
00089               XferErrorCallback (i.e a member of MDMA handle structure).
00090 
00091           (+) Use HAL_MDMA_Abort_IT() function to abort the current transfer : non-blocking method. This API will finish the execution immediately
00092               then the callback XferAbortCallback (if specified  by the user) is asserted once the MDMA channel has effectively aborted.
00093               (could be called from an interrupt service routine).
00094 
00095           (+) Use functions HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback respectevely to register unregister user callbacks
00096               from the following list :
00097               (++) XferCpltCallback            : transfer complete callback.
00098               (++) XferBufferCpltCallback      : buffer transfer complete callback.
00099               (++) XferBlockCpltCallback       : block transfer complete callback.
00100               (++) XferRepeatBlockCpltCallback : repeated block transfer complete callback.
00101               (++) XferErrorCallback           : transfer error callback.
00102               (++) XferAbortCallback           : transfer abort complete callback.
00103 
00104     [..]
00105          (+)  If the transfer Request corresponds to SW request (MDMA_REQUEST_SW) User can use function HAL_MDMA_GenerateSWRequest to
00106               trigger requests manually. Function HAL_MDMA_GenerateSWRequest must be used with the following precautions:
00107               (++) This function returns an error if used while the Transfer has ended or not started.
00108               (++) If used while the current request has not been served yet (current request transfer on going)
00109                 this function returns an error and the new request is ignored.
00110 
00111               Generally this function should be used in conjunctions with the MDMA callbacks:
00112               (++) example 1:
00113                  (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BUFFER_TRANSFER
00114                  (+++) Register a callback for buffer transfer complete (using callback ID set to HAL_MDMA_XFER_BUFFERCPLT_CB_ID)
00115                  (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first BufferTransferLength data.
00116                  (+++) When the buffer transfer complete callback is asserted first buffer has been transferred and user can ask for a new buffer transfer
00117                    request using HAL_MDMA_GenerateSWRequest.
00118 
00119               (++) example 2:
00120                  (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BLOCK_TRANSFER
00121                  (+++) Register a callback for block transfer complete (using callback ID HAL_MDMA_XFER_BLOCKCPLT_CB_ID)
00122                  (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first block of data.
00123                  (+++) When the block transfer complete callback is asserted the first block has been transferred and user can ask
00124                    for a new block transfer request using HAL_MDMA_GenerateSWRequest.
00125 
00126     [..]  Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection.
00127 
00128      *** MDMA HAL driver macros list ***
00129      =============================================
00130      [..]
00131        Below the list of most used macros in MDMA HAL driver.
00132 
00133       (+) __HAL_MDMA_ENABLE: Enable the specified MDMA Channel.
00134       (+) __HAL_MDMA_DISABLE: Disable the specified MDMA Channel.
00135       (+) __HAL_MDMA_GET_FLAG: Get the MDMA Channel pending flags.
00136       (+) __HAL_MDMA_CLEAR_FLAG: Clear the MDMA Channel pending flags.
00137       (+) __HAL_MDMA_ENABLE_IT: Enable the specified MDMA Channel interrupts.
00138       (+) __HAL_MDMA_DISABLE_IT: Disable the specified MDMA Channel interrupts.
00139       (+) __HAL_MDMA_GET_IT_SOURCE: Check whether the specified MDMA Channel interrupt has occurred or not.
00140 
00141      [..]
00142       (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
00143 
00144     [..]
00145 
00146   @endverbatim
00147   */
00148 
00149 /* Includes ------------------------------------------------------------------*/
00150 #include "stm32h7xx_hal.h"
00151 
00152 /** @addtogroup STM32H7xx_HAL_Driver
00153   * @{
00154   */
00155 
00156 /** @defgroup MDMA  MDMA
00157   * @brief MDMA HAL module driver
00158   * @{
00159   */
00160 
00161 #ifdef HAL_MDMA_MODULE_ENABLED
00162 
00163 /* Private typedef -----------------------------------------------------------*/
00164 /* Private constants ---------------------------------------------------------*/
00165 /** @addtogroup MDMA_Private_Constants
00166  * @{
00167  */
00168 #define HAL_TIMEOUT_MDMA_ABORT    5U    /* 5 ms */
00169 #define HAL_MDMA_CHANNEL_SIZE     0x40U /* an MDMA instance channel size is 64 byte  */
00170 /**
00171   * @}
00172   */
00173 /* Private macro -------------------------------------------------------------*/
00174 /* Private variables ---------------------------------------------------------*/
00175 /* Private function prototypes -----------------------------------------------*/
00176 /** @addtogroup MDMA_Private_Functions_Prototypes
00177   * @{
00178   */
00179 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount);
00180 static void MDMA_Init(MDMA_HandleTypeDef *hmdma);
00181 
00182 /**
00183   * @}
00184   */
00185 
00186 /** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
00187   * @{
00188   */
00189 
00190 /** @addtogroup MDMA_Exported_Functions_Group1
00191   *
00192 @verbatim
00193  ===============================================================================
00194              ##### Initialization and de-initialization functions  #####
00195  ===============================================================================
00196     [..]
00197     This section provides functions allowing to :
00198       Initialize and de-initialize the MDMA channel.
00199       Register and Unregister MDMA callbacks
00200     [..]
00201     The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in
00202     reference manual.
00203     The HAL_MDMA_DeInit function allows to deinitialize the MDMA channel.
00204     HAL_MDMA_RegisterCallback and  HAL_MDMA_UnRegisterCallback functions allows
00205     respectevely to register/unregister an MDMA callback function.
00206 
00207 @endverbatim
00208   * @{
00209   */
00210 
00211 /**
00212   * @brief  Initializes the MDMA according to the specified
00213   *         parameters in the MDMA_InitTypeDef and create the associated handle.
00214   * @param  hmdma: Pointer to a MDMA_HandleTypeDef structure that contains
00215   *               the configuration information for the specified MDMA Channel.
00216   * @retval HAL status
00217   */
00218 HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
00219 {
00220   uint32_t tickstart = HAL_GetTick();
00221 
00222   /* Check the MDMA peripheral handle */
00223   if(hmdma == NULL)
00224   {
00225     return HAL_ERROR;
00226   }
00227 
00228   /* Check the parameters */
00229   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
00230   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
00231   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));
00232   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
00233   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
00234   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
00235   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
00236   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
00237   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
00238   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
00239   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
00240   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));
00241   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
00242   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
00243   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
00244 
00245 
00246   /* Allocate lock resource */
00247   __HAL_UNLOCK(hmdma);
00248 
00249   /* Change MDMA peripheral state */
00250   hmdma->State = HAL_MDMA_STATE_BUSY;
00251 
00252   /* Disable the MDMA channel */
00253   __HAL_MDMA_DISABLE(hmdma);
00254 
00255   /* Check if the MDMA channel is effectively disabled */
00256   while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
00257   {
00258     /* Check for the Timeout */
00259     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
00260     {
00261       /* Update error code */
00262       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
00263 
00264       /* Change the MDMA state */
00265       hmdma->State = HAL_MDMA_STATE_ERROR;
00266 
00267       return HAL_ERROR;
00268     }
00269   }
00270 
00271   /* Initialize the MDMA channel registers */
00272   MDMA_Init(hmdma);
00273 
00274   /* Reset the MDMA first/last linkedlist node addresses and node counter */
00275   hmdma->FirstLinkedListNodeAddress  = 0;
00276   hmdma->LastLinkedListNodeAddress   = 0;
00277   hmdma->LinkedListNodeCounter  = 0;
00278 
00279   /* Initialize the error code */
00280   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
00281 
00282   /* Initialize the MDMA state */
00283   hmdma->State = HAL_MDMA_STATE_READY;
00284 
00285   return HAL_OK;
00286 }
00287 
00288 /**
00289   * @brief  DeInitializes the MDMA peripheral
00290   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
00291   *               the configuration information for the specified MDMA Channel.
00292   * @retval HAL status
00293   */
00294 HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma)
00295 {
00296 
00297   /* Check the MDMA peripheral handle */
00298   if(hmdma == NULL)
00299   {
00300     return HAL_ERROR;
00301   }
00302 
00303   /* Disable the selected MDMA Channelx */
00304   __HAL_MDMA_DISABLE(hmdma);
00305 
00306   /* Reset MDMA Channel control register */
00307   hmdma->Instance->CCR  = 0;
00308   hmdma->Instance->CTCR = 0;
00309   hmdma->Instance->CBNDTR = 0;
00310   hmdma->Instance->CSAR = 0;
00311   hmdma->Instance->CDAR = 0;
00312   hmdma->Instance->CBRUR = 0;
00313   hmdma->Instance->CLAR = 0;
00314   hmdma->Instance->CTBR = 0;
00315   hmdma->Instance->CMAR = 0;
00316   hmdma->Instance->CMDR = 0;
00317 
00318   /* Clear all flags */
00319   __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC));
00320 
00321   /* Reset the  MDMA first/last linkedlist node addresses and node counter */
00322   hmdma->FirstLinkedListNodeAddress  = 0;
00323   hmdma->LastLinkedListNodeAddress   = 0;
00324   hmdma->LinkedListNodeCounter  = 0;
00325 
00326   /* Initialize the error code */
00327   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
00328 
00329   /* Initialize the MDMA state */
00330   hmdma->State = HAL_MDMA_STATE_RESET;
00331 
00332   /* Release Lock */
00333   __HAL_UNLOCK(hmdma);
00334 
00335   return HAL_OK;
00336 }
00337 
00338 /**
00339   * @brief  Config the Post request Mask address and Mask data
00340   * @param  hmdma      : pointer to a MDMA_HandleTypeDef structure that contains
00341   *                               the configuration information for the specified MDMA Channel.
00342   * @param  MaskAddress: specifies the address to be updated (written) with MaskData after a request is served.
00343   * @param  MaskData:    specifies the value to be written to MaskAddress after a request is served.
00344   *                      MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served.
00345   * @retval HAL status
00346   */
00347 HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData)
00348 {
00349   HAL_StatusTypeDef  status = HAL_OK;
00350 
00351   /* Check the MDMA peripheral handle */
00352   if(hmdma == NULL)
00353   {
00354     return HAL_ERROR;
00355   }
00356 
00357   /* Process locked */
00358   __HAL_LOCK(hmdma);
00359 
00360   if(HAL_MDMA_STATE_READY == hmdma->State)
00361   {
00362     /* if HW request set Post Request MaskAddress and MaskData,  */
00363     if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U)
00364     {
00365       /* Set the HW request clear Mask and Data */
00366       hmdma->Instance->CMAR = MaskAddress;
00367       hmdma->Instance->CMDR = MaskData;
00368 
00369       /*
00370       -If the request is done by SW : BWM could be set to 1 or 0.
00371       -If the request is done by a peripheral :
00372          If mask address not set (0) => BWM must be set to 0
00373          If mask address set (different than 0) => BWM could be set to 1 or 0
00374       */
00375       if(MaskAddress == 0U)
00376       {
00377         hmdma->Instance->CTCR &=  ~MDMA_CTCR_BWM;
00378       }
00379       else
00380       {
00381         hmdma->Instance->CTCR |=  MDMA_CTCR_BWM;
00382       }
00383     }
00384     else
00385     {
00386       /* Return error status */
00387       status =  HAL_ERROR;
00388     }
00389   }
00390   else
00391   {
00392     /* Return error status */
00393     status =  HAL_ERROR;
00394   }
00395   /* Release Lock */
00396   __HAL_UNLOCK(hmdma);
00397 
00398   return status;
00399 }
00400 
00401 /**
00402   * @brief  Register callbacks
00403   * @param  hmdma:                pointer to a MDMA_HandleTypeDef structure that contains
00404   *                               the configuration information for the specified MDMA Channel.
00405   * @param  CallbackID:           User Callback identifier
00406   * @param  pCallback:            pointer to callbacsk function.
00407   * @retval HAL status
00408   */
00409 HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma))
00410 {
00411   HAL_StatusTypeDef status = HAL_OK;
00412 
00413   /* Check the MDMA peripheral handle */
00414   if(hmdma == NULL)
00415   {
00416     return HAL_ERROR;
00417   }
00418 
00419   /* Process locked */
00420   __HAL_LOCK(hmdma);
00421 
00422   if(HAL_MDMA_STATE_READY == hmdma->State)
00423   {
00424     switch (CallbackID)
00425     {
00426     case  HAL_MDMA_XFER_CPLT_CB_ID:
00427       hmdma->XferCpltCallback = pCallback;
00428       break;
00429 
00430     case  HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
00431       hmdma->XferBufferCpltCallback = pCallback;
00432       break;
00433 
00434     case  HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
00435       hmdma->XferBlockCpltCallback = pCallback;
00436       break;
00437 
00438     case  HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
00439       hmdma->XferRepeatBlockCpltCallback = pCallback;
00440       break;
00441 
00442     case  HAL_MDMA_XFER_ERROR_CB_ID:
00443       hmdma->XferErrorCallback = pCallback;
00444       break;
00445 
00446     case  HAL_MDMA_XFER_ABORT_CB_ID:
00447       hmdma->XferAbortCallback = pCallback;
00448       break;
00449 
00450     default:
00451       break;
00452     }
00453   }
00454   else
00455   {
00456     /* Return error status */
00457     status =  HAL_ERROR;
00458   }
00459 
00460   /* Release Lock */
00461   __HAL_UNLOCK(hmdma);
00462 
00463   return status;
00464 }
00465 
00466 /**
00467   * @brief  UnRegister callbacks
00468   * @param  hmdma:                 pointer to a MDMA_HandleTypeDef structure that contains
00469   *                               the configuration information for the specified MDMA Channel.
00470   * @param  CallbackID:           User Callback identifier
00471   *                               a HAL_MDMA_CallbackIDTypeDef ENUM as parameter.
00472   * @retval HAL status
00473   */
00474 HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID)
00475 {
00476   HAL_StatusTypeDef status = HAL_OK;
00477 
00478   /* Check the MDMA peripheral handle */
00479   if(hmdma == NULL)
00480   {
00481     return HAL_ERROR;
00482   }
00483 
00484   /* Process locked */
00485   __HAL_LOCK(hmdma);
00486 
00487   if(HAL_MDMA_STATE_READY == hmdma->State)
00488   {
00489     switch (CallbackID)
00490     {
00491     case  HAL_MDMA_XFER_CPLT_CB_ID:
00492       hmdma->XferCpltCallback = NULL;
00493       break;
00494 
00495     case  HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
00496       hmdma->XferBufferCpltCallback = NULL;
00497       break;
00498 
00499     case  HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
00500       hmdma->XferBlockCpltCallback = NULL;
00501       break;
00502 
00503     case  HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
00504       hmdma->XferRepeatBlockCpltCallback = NULL;
00505       break;
00506 
00507     case  HAL_MDMA_XFER_ERROR_CB_ID:
00508       hmdma->XferErrorCallback = NULL;
00509       break;
00510 
00511     case  HAL_MDMA_XFER_ABORT_CB_ID:
00512       hmdma->XferAbortCallback = NULL;
00513       break;
00514 
00515     case   HAL_MDMA_XFER_ALL_CB_ID:
00516       hmdma->XferCpltCallback = NULL;
00517       hmdma->XferBufferCpltCallback = NULL;
00518       hmdma->XferBlockCpltCallback = NULL;
00519       hmdma->XferRepeatBlockCpltCallback = NULL;
00520       hmdma->XferErrorCallback = NULL;
00521       hmdma->XferAbortCallback = NULL;
00522       break;
00523 
00524     default:
00525       status = HAL_ERROR;
00526       break;
00527     }
00528   }
00529   else
00530   {
00531     status = HAL_ERROR;
00532   }
00533 
00534   /* Release Lock */
00535   __HAL_UNLOCK(hmdma);
00536 
00537   return status;
00538 }
00539 
00540 /**
00541   * @}
00542   */
00543 
00544 /** @addtogroup MDMA_Exported_Functions_Group2
00545  *
00546 @verbatim
00547  ===============================================================================
00548                       #####  Linked list operation functions  #####
00549  ===============================================================================
00550     [..]  This section provides functions allowing to:
00551       (+) Create a linked list node
00552       (+) Add a node to the MDMA linked list
00553       (+) Remove a node from the MDMA linked list
00554       (+) Enable/Disable linked list circular mode
00555 @endverbatim
00556   * @{
00557   */
00558 
00559 /**
00560   * @brief  Initializes an MDMA Link Node according to the specified
00561   *         parameters in the pMDMA_LinkedListNodeConfig .
00562   * @param  pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
00563   *         registers configurations.
00564   * @param  pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains
00565   *               the configuration information for the specified MDMA Linked List Node.
00566   * @retval HAL status
00567   */
00568 HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig)
00569 {
00570   uint32_t addressMask;
00571   uint32_t blockoffset;
00572 
00573   /* Check the MDMA peripheral state */
00574   if((pNode == NULL) || (pNodeConfig == NULL))
00575   {
00576     return HAL_ERROR;
00577   }
00578 
00579   /* Check the parameters */
00580   assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority));
00581   assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness));
00582   assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request));
00583   assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc));
00584   assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc));
00585   assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize));
00586   assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize));
00587   assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment));
00588   assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst));
00589   assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst));
00590   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength));
00591   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode));
00592   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset));
00593   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset));
00594 
00595   assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength));
00596   assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount));
00597 
00598 
00599   /* Configure next Link node Address Register to zero */
00600   pNode->CLAR =  0;
00601 
00602   /* Configure the Link Node registers*/
00603   pNode->CTBR   = 0;
00604   pNode->CMAR   = 0;
00605   pNode->CMDR   = 0;
00606   pNode->Reserved = 0;
00607 
00608   /* Write new CTCR Register value */
00609   pNode->CTCR =  pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \
00610     pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize           | \
00611       pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst            | \
00612         pNodeConfig->Init.DestBurst                                             | \
00613           ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
00614             pNodeConfig->Init.TransferTriggerMode;
00615 
00616   /* If SW request set the CTCR register to SW Request Mode*/
00617   if(pNodeConfig->Init.Request == MDMA_REQUEST_SW)
00618   {
00619     pNode->CTCR |= MDMA_CTCR_SWRM;
00620   }
00621 
00622   /*
00623   -If the request is done by SW : BWM could be set to 1 or 0.
00624   -If the request is done by a peripheral :
00625      If mask address not set (0) => BWM must be set to 0
00626      If mask address set (different than 0) => BWM could be set to 1 or 0
00627   */
00628   if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U))
00629   {
00630     pNode->CTCR |=  MDMA_CTCR_BWM;
00631   }
00632 
00633   /* Set the new CBNDTR Register value */
00634   pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC;
00635 
00636   /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
00637   if(pNodeConfig->Init.SourceBlockAddressOffset < 0)
00638   {
00639     pNode->CBNDTR |= MDMA_CBNDTR_BRSUM;
00640     /*write new CBRUR Register value : source repeat block offset */
00641     blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset);
00642     pNode->CBRUR = blockoffset & 0x0000FFFFU;
00643   }
00644   else
00645   {
00646     /*write new CBRUR Register value : source repeat block offset */
00647     pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
00648   }
00649 
00650   /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
00651   if(pNodeConfig->Init.DestBlockAddressOffset < 0)
00652   {
00653     pNode->CBNDTR |= MDMA_CBNDTR_BRDUM;
00654     /*write new CBRUR Register value : destination repeat block offset */
00655     blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset);
00656     pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
00657   }
00658   else
00659   {
00660     /*write new CBRUR Register value : destination repeat block offset */
00661     pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
00662   }
00663 
00664   /* Configure MDMA Link Node data length */
00665   pNode->CBNDTR |=  pNodeConfig->BlockDataLength;
00666 
00667   /* Configure MDMA Link Node destination address */
00668   pNode->CDAR = pNodeConfig->DstAddress;
00669 
00670   /* Configure MDMA Link Node Source address */
00671   pNode->CSAR = pNodeConfig->SrcAddress;
00672 
00673   /* if HW request set the HW request and the requet CleraMask and ClearData MaskData,  */
00674   if(pNodeConfig->Init.Request != MDMA_REQUEST_SW)
00675   {
00676     /* Set the HW request in CTBR register  */
00677     pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL;
00678     /* Set the HW request clear Mask and Data */
00679     pNode->CMAR = pNodeConfig->PostRequestMaskAddress;
00680     pNode->CMDR = pNodeConfig->PostRequestMaskData;
00681   }
00682 
00683   addressMask = pNodeConfig->SrcAddress & 0xFF000000U;
00684   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
00685   {
00686     /*The AHBSbus is used as source (read operation) on channel x */
00687     pNode->CTBR |= MDMA_CTBR_SBUS;
00688   }
00689 
00690   addressMask = pNodeConfig->DstAddress & 0xFF000000U;
00691   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
00692   {
00693     /*The AHB bus is used as destination (write operation) on channel x */
00694     pNode->CTBR |= MDMA_CTBR_DBUS;
00695   }
00696 
00697   return HAL_OK;
00698 }
00699 
00700 /**
00701   * @brief  Connect a node to the linked list.
00702   * @param  hmdma    : Pointer to a MDMA_HandleTypeDef structure that contains
00703   *                    the configuration information for the specified MDMA Channel.
00704   * @param  pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
00705   *                    to be add to the list.
00706   * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
00707   *                    at the end of the list
00708   *
00709   * @retval HAL status
00710   */
00711 HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
00712 {
00713   MDMA_LinkNodeTypeDef *pNode;
00714   uint32_t counter = 0, nodeInserted = 0;
00715   HAL_StatusTypeDef hal_status = HAL_OK;
00716 
00717   /* Check the MDMA peripheral handle */
00718   if((hmdma == NULL) || (pNewNode == NULL))
00719   {
00720     return HAL_ERROR;
00721   }
00722 
00723   /* Process locked */
00724   __HAL_LOCK(hmdma);
00725 
00726   if(HAL_MDMA_STATE_READY == hmdma->State)
00727   {
00728     /* Change MDMA peripheral state */
00729     hmdma->State = HAL_MDMA_STATE_BUSY;
00730 
00731     /* Check if this is the first node (after the Inititlization node) */
00732     if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U)
00733     {
00734       if(pPrevNode == NULL)
00735       {
00736         /* if this is the first node after the initialization
00737         connect this node to the node 0 by updating
00738         the MDMA channel CLAR register to this node address */
00739         hmdma->Instance->CLAR = (uint32_t)pNewNode;
00740         /* Set the MDMA handle First linked List node*/
00741         hmdma->FirstLinkedListNodeAddress = pNewNode;
00742 
00743         /*reset New node link */
00744         pNewNode->CLAR = 0;
00745 
00746         /* Update the Handle last node address */
00747         hmdma->LastLinkedListNodeAddress = pNewNode;
00748 
00749         hmdma->LinkedListNodeCounter = 1;
00750       }
00751       else
00752       {
00753         hal_status = HAL_ERROR;
00754       }
00755     }
00756     else if(hmdma->FirstLinkedListNodeAddress != pNewNode)
00757     {
00758       /* Check if the node to insert already exists*/
00759       pNode = hmdma->FirstLinkedListNodeAddress;
00760       while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
00761       {
00762         if(pNode->CLAR == (uint32_t)pNewNode)
00763         {
00764           hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
00765         }
00766         pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
00767         counter++;
00768       }
00769 
00770       if(hal_status == HAL_OK)
00771       {
00772         /* Check if the previous node is the last one in the current list or zero */
00773         if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL))
00774         {
00775           /* insert the new node at the end of the list */
00776           pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;
00777           hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
00778           /* Update the Handle last node address */
00779           hmdma->LastLinkedListNodeAddress = pNewNode;
00780           /* Increment the linked list node counter */
00781           hmdma->LinkedListNodeCounter++;
00782         }
00783         else
00784         {
00785           /*insert the new node after the pPreviousNode node */
00786           pNode = hmdma->FirstLinkedListNodeAddress;
00787           counter = 0;
00788           while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U))
00789           {
00790             counter++;
00791             if(pNode == pPrevNode)
00792             {
00793               /*Insert the new node after the previous one */
00794               pNewNode->CLAR = pNode->CLAR;
00795               pNode->CLAR = (uint32_t)pNewNode;
00796               /* Increment the linked list node counter */
00797               hmdma->LinkedListNodeCounter++;
00798               nodeInserted = 1;
00799             }
00800             else
00801             {
00802               pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
00803             }
00804           }
00805 
00806           if(nodeInserted == 0U)
00807           {
00808             hal_status = HAL_ERROR;
00809           }
00810         }
00811       }
00812     }
00813     else
00814     {
00815       hal_status = HAL_ERROR;
00816     }
00817 
00818     /* Process unlocked */
00819     __HAL_UNLOCK(hmdma);
00820 
00821     hmdma->State = HAL_MDMA_STATE_READY;
00822 
00823     return hal_status;
00824   }
00825   else
00826   {
00827     /* Process unlocked */
00828     __HAL_UNLOCK(hmdma);
00829 
00830     /* Return error status */
00831     return HAL_BUSY;
00832   }
00833 }
00834 
00835 /**
00836   * @brief  Disconnect/Remove a node from the transfer linked list.
00837   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
00838   *                 the configuration information for the specified MDMA Channel.
00839   * @param  pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
00840   *                 to be removed from the list.
00841   *
00842   * @retval HAL status
00843   */
00844 HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode)
00845 {
00846   MDMA_LinkNodeTypeDef *ptmpNode;
00847   uint32_t counter = 0, nodeDeleted = 0;
00848   HAL_StatusTypeDef hal_status = HAL_OK;
00849 
00850   /* Check the MDMA peripheral handle */
00851   if((hmdma == NULL) || (pNode == NULL))
00852   {
00853     return HAL_ERROR;
00854   }
00855 
00856   /* Process locked */
00857   __HAL_LOCK(hmdma);
00858 
00859   if(HAL_MDMA_STATE_READY == hmdma->State)
00860   {
00861     /* Change MDMA peripheral state */
00862     hmdma->State = HAL_MDMA_STATE_BUSY;
00863 
00864     /* If first and last node are null (no nodes in the list) : return error*/
00865     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
00866     {
00867       hal_status = HAL_ERROR;
00868     }
00869     else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */
00870     {
00871       /* Delete 1st node */
00872       if(hmdma->LastLinkedListNodeAddress == pNode)
00873       {
00874         /*if the last node is at the same time the first one (1 single node after the init node 0)
00875         then update the last node too */
00876 
00877         hmdma->FirstLinkedListNodeAddress = 0;
00878         hmdma->LastLinkedListNodeAddress  = 0;
00879         hmdma->LinkedListNodeCounter = 0;
00880 
00881         hmdma->Instance->CLAR = 0;
00882       }
00883       else
00884       {
00885         if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR)
00886         {
00887           /* if last node is looping to first (circular list) one update the last node connection */
00888           hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR;
00889         }
00890 
00891         /* if deleting the first node after the initialization
00892         connect the next node to the node 0 by updating
00893         the MDMA channel CLAR register to this node address */
00894         hmdma->Instance->CLAR = pNode->CLAR;
00895         hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR;
00896         /* Update the Handle node counter */
00897         hmdma->LinkedListNodeCounter--;
00898       }
00899     }
00900     else /* Deleting any other node */
00901     {
00902       /*Deleted node is not the first one : find it  */
00903       ptmpNode = hmdma->FirstLinkedListNodeAddress;
00904       while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U))
00905       {
00906         counter++;
00907         if(ptmpNode->CLAR == ((uint32_t)pNode))
00908         {
00909           /* if deleting the last node */
00910           if(pNode == hmdma->LastLinkedListNodeAddress)
00911           {
00912             /*Update the linked list last node address in the handle*/
00913             hmdma->LastLinkedListNodeAddress = ptmpNode;
00914           }
00915           /* update the next node link after deleting pMDMA_LinkedListNode */
00916           ptmpNode->CLAR = pNode->CLAR;
00917           nodeDeleted = 1;
00918           /* Update the Handle node counter */
00919           hmdma->LinkedListNodeCounter--;
00920         }
00921         else
00922         {
00923           ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR;
00924         }
00925       }
00926 
00927       if(nodeDeleted == 0U)
00928       {
00929         /* last node reashed without finding the node to delete : return error */
00930         hal_status = HAL_ERROR;
00931       }
00932     }
00933 
00934     /* Process unlocked */
00935     __HAL_UNLOCK(hmdma);
00936 
00937     hmdma->State = HAL_MDMA_STATE_READY;
00938 
00939     return hal_status;
00940   }
00941   else
00942   {
00943     /* Process unlocked */
00944     __HAL_UNLOCK(hmdma);
00945 
00946     /* Return error status */
00947     return HAL_BUSY;
00948   }
00949 }
00950 
00951 /**
00952   * @brief  Make the linked list circular by connecting the last node to the first.
00953   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
00954   *                 the configuration information for the specified MDMA Channel.
00955   * @retval HAL status
00956   */
00957 HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
00958 {
00959   HAL_StatusTypeDef hal_status = HAL_OK;
00960 
00961   /* Check the MDMA peripheral handle */
00962   if(hmdma == NULL)
00963   {
00964     return HAL_ERROR;
00965   }
00966 
00967   /* Process locked */
00968   __HAL_LOCK(hmdma);
00969 
00970   if(HAL_MDMA_STATE_READY == hmdma->State)
00971   {
00972     /* Change MDMA peripheral state */
00973     hmdma->State = HAL_MDMA_STATE_BUSY;
00974 
00975     /* If first and last node are null (no nodes in the list) : return error*/
00976     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
00977     {
00978       hal_status = HAL_ERROR;
00979     }
00980     else
00981     {
00982       /* to enable circular mode Last Node should be connected to first node */
00983       hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
00984     }
00985 
00986   }
00987   /* Process unlocked */
00988   __HAL_UNLOCK(hmdma);
00989 
00990   hmdma->State = HAL_MDMA_STATE_READY;
00991 
00992   return hal_status;
00993 }
00994 
00995 /**
00996   * @brief  Disable the linked list circular mode by setting the last node connection to null
00997   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
00998   *                 the configuration information for the specified MDMA Channel.
00999   * @retval HAL status
01000   */
01001 HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma)
01002 {
01003   HAL_StatusTypeDef hal_status = HAL_OK;
01004 
01005   /* Check the MDMA peripheral handle */
01006   if(hmdma == NULL)
01007   {
01008     return HAL_ERROR;
01009   }
01010 
01011   /* Process locked */
01012   __HAL_LOCK(hmdma);
01013 
01014   if(HAL_MDMA_STATE_READY == hmdma->State)
01015   {
01016     /* Change MDMA peripheral state */
01017     hmdma->State = HAL_MDMA_STATE_BUSY;
01018 
01019     /* If first and last node are null (no nodes in the list) : return error*/
01020     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
01021     {
01022       hal_status = HAL_ERROR;
01023     }
01024     else
01025     {
01026       /* to disable circular mode Last Node should be connected to NULL */
01027       hmdma->LastLinkedListNodeAddress->CLAR = 0;
01028     }
01029 
01030   }
01031   /* Process unlocked */
01032   __HAL_UNLOCK(hmdma);
01033 
01034   hmdma->State = HAL_MDMA_STATE_READY;
01035 
01036   return hal_status;
01037 }
01038 
01039 /**
01040   * @}
01041   */
01042 
01043 /** @addtogroup MDMA_Exported_Functions_Group3
01044  *
01045 @verbatim
01046  ===============================================================================
01047                       #####  IO operation functions  #####
01048  ===============================================================================
01049     [..]  This section provides functions allowing to:
01050       (+) Configure the source, destination address and data length and Start MDMA transfer
01051       (+) Configure the source, destination address and data length and
01052           Start MDMA transfer with interrupt
01053       (+) Abort MDMA transfer
01054       (+) Poll for transfer complete
01055       (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW)
01056       (+) Handle MDMA interrupt request
01057 
01058 @endverbatim
01059   * @{
01060   */
01061 
01062 /**
01063   * @brief  Starts the MDMA Transfer.
01064   * @param  hmdma           : pointer to a MDMA_HandleTypeDef structure that contains
01065   *                           the configuration information for the specified MDMA Channel.
01066   * @param  SrcAddress      : The source memory Buffer address
01067   * @param  DstAddress      : The destination memory Buffer address
01068   * @param  BlockDataLength : The length of a block transfer in bytes
01069   * @param  BlockCount      : The number of a blocks to be transfer
01070   * @retval HAL status
01071   */
01072 HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
01073 {
01074   /* Check the parameters */
01075   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
01076   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
01077 
01078   /* Check the MDMA peripheral handle */
01079   if(hmdma == NULL)
01080   {
01081     return HAL_ERROR;
01082   }
01083 
01084   /* Process locked */
01085   __HAL_LOCK(hmdma);
01086 
01087   if(HAL_MDMA_STATE_READY == hmdma->State)
01088   {
01089     /* Change MDMA peripheral state */
01090     hmdma->State = HAL_MDMA_STATE_BUSY;
01091 
01092     /* Initialize the error code */
01093     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
01094 
01095     /* Disable the peripheral */
01096     __HAL_MDMA_DISABLE(hmdma);
01097 
01098     /* Configure the source, destination address and the data length */
01099     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
01100 
01101     /* Enable the Peripheral */
01102     __HAL_MDMA_ENABLE(hmdma);
01103 
01104     if(hmdma->Init.Request == MDMA_REQUEST_SW)
01105     {
01106       /* activate If SW request mode*/
01107       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
01108     }
01109   }
01110   else
01111   {
01112     /* Process unlocked */
01113     __HAL_UNLOCK(hmdma);
01114 
01115     /* Return error status */
01116     return HAL_BUSY;
01117   }
01118 
01119   return HAL_OK;
01120 }
01121 
01122 /**
01123   * @brief  Starts the MDMA Transfer with interrupts enabled.
01124   * @param  hmdma           : pointer to a MDMA_HandleTypeDef structure that contains
01125   *                           the configuration information for the specified MDMA Channel.
01126   * @param  SrcAddress      : The source memory Buffer address
01127   * @param  DstAddress      : The destination memory Buffer address
01128   * @param  BlockDataLength : The length of a block transfer in bytes
01129   * @param  BlockCount      : The number of a blocks to be transfer
01130   * @retval HAL status
01131   */
01132 HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
01133 {
01134   /* Check the parameters */
01135   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
01136   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
01137 
01138   /* Check the MDMA peripheral handle */
01139   if(hmdma == NULL)
01140   {
01141     return HAL_ERROR;
01142   }
01143 
01144   /* Process locked */
01145   __HAL_LOCK(hmdma);
01146 
01147   if(HAL_MDMA_STATE_READY == hmdma->State)
01148   {
01149     /* Change MDMA peripheral state */
01150     hmdma->State = HAL_MDMA_STATE_BUSY;
01151 
01152     /* Initialize the error code */
01153     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
01154 
01155     /* Disable the peripheral */
01156     __HAL_MDMA_DISABLE(hmdma);
01157 
01158     /* Configure the source, destination address and the data length */
01159     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
01160 
01161     /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/
01162     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
01163 
01164     if(hmdma->XferBlockCpltCallback != NULL)
01165     {
01166       /* if Block transfer complete Callback is set enable the corresponding IT*/
01167       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
01168     }
01169 
01170     if(hmdma->XferRepeatBlockCpltCallback != NULL)
01171     {
01172       /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/
01173       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
01174     }
01175 
01176     if(hmdma->XferBufferCpltCallback != NULL)
01177     {
01178       /* if buffer transfer complete Callback is set enable the corresponding IT*/
01179       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);
01180     }
01181 
01182     /* Enable the Peripheral */
01183     __HAL_MDMA_ENABLE(hmdma);
01184 
01185     if(hmdma->Init.Request == MDMA_REQUEST_SW)
01186     {
01187       /* activate If SW request mode*/
01188       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
01189     }
01190   }
01191   else
01192   {
01193     /* Process unlocked */
01194     __HAL_UNLOCK(hmdma);
01195 
01196     /* Return error status */
01197     return HAL_BUSY;
01198   }
01199 
01200   return HAL_OK;
01201 }
01202 
01203 /**
01204   * @brief  Aborts the MDMA Transfer.
01205   * @param  hmdma  : pointer to a MDMA_HandleTypeDef structure that contains
01206   *                 the configuration information for the specified MDMA Channel.
01207   *
01208   * @note  After disabling a MDMA Channel, a check for wait until the MDMA Channel is
01209   *        effectively disabled is added. If a Channel is disabled
01210   *        while a data transfer is ongoing, the current data will be transferred
01211   *        and the Channel will be effectively disabled only after the transfer of
01212   *        this single data is finished.
01213   * @retval HAL status
01214   */
01215 HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma)
01216 {
01217   uint32_t tickstart =  HAL_GetTick();
01218 
01219   /* Check the MDMA peripheral handle */
01220   if(hmdma == NULL)
01221   {
01222     return HAL_ERROR;
01223   }
01224 
01225   if(HAL_MDMA_STATE_BUSY != hmdma->State)
01226   {
01227     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
01228 
01229     /* Process Unlocked */
01230     __HAL_UNLOCK(hmdma);
01231 
01232     return HAL_ERROR;
01233   }
01234   else
01235   {
01236     /* Disable all the transfer interrupts */
01237     __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
01238 
01239     /* Disable the channel */
01240     __HAL_MDMA_DISABLE(hmdma);
01241 
01242     /* Check if the MDMA Channel is effectively disabled */
01243     while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
01244     {
01245       /* Check for the Timeout */
01246       if( (HAL_GetTick()  - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
01247       {
01248         /* Update error code */
01249         hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
01250 
01251         /* Process Unlocked */
01252         __HAL_UNLOCK(hmdma);
01253 
01254         /* Change the MDMA state */
01255         hmdma->State = HAL_MDMA_STATE_ERROR;
01256 
01257         return HAL_ERROR;
01258       }
01259     }
01260 
01261     /* Clear all interrupt flags */
01262     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC));
01263 
01264     /* Process Unlocked */
01265     __HAL_UNLOCK(hmdma);
01266 
01267     /* Change the MDMA state*/
01268     hmdma->State = HAL_MDMA_STATE_READY;
01269   }
01270 
01271   return HAL_OK;
01272 }
01273 
01274 /**
01275   * @brief  Aborts the MDMA Transfer in Interrupt mode.
01276   * @param  hmdma  : pointer to a MDMA_HandleTypeDef structure that contains
01277   *                 the configuration information for the specified MDMA Channel.
01278   * @retval HAL status
01279   */
01280 HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma)
01281 {
01282   /* Check the MDMA peripheral handle */
01283   if(hmdma == NULL)
01284   {
01285     return HAL_ERROR;
01286   }
01287 
01288   if(HAL_MDMA_STATE_BUSY != hmdma->State)
01289   {
01290     /* No transfer ongoing */
01291     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
01292 
01293     return HAL_ERROR;
01294   }
01295   else
01296   {
01297     /* Set Abort State  */
01298     hmdma->State = HAL_MDMA_STATE_ABORT;
01299 
01300     /* Disable the stream */
01301     __HAL_MDMA_DISABLE(hmdma);
01302   }
01303 
01304   return HAL_OK;
01305 }
01306 
01307 /**
01308   * @brief  Polling for transfer complete.
01309   * @param  hmdma:          pointer to a MDMA_HandleTypeDef structure that contains
01310   *                        the configuration information for the specified MDMA Channel.
01311   * @param  CompleteLevel: Specifies the MDMA level complete.
01312   * @param  Timeout:       Timeout duration.
01313   * @retval HAL status
01314   */
01315 HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
01316 {
01317   uint32_t levelFlag, errorFlag;
01318   uint32_t tickstart;
01319 
01320   /* Check the parameters */
01321   assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel));
01322 
01323   /* Check the MDMA peripheral handle */
01324   if(hmdma == NULL)
01325   {
01326     return HAL_ERROR;
01327   }
01328 
01329   if(HAL_MDMA_STATE_BUSY != hmdma->State)
01330   {
01331     /* No transfer ongoing */
01332     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
01333 
01334     return HAL_ERROR;
01335   }
01336 
01337   /* Get the level transfer complete flag */
01338   levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER)  ? MDMA_FLAG_CTC  : \
01339                (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \
01340                (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT   : \
01341                MDMA_FLAG_BRT);
01342 
01343 
01344   /* Get timeout */
01345   tickstart = HAL_GetTick();
01346 
01347   while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U)
01348   {
01349     if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
01350     {
01351       /* Get the transfer error source flag */
01352       errorFlag = hmdma->Instance->CESR;
01353 
01354       if((errorFlag & MDMA_CESR_TED) == 0U)
01355       {
01356         /* Update error code : Read Transfer error  */
01357         hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
01358       }
01359       else
01360       {
01361         /* Update error code : Write Transfer error */
01362         hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
01363       }
01364 
01365       if((errorFlag & MDMA_CESR_TEMD) != 0U)
01366       {
01367         /* Update error code : Error Mask Data */
01368         hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
01369       }
01370 
01371       if((errorFlag & MDMA_CESR_TELD) != 0U)
01372       {
01373         /* Update error code : Error Linked list */
01374         hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
01375       }
01376 
01377       if((errorFlag & MDMA_CESR_ASE) != 0U)
01378       {
01379         /* Update error code : Address/Size alignment error */
01380         hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
01381       }
01382 
01383       if((errorFlag & MDMA_CESR_BSE) != 0U)
01384       {
01385         /* Update error code : Block Size error */
01386         hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
01387       }
01388 
01389       (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */
01390 
01391       /*
01392         Note that the Abort function will
01393           - Clear all transfer flags
01394           - Unlock
01395           - Set the State
01396       */
01397 
01398       return HAL_ERROR;
01399 
01400     }
01401 
01402     /* Check for the Timeout */
01403     if(Timeout != HAL_MAX_DELAY)
01404     {
01405       if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
01406       {
01407         /* Update error code */
01408         hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
01409 
01410         (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */
01411 
01412         /*
01413           Note that the Abort function will
01414             - Clear all transfer flags
01415             - Unlock
01416             - Set the State
01417         */
01418 
01419         return HAL_ERROR;
01420       }
01421     }
01422   }
01423 
01424   /* Clear the transfer level flag */
01425   if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)
01426   {
01427     __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
01428 
01429   }
01430   else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER)
01431   {
01432     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT));
01433 
01434   }
01435   else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER)
01436   {
01437     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT));
01438   }
01439   else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER)
01440   {
01441     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC));
01442 
01443     /* Process unlocked */
01444     __HAL_UNLOCK(hmdma);
01445 
01446     hmdma->State = HAL_MDMA_STATE_READY;
01447   }
01448   else
01449   {
01450     return HAL_ERROR;
01451   }
01452 
01453   return HAL_OK;
01454 }
01455 
01456 /**
01457   * @brief  Generate an MDMA SW request trigger to activate the request on the given Channel.
01458   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
01459   *                     the configuration information for the specified MDMA Stream.
01460   * @retval HAL status
01461   */
01462 HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma)
01463 {
01464   uint32_t request_mode;
01465 
01466   /* Check the MDMA peripheral handle */
01467   if(hmdma == NULL)
01468   {
01469     return HAL_ERROR;
01470   }
01471 
01472   /* Get the softawre request mode */
01473   request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM;
01474 
01475   if((hmdma->Instance->CCR &  MDMA_CCR_EN) == 0U)
01476   {
01477     /* if no Transfer on going (MDMA enable bit not set) return error */
01478     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
01479 
01480     return HAL_ERROR;
01481   }
01482   else if(((hmdma->Instance->CISR &  MDMA_CISR_CRQA) != 0U) || (request_mode == 0U))
01483   {
01484     /* if an MDMA ongoing request has not yet end or if request mode is not SW request return error */
01485     hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY;
01486 
01487     return HAL_ERROR;
01488   }
01489   else
01490   {
01491     /* Set the SW request bit to activate the request on the Channel */
01492     hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
01493 
01494     return HAL_OK;
01495   }
01496 }
01497 
01498 /**
01499   * @brief  Handles MDMA interrupt request.
01500   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
01501   *               the configuration information for the specified MDMA Channel.
01502   * @retval None
01503   */
01504 void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma)
01505 {
01506   __IO uint32_t count = 0;
01507   uint32_t timeout = SystemCoreClock / 9600U;
01508 
01509   uint32_t generalIntFlag, errorFlag;
01510 
01511   /* General Interrupt Flag management ****************************************/
01512   generalIntFlag =  1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU);
01513   if((MDMA->GISR0 & generalIntFlag) == 0U)
01514   {
01515     return; /* the  General interrupt flag for the current channel is down , nothing to do */
01516   }
01517 
01518   /* Transfer Error Interrupt management ***************************************/
01519   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
01520   {
01521     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U)
01522     {
01523       /* Disable the transfer error interrupt */
01524       __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE);
01525 
01526       /* Get the transfer error source flag */
01527       errorFlag = hmdma->Instance->CESR;
01528 
01529       if((errorFlag & MDMA_CESR_TED) == 0U)
01530       {
01531         /* Update error code : Read Transfer error  */
01532         hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
01533       }
01534       else
01535       {
01536         /* Update error code : Write Transfer error */
01537         hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
01538       }
01539 
01540       if((errorFlag & MDMA_CESR_TEMD) != 0U)
01541       {
01542         /* Update error code : Error Mask Data */
01543         hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
01544       }
01545 
01546       if((errorFlag & MDMA_CESR_TELD) != 0U)
01547       {
01548         /* Update error code : Error Linked list */
01549         hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
01550       }
01551 
01552       if((errorFlag & MDMA_CESR_ASE) != 0U)
01553       {
01554         /* Update error code : Address/Size alignment error */
01555         hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
01556       }
01557 
01558       if((errorFlag & MDMA_CESR_BSE) != 0U)
01559       {
01560         /* Update error code : Block Size error error */
01561         hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
01562       }
01563 
01564       /* Clear the transfer error flags */
01565       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE);
01566     }
01567   }
01568 
01569   /* Buffer Transfer Complete Interrupt management ******************************/
01570   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U))
01571   {
01572     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U)
01573     {
01574       /* Clear the buffer transfer complete flag */
01575       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
01576 
01577       if(hmdma->XferBufferCpltCallback != NULL)
01578       {
01579         /* Buffer transfer callback */
01580         hmdma->XferBufferCpltCallback(hmdma);
01581       }
01582     }
01583   }
01584 
01585   /* Block Transfer Complete Interrupt management ******************************/
01586   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U))
01587   {
01588     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U)
01589     {
01590       /* Clear the block transfer complete flag */
01591       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT);
01592 
01593       if(hmdma->XferBlockCpltCallback != NULL)
01594       {
01595         /* Block transfer callback */
01596         hmdma->XferBlockCpltCallback(hmdma);
01597       }
01598     }
01599   }
01600 
01601   /* Repeated Block Transfer Complete Interrupt management ******************************/
01602   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U))
01603   {
01604     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U)
01605     {
01606       /* Clear the repeat block transfer complete flag */
01607       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT);
01608 
01609       if(hmdma->XferRepeatBlockCpltCallback != NULL)
01610       {
01611         /* Repeated Block transfer callback */
01612         hmdma->XferRepeatBlockCpltCallback(hmdma);
01613       }
01614     }
01615   }
01616 
01617   /* Channel Transfer Complete Interrupt management ***********************************/
01618   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U))
01619   {
01620     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U)
01621     {
01622       /* Disable all the transfer interrupts */
01623       __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
01624 
01625       if(HAL_MDMA_STATE_ABORT == hmdma->State)
01626       {
01627         /* Process Unlocked */
01628         __HAL_UNLOCK(hmdma);
01629 
01630         /* Change the DMA state */
01631         hmdma->State = HAL_MDMA_STATE_READY;
01632 
01633         if(hmdma->XferAbortCallback != NULL)
01634         {
01635           hmdma->XferAbortCallback(hmdma);
01636         }
01637         return;
01638       }
01639 
01640       /* Clear the Channel Transfer Complete flag */
01641       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC);
01642 
01643       /* Process Unlocked */
01644       __HAL_UNLOCK(hmdma);
01645 
01646       /* Change MDMA peripheral state */
01647       hmdma->State = HAL_MDMA_STATE_READY;
01648 
01649       if(hmdma->XferCpltCallback != NULL)
01650       {
01651         /* Channel Transfer Complete callback */
01652         hmdma->XferCpltCallback(hmdma);
01653       }
01654     }
01655   }
01656 
01657   /* manage error case */
01658   if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE)
01659   {
01660     hmdma->State = HAL_MDMA_STATE_ABORT;
01661 
01662     /* Disable the channel */
01663     __HAL_MDMA_DISABLE(hmdma);
01664 
01665     do
01666     {
01667       if (++count > timeout)
01668       {
01669         break;
01670       }
01671     }
01672     while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U);
01673 
01674     /* Process Unlocked */
01675     __HAL_UNLOCK(hmdma);
01676 
01677     if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
01678     {
01679       /* Change the MDMA state to error if MDMA disable fails */
01680       hmdma->State = HAL_MDMA_STATE_ERROR;
01681     }
01682     else
01683     {
01684       /* Change the MDMA state to Ready if MDMA disable success */
01685       hmdma->State = HAL_MDMA_STATE_READY;
01686     }
01687 
01688 
01689     if (hmdma->XferErrorCallback != NULL)
01690     {
01691       /* Transfer error callback */
01692       hmdma->XferErrorCallback(hmdma);
01693     }
01694   }
01695 }
01696 
01697 /**
01698   * @}
01699   */
01700 
01701 /** @addtogroup MDMA_Exported_Functions_Group4
01702  *
01703 @verbatim
01704  ===============================================================================
01705                     ##### State and Errors functions #####
01706  ===============================================================================
01707     [..]
01708     This subsection provides functions allowing to
01709       (+) Check the MDMA state
01710       (+) Get error code
01711 
01712 @endverbatim
01713   * @{
01714   */
01715 
01716 /**
01717   * @brief  Returns the MDMA state.
01718   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
01719   *               the configuration information for the specified MDMA Channel.
01720   * @retval HAL state
01721   */
01722 HAL_MDMA_StateTypeDef HAL_MDMA_GetState(MDMA_HandleTypeDef *hmdma)
01723 {
01724   return hmdma->State;
01725 }
01726 
01727 /**
01728   * @brief  Return the MDMA error code
01729   * @param  hmdma : pointer to a MDMA_HandleTypeDef structure that contains
01730   *              the configuration information for the specified MDMA Channel.
01731   * @retval MDMA Error Code
01732   */
01733 uint32_t HAL_MDMA_GetError(MDMA_HandleTypeDef *hmdma)
01734 {
01735   return hmdma->ErrorCode;
01736 }
01737 
01738 /**
01739   * @}
01740   */
01741 
01742 /**
01743   * @}
01744   */
01745 
01746 /** @addtogroup MDMA_Private_Functions
01747   * @{
01748   */
01749 
01750 /**
01751   * @brief  Sets the MDMA Transfer parameter.
01752   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
01753   *                     the configuration information for the specified MDMA Channel.
01754   * @param  SrcAddress: The source memory Buffer address
01755   * @param  DstAddress: The destination memory Buffer address
01756   * @param  BlockDataLength : The length of a block transfer in bytes
01757   * @param  BlockCount: The number of blocks to be transferred
01758   * @retval HAL status
01759   */
01760 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
01761 {
01762   uint32_t addressMask;
01763 
01764   /* Configure the MDMA Channel data length */
01765   MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT));
01766 
01767   /* Configure the MDMA block repeat count */
01768   MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC);
01769 
01770   /* Clear all interrupt flags */
01771   __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF);
01772 
01773   /* Configure MDMA Channel destination address */
01774   hmdma->Instance->CDAR = DstAddress;
01775 
01776   /* Configure MDMA Channel Source address */
01777   hmdma->Instance->CSAR = SrcAddress;
01778 
01779   addressMask = SrcAddress & 0xFF000000U;
01780   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
01781   {
01782     /*The AHBSbus is used as source (read operation) on channel x */
01783     hmdma->Instance->CTBR |= MDMA_CTBR_SBUS;
01784   }
01785   else
01786   {
01787     /*The AXI bus is used as source (read operation) on channel x */
01788     hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS);
01789   }
01790 
01791   addressMask = DstAddress & 0xFF000000U;
01792   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
01793   {
01794     /*The AHB bus is used as destination (write operation) on channel x */
01795     hmdma->Instance->CTBR |= MDMA_CTBR_DBUS;
01796   }
01797   else
01798   {
01799     /*The AXI bus is used as destination (write operation) on channel x */
01800     hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS);
01801   }
01802 
01803   /* Set the linked list register to the first node of the list */
01804   hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
01805 }
01806 
01807 /**
01808   * @brief  Initializes the MDMA handle according to the specified
01809   *         parameters in the MDMA_InitTypeDef
01810   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
01811   *                     the configuration information for the specified MDMA Channel.
01812   * @retval None
01813   */
01814 static void MDMA_Init(MDMA_HandleTypeDef *hmdma)
01815 {
01816   uint32_t blockoffset;
01817 
01818   /* Prepare the MDMA Channel configuration */
01819   hmdma->Instance->CCR = hmdma->Init.Priority  | hmdma->Init.Endianness;
01820 
01821   /* Write new CTCR Register value */
01822   hmdma->Instance->CTCR =  hmdma->Init.SourceInc      | hmdma->Init.DestinationInc | \
01823                            hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize   | \
01824                            hmdma->Init.DataAlignment  | hmdma->Init.SourceBurst    | \
01825                            hmdma->Init.DestBurst                                   | \
01826                            ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
01827                            hmdma->Init.TransferTriggerMode;
01828 
01829   /* If SW request set the CTCR register to SW Request Mode */
01830   if(hmdma->Init.Request == MDMA_REQUEST_SW)
01831   {
01832     /*
01833     -If the request is done by SW : BWM could be set to 1 or 0.
01834     -If the request is done by a peripheral :
01835     If mask address not set (0) => BWM must be set to 0
01836     If mask address set (different than 0) => BWM could be set to 1 or 0
01837     */
01838     hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM);
01839   }
01840 
01841   /* Reset CBNDTR Register */
01842   hmdma->Instance->CBNDTR = 0;
01843 
01844   /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
01845   if(hmdma->Init.SourceBlockAddressOffset < 0)
01846   {
01847     hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM;
01848     /* Write new CBRUR Register value : source repeat block offset */
01849     blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset);
01850     hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU);
01851   }
01852   else
01853   {
01854     /* Write new CBRUR Register value : source repeat block offset */
01855     hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
01856   }
01857 
01858   /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
01859   if(hmdma->Init.DestBlockAddressOffset < 0)
01860   {
01861     hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM;
01862     /* Write new CBRUR Register value : destination repeat block offset */
01863     blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset);
01864     hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
01865   }
01866   else
01867   {
01868     /*write new CBRUR Register value : destination repeat block offset */
01869     hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
01870   }
01871 
01872   /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
01873   if(hmdma->Init.Request != MDMA_REQUEST_SW)
01874   {
01875     /* Set the HW request in CTRB register  */
01876     hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL;
01877   }
01878   else /* SW request : reset the CTBR register */
01879   {
01880     hmdma->Instance->CTBR = 0;
01881   }
01882 
01883   /* Write Link Address Register */
01884   hmdma->Instance->CLAR =  0;
01885 }
01886 
01887 /**
01888   * @}
01889   */
01890 
01891 #endif /* HAL_MDMA_MODULE_ENABLED */
01892 /**
01893   * @}
01894   */
01895 
01896 /**
01897   * @}
01898   */
01899