Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:08

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_hal_mdma.c
0004   * @author  MCD Application Team
0005   * @brief  This file provides firmware functions to manage the following
0006   *         functionalities of the Master Direct Memory Access (MDMA) peripheral:
0007   *           + Initialization/de-initialization functions
0008   *           + I/O operation functions
0009   *           + Peripheral State and errors functions
0010   ******************************************************************************
0011   * @attention
0012   *
0013   * Copyright (c) 2017 STMicroelectronics.
0014   * All rights reserved.
0015   *
0016   * This software is licensed under terms that can be found in the LICENSE file
0017   * in the root directory of this software component.
0018   * If no LICENSE file comes with this software, it is provided AS-IS.
0019   *
0020   ******************************************************************************
0021   @verbatim
0022   ==============================================================================
0023                         ##### How to use this driver #####
0024   ==============================================================================
0025   [..]
0026    (#) Enable and configure the peripheral to be connected to the MDMA Channel
0027        (except for internal SRAM/FLASH memories: no initialization is
0028        necessary) please refer to Reference manual for connection between peripherals
0029        and MDMA requests.
0030 
0031    (#)
0032        For a given Channel use HAL_MDMA_Init function to program the required configuration through the following parameters:
0033        transfer request , channel priority, data endianness, Source increment, destination increment ,
0034        source data size, destination data size, data alignment, source Burst, destination Burst ,
0035        buffer Transfer Length, Transfer Trigger Mode (buffer transfer, block transfer, repeated block transfer
0036        or full transfer) source and destination block address offset, mask address and data.
0037 
0038        If using the MDMA in linked list mode then use function HAL_MDMA_LinkedList_CreateNode to fill a transfer node.
0039        Note that parameters given to the function HAL_MDMA_Init corresponds always to the node zero.
0040        Use function HAL_MDMA_LinkedList_AddNode to connect the created node to the linked list at a given position.
0041        User can make a linked list circular using function HAL_MDMA_LinkedList_EnableCircularMode , this function will automatically connect the
0042        last node of the list to the first one in order to make the list circular.
0043        In this case the linked list will loop on node 1 : first node connected after the initial transfer defined by the HAL_MDMA_Init
0044 
0045       -@-   The initial transfer itself (node 0 corresponding to the Init).
0046             User can disable the circular mode using function HAL_MDMA_LinkedList_DisableCircularMode, this function will then remove
0047             the connection between last node and first one.
0048 
0049        Function HAL_MDMA_LinkedList_RemoveNode can be used to remove (disconnect) a node from the transfer linked list.
0050        When a linked list is circular (last node connected to first one), if removing node1  (node where the linked list loops),
0051        the linked list remains circular and node 2 becomes the first one.
0052        Note that if the linked list is made circular the transfer will loop infinitely (or until aborted by the user).
0053 
0054     [..]
0055        (+) User can select the transfer trigger mode (parameter TransferTriggerMode) to define the amount of data to be
0056            transfer upon a request :
0057              (++) MDMA_BUFFER_TRANSFER : each request triggers a transfer of BufferTransferLength data
0058                with BufferTransferLength defined within the HAL_MDMA_Init.
0059              (++) MDMA_BLOCK_TRANSFER : each request triggers a transfer of a block
0060                with block size defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
0061                or within the current linked list node parameters.
0062              (++) MDMA_REPEAT_BLOCK_TRANSFER : each request triggers a transfer of a number of blocks
0063                with block size and number of blocks defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
0064                or within the current linked list node parameters.
0065              (++) MDMA_FULL_TRANSFER : each request triggers a full transfer
0066               all blocks and all nodes(if a linked list has been created using HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode).
0067 
0068      *** Polling mode IO operation ***
0069      =================================
0070     [..]
0071           (+) Use HAL_MDMA_Start() to start MDMA transfer after the configuration of Source
0072               address and destination address and the Length of data to be transferred.
0073           (+) Use HAL_MDMA_PollForTransfer() to poll for the end of current transfer or a transfer level
0074              In this case a fixed Timeout can be configured by User depending from his application.
0075           (+) Use HAL_MDMA_Abort() function to abort the current transfer : blocking method this API returns
0076               when the abort ends or timeout (should not be called from an interrupt service routine).
0077 
0078      *** Interrupt mode IO operation ***
0079      ===================================
0080     [..]
0081           (+) Configure the MDMA interrupt priority using HAL_NVIC_SetPriority()
0082           (+) Enable the MDMA IRQ handler using HAL_NVIC_EnableIRQ()
0083           (+) Use HAL_MDMA_Start_IT() to start MDMA transfer after the configuration of
0084               Source address and destination address and the Length of data to be transferred. In this
0085               case the MDMA interrupt is configured.
0086           (+) Use HAL_MDMA_IRQHandler() called under MDMA_IRQHandler() Interrupt subroutine
0087           (+) At the end of data transfer HAL_MDMA_IRQHandler() function is executed and user can
0088               add his own function by customization of function pointer XferCpltCallback and
0089               XferErrorCallback (i.e a member of MDMA handle structure).
0090 
0091           (+) Use HAL_MDMA_Abort_IT() function to abort the current transfer : non-blocking method. This API will finish the execution immediately
0092               then the callback XferAbortCallback (if specified  by the user) is asserted once the MDMA channel has effectively aborted.
0093               (could be called from an interrupt service routine).
0094 
0095           (+) Use functions HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback respectevely to register unregister user callbacks
0096               from the following list :
0097               (++) XferCpltCallback            : transfer complete callback.
0098               (++) XferBufferCpltCallback      : buffer transfer complete callback.
0099               (++) XferBlockCpltCallback       : block transfer complete callback.
0100               (++) XferRepeatBlockCpltCallback : repeated block transfer complete callback.
0101               (++) XferErrorCallback           : transfer error callback.
0102               (++) XferAbortCallback           : transfer abort complete callback.
0103 
0104     [..]
0105          (+)  If the transfer Request corresponds to SW request (MDMA_REQUEST_SW) User can use function HAL_MDMA_GenerateSWRequest to
0106               trigger requests manually. Function HAL_MDMA_GenerateSWRequest must be used with the following precautions:
0107               (++) This function returns an error if used while the Transfer has ended or not started.
0108               (++) If used while the current request has not been served yet (current request transfer on going)
0109                 this function returns an error and the new request is ignored.
0110 
0111               Generally this function should be used in conjunctions with the MDMA callbacks:
0112               (++) example 1:
0113                  (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BUFFER_TRANSFER
0114                  (+++) Register a callback for buffer transfer complete (using callback ID set to HAL_MDMA_XFER_BUFFERCPLT_CB_ID)
0115                  (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first BufferTransferLength data.
0116                  (+++) When the buffer transfer complete callback is asserted first buffer has been transferred and user can ask for a new buffer transfer
0117                    request using HAL_MDMA_GenerateSWRequest.
0118 
0119               (++) example 2:
0120                  (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BLOCK_TRANSFER
0121                  (+++) Register a callback for block transfer complete (using callback ID HAL_MDMA_XFER_BLOCKCPLT_CB_ID)
0122                  (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first block of data.
0123                  (+++) When the block transfer complete callback is asserted the first block has been transferred and user can ask
0124                    for a new block transfer request using HAL_MDMA_GenerateSWRequest.
0125 
0126     [..]  Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection.
0127 
0128      *** MDMA HAL driver macros list ***
0129      =============================================
0130      [..]
0131        Below the list of most used macros in MDMA HAL driver.
0132 
0133       (+) __HAL_MDMA_ENABLE: Enable the specified MDMA Channel.
0134       (+) __HAL_MDMA_DISABLE: Disable the specified MDMA Channel.
0135       (+) __HAL_MDMA_GET_FLAG: Get the MDMA Channel pending flags.
0136       (+) __HAL_MDMA_CLEAR_FLAG: Clear the MDMA Channel pending flags.
0137       (+) __HAL_MDMA_ENABLE_IT: Enable the specified MDMA Channel interrupts.
0138       (+) __HAL_MDMA_DISABLE_IT: Disable the specified MDMA Channel interrupts.
0139       (+) __HAL_MDMA_GET_IT_SOURCE: Check whether the specified MDMA Channel interrupt has occurred or not.
0140 
0141      [..]
0142       (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
0143 
0144     [..]
0145 
0146   @endverbatim
0147   */
0148 
0149 /* Includes ------------------------------------------------------------------*/
0150 #include "stm32h7xx_hal.h"
0151 
0152 /** @addtogroup STM32H7xx_HAL_Driver
0153   * @{
0154   */
0155 
0156 /** @defgroup MDMA  MDMA
0157   * @ingroup RTEMSBSPsARMSTM32H7
0158   * @brief MDMA HAL module driver
0159   * @{
0160   */
0161 
0162 #ifdef HAL_MDMA_MODULE_ENABLED
0163 
0164 /* Private typedef -----------------------------------------------------------*/
0165 /* Private constants ---------------------------------------------------------*/
0166 /** @addtogroup MDMA_Private_Constants
0167  * @{
0168  */
0169 #define HAL_TIMEOUT_MDMA_ABORT    5U    /* 5 ms */
0170 #define HAL_MDMA_CHANNEL_SIZE     0x40U /* an MDMA instance channel size is 64 byte  */
0171 /**
0172   * @}
0173   */
0174 /* Private macro -------------------------------------------------------------*/
0175 /* Private variables ---------------------------------------------------------*/
0176 /* Private function prototypes -----------------------------------------------*/
0177 /** @addtogroup MDMA_Private_Functions_Prototypes
0178   * @{
0179   */
0180 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount);
0181 static void MDMA_Init(MDMA_HandleTypeDef *hmdma);
0182 
0183 /**
0184   * @}
0185   */
0186 
0187 /** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
0188   * @{
0189   */
0190 
0191 /** @addtogroup MDMA_Exported_Functions_Group1
0192   *
0193 @verbatim
0194  ===============================================================================
0195              ##### Initialization and de-initialization functions  #####
0196  ===============================================================================
0197     [..]
0198     This section provides functions allowing to :
0199       Initialize and de-initialize the MDMA channel.
0200       Register and Unregister MDMA callbacks
0201     [..]
0202     The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in
0203     reference manual.
0204     The HAL_MDMA_DeInit function allows to deinitialize the MDMA channel.
0205     HAL_MDMA_RegisterCallback and  HAL_MDMA_UnRegisterCallback functions allows
0206     respectevely to register/unregister an MDMA callback function.
0207 
0208 @endverbatim
0209   * @{
0210   */
0211 
0212 /**
0213   * @brief  Initializes the MDMA according to the specified
0214   *         parameters in the MDMA_InitTypeDef and create the associated handle.
0215   * @param  hmdma: Pointer to a MDMA_HandleTypeDef structure that contains
0216   *               the configuration information for the specified MDMA Channel.
0217   * @retval HAL status
0218   */
0219 HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
0220 {
0221   uint32_t tickstart = HAL_GetTick();
0222 
0223   /* Check the MDMA peripheral handle */
0224   if(hmdma == NULL)
0225   {
0226     return HAL_ERROR;
0227   }
0228 
0229   /* Check the parameters */
0230   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
0231   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
0232   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));
0233   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
0234   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
0235   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
0236   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
0237   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
0238   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
0239   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
0240   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
0241   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));
0242   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
0243   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
0244   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
0245 
0246 
0247   /* Allocate lock resource */
0248   __HAL_UNLOCK(hmdma);
0249 
0250   /* Change MDMA peripheral state */
0251   hmdma->State = HAL_MDMA_STATE_BUSY;
0252 
0253   /* Disable the MDMA channel */
0254   __HAL_MDMA_DISABLE(hmdma);
0255 
0256   /* Check if the MDMA channel is effectively disabled */
0257   while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
0258   {
0259     /* Check for the Timeout */
0260     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
0261     {
0262       /* Update error code */
0263       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
0264 
0265       /* Change the MDMA state */
0266       hmdma->State = HAL_MDMA_STATE_ERROR;
0267 
0268       return HAL_ERROR;
0269     }
0270   }
0271 
0272   /* Initialize the MDMA channel registers */
0273   MDMA_Init(hmdma);
0274 
0275   /* Reset the MDMA first/last linkedlist node addresses and node counter */
0276   hmdma->FirstLinkedListNodeAddress  = 0;
0277   hmdma->LastLinkedListNodeAddress   = 0;
0278   hmdma->LinkedListNodeCounter  = 0;
0279 
0280   /* Initialize the error code */
0281   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
0282 
0283   /* Initialize the MDMA state */
0284   hmdma->State = HAL_MDMA_STATE_READY;
0285 
0286   return HAL_OK;
0287 }
0288 
0289 /**
0290   * @brief  DeInitializes the MDMA peripheral
0291   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
0292   *               the configuration information for the specified MDMA Channel.
0293   * @retval HAL status
0294   */
0295 HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma)
0296 {
0297 
0298   /* Check the MDMA peripheral handle */
0299   if(hmdma == NULL)
0300   {
0301     return HAL_ERROR;
0302   }
0303 
0304   /* Disable the selected MDMA Channelx */
0305   __HAL_MDMA_DISABLE(hmdma);
0306 
0307   /* Reset MDMA Channel control register */
0308   hmdma->Instance->CCR  = 0;
0309   hmdma->Instance->CTCR = 0;
0310   hmdma->Instance->CBNDTR = 0;
0311   hmdma->Instance->CSAR = 0;
0312   hmdma->Instance->CDAR = 0;
0313   hmdma->Instance->CBRUR = 0;
0314   hmdma->Instance->CLAR = 0;
0315   hmdma->Instance->CTBR = 0;
0316   hmdma->Instance->CMAR = 0;
0317   hmdma->Instance->CMDR = 0;
0318 
0319   /* Clear all flags */
0320   __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC));
0321 
0322   /* Reset the  MDMA first/last linkedlist node addresses and node counter */
0323   hmdma->FirstLinkedListNodeAddress  = 0;
0324   hmdma->LastLinkedListNodeAddress   = 0;
0325   hmdma->LinkedListNodeCounter  = 0;
0326 
0327   /* Initialize the error code */
0328   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
0329 
0330   /* Initialize the MDMA state */
0331   hmdma->State = HAL_MDMA_STATE_RESET;
0332 
0333   /* Release Lock */
0334   __HAL_UNLOCK(hmdma);
0335 
0336   return HAL_OK;
0337 }
0338 
0339 /**
0340   * @brief  Config the Post request Mask address and Mask data
0341   * @param  hmdma      : pointer to a MDMA_HandleTypeDef structure that contains
0342   *                               the configuration information for the specified MDMA Channel.
0343   * @param  MaskAddress: specifies the address to be updated (written) with MaskData after a request is served.
0344   * @param  MaskData:    specifies the value to be written to MaskAddress after a request is served.
0345   *                      MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served.
0346   * @retval HAL status
0347   */
0348 HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData)
0349 {
0350   HAL_StatusTypeDef  status = HAL_OK;
0351 
0352   /* Check the MDMA peripheral handle */
0353   if(hmdma == NULL)
0354   {
0355     return HAL_ERROR;
0356   }
0357 
0358   /* Process locked */
0359   __HAL_LOCK(hmdma);
0360 
0361   if(HAL_MDMA_STATE_READY == hmdma->State)
0362   {
0363     /* if HW request set Post Request MaskAddress and MaskData,  */
0364     if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U)
0365     {
0366       /* Set the HW request clear Mask and Data */
0367       hmdma->Instance->CMAR = MaskAddress;
0368       hmdma->Instance->CMDR = MaskData;
0369 
0370       /*
0371       -If the request is done by SW : BWM could be set to 1 or 0.
0372       -If the request is done by a peripheral :
0373          If mask address not set (0) => BWM must be set to 0
0374          If mask address set (different than 0) => BWM could be set to 1 or 0
0375       */
0376       if(MaskAddress == 0U)
0377       {
0378         hmdma->Instance->CTCR &=  ~MDMA_CTCR_BWM;
0379       }
0380       else
0381       {
0382         hmdma->Instance->CTCR |=  MDMA_CTCR_BWM;
0383       }
0384     }
0385     else
0386     {
0387       /* Return error status */
0388       status =  HAL_ERROR;
0389     }
0390   }
0391   else
0392   {
0393     /* Return error status */
0394     status =  HAL_ERROR;
0395   }
0396   /* Release Lock */
0397   __HAL_UNLOCK(hmdma);
0398 
0399   return status;
0400 }
0401 
0402 /**
0403   * @brief  Register callbacks
0404   * @param  hmdma:                pointer to a MDMA_HandleTypeDef structure that contains
0405   *                               the configuration information for the specified MDMA Channel.
0406   * @param  CallbackID:           User Callback identifier
0407   * @param  pCallback:            pointer to callbacsk function.
0408   * @retval HAL status
0409   */
0410 HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma))
0411 {
0412   HAL_StatusTypeDef status = HAL_OK;
0413 
0414   /* Check the MDMA peripheral handle */
0415   if(hmdma == NULL)
0416   {
0417     return HAL_ERROR;
0418   }
0419 
0420   /* Process locked */
0421   __HAL_LOCK(hmdma);
0422 
0423   if(HAL_MDMA_STATE_READY == hmdma->State)
0424   {
0425     switch (CallbackID)
0426     {
0427     case  HAL_MDMA_XFER_CPLT_CB_ID:
0428       hmdma->XferCpltCallback = pCallback;
0429       break;
0430 
0431     case  HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
0432       hmdma->XferBufferCpltCallback = pCallback;
0433       break;
0434 
0435     case  HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
0436       hmdma->XferBlockCpltCallback = pCallback;
0437       break;
0438 
0439     case  HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
0440       hmdma->XferRepeatBlockCpltCallback = pCallback;
0441       break;
0442 
0443     case  HAL_MDMA_XFER_ERROR_CB_ID:
0444       hmdma->XferErrorCallback = pCallback;
0445       break;
0446 
0447     case  HAL_MDMA_XFER_ABORT_CB_ID:
0448       hmdma->XferAbortCallback = pCallback;
0449       break;
0450 
0451     default:
0452       break;
0453     }
0454   }
0455   else
0456   {
0457     /* Return error status */
0458     status =  HAL_ERROR;
0459   }
0460 
0461   /* Release Lock */
0462   __HAL_UNLOCK(hmdma);
0463 
0464   return status;
0465 }
0466 
0467 /**
0468   * @brief  UnRegister callbacks
0469   * @param  hmdma:                 pointer to a MDMA_HandleTypeDef structure that contains
0470   *                               the configuration information for the specified MDMA Channel.
0471   * @param  CallbackID:           User Callback identifier
0472   *                               a HAL_MDMA_CallbackIDTypeDef ENUM as parameter.
0473   * @retval HAL status
0474   */
0475 HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID)
0476 {
0477   HAL_StatusTypeDef status = HAL_OK;
0478 
0479   /* Check the MDMA peripheral handle */
0480   if(hmdma == NULL)
0481   {
0482     return HAL_ERROR;
0483   }
0484 
0485   /* Process locked */
0486   __HAL_LOCK(hmdma);
0487 
0488   if(HAL_MDMA_STATE_READY == hmdma->State)
0489   {
0490     switch (CallbackID)
0491     {
0492     case  HAL_MDMA_XFER_CPLT_CB_ID:
0493       hmdma->XferCpltCallback = NULL;
0494       break;
0495 
0496     case  HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
0497       hmdma->XferBufferCpltCallback = NULL;
0498       break;
0499 
0500     case  HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
0501       hmdma->XferBlockCpltCallback = NULL;
0502       break;
0503 
0504     case  HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
0505       hmdma->XferRepeatBlockCpltCallback = NULL;
0506       break;
0507 
0508     case  HAL_MDMA_XFER_ERROR_CB_ID:
0509       hmdma->XferErrorCallback = NULL;
0510       break;
0511 
0512     case  HAL_MDMA_XFER_ABORT_CB_ID:
0513       hmdma->XferAbortCallback = NULL;
0514       break;
0515 
0516     case   HAL_MDMA_XFER_ALL_CB_ID:
0517       hmdma->XferCpltCallback = NULL;
0518       hmdma->XferBufferCpltCallback = NULL;
0519       hmdma->XferBlockCpltCallback = NULL;
0520       hmdma->XferRepeatBlockCpltCallback = NULL;
0521       hmdma->XferErrorCallback = NULL;
0522       hmdma->XferAbortCallback = NULL;
0523       break;
0524 
0525     default:
0526       status = HAL_ERROR;
0527       break;
0528     }
0529   }
0530   else
0531   {
0532     status = HAL_ERROR;
0533   }
0534 
0535   /* Release Lock */
0536   __HAL_UNLOCK(hmdma);
0537 
0538   return status;
0539 }
0540 
0541 /**
0542   * @}
0543   */
0544 
0545 /** @addtogroup MDMA_Exported_Functions_Group2
0546  *
0547 @verbatim
0548  ===============================================================================
0549                       #####  Linked list operation functions  #####
0550  ===============================================================================
0551     [..]  This section provides functions allowing to:
0552       (+) Create a linked list node
0553       (+) Add a node to the MDMA linked list
0554       (+) Remove a node from the MDMA linked list
0555       (+) Enable/Disable linked list circular mode
0556 @endverbatim
0557   * @{
0558   */
0559 
0560 /**
0561   * @brief  Initializes an MDMA Link Node according to the specified
0562   *         parameters in the pMDMA_LinkedListNodeConfig .
0563   * @param  pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
0564   *         registers configurations.
0565   * @param  pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains
0566   *               the configuration information for the specified MDMA Linked List Node.
0567   * @retval HAL status
0568   */
0569 HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig)
0570 {
0571   uint32_t addressMask;
0572   uint32_t blockoffset;
0573 
0574   /* Check the MDMA peripheral state */
0575   if((pNode == NULL) || (pNodeConfig == NULL))
0576   {
0577     return HAL_ERROR;
0578   }
0579 
0580   /* Check the parameters */
0581   assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority));
0582   assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness));
0583   assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request));
0584   assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc));
0585   assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc));
0586   assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize));
0587   assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize));
0588   assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment));
0589   assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst));
0590   assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst));
0591   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength));
0592   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode));
0593   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset));
0594   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset));
0595 
0596   assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength));
0597   assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount));
0598 
0599 
0600   /* Configure next Link node Address Register to zero */
0601   pNode->CLAR =  0;
0602 
0603   /* Configure the Link Node registers*/
0604   pNode->CTBR   = 0;
0605   pNode->CMAR   = 0;
0606   pNode->CMDR   = 0;
0607   pNode->Reserved = 0;
0608 
0609   /* Write new CTCR Register value */
0610   pNode->CTCR =  pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \
0611     pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize           | \
0612       pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst            | \
0613         pNodeConfig->Init.DestBurst                                             | \
0614           ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
0615             pNodeConfig->Init.TransferTriggerMode;
0616 
0617   /* If SW request set the CTCR register to SW Request Mode*/
0618   if(pNodeConfig->Init.Request == MDMA_REQUEST_SW)
0619   {
0620     pNode->CTCR |= MDMA_CTCR_SWRM;
0621   }
0622 
0623   /*
0624   -If the request is done by SW : BWM could be set to 1 or 0.
0625   -If the request is done by a peripheral :
0626      If mask address not set (0) => BWM must be set to 0
0627      If mask address set (different than 0) => BWM could be set to 1 or 0
0628   */
0629   if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U))
0630   {
0631     pNode->CTCR |=  MDMA_CTCR_BWM;
0632   }
0633 
0634   /* Set the new CBNDTR Register value */
0635   pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC;
0636 
0637   /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
0638   if(pNodeConfig->Init.SourceBlockAddressOffset < 0)
0639   {
0640     pNode->CBNDTR |= MDMA_CBNDTR_BRSUM;
0641     /*write new CBRUR Register value : source repeat block offset */
0642     blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset);
0643     pNode->CBRUR = blockoffset & 0x0000FFFFU;
0644   }
0645   else
0646   {
0647     /*write new CBRUR Register value : source repeat block offset */
0648     pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
0649   }
0650 
0651   /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
0652   if(pNodeConfig->Init.DestBlockAddressOffset < 0)
0653   {
0654     pNode->CBNDTR |= MDMA_CBNDTR_BRDUM;
0655     /*write new CBRUR Register value : destination repeat block offset */
0656     blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset);
0657     pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
0658   }
0659   else
0660   {
0661     /*write new CBRUR Register value : destination repeat block offset */
0662     pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
0663   }
0664 
0665   /* Configure MDMA Link Node data length */
0666   pNode->CBNDTR |=  pNodeConfig->BlockDataLength;
0667 
0668   /* Configure MDMA Link Node destination address */
0669   pNode->CDAR = pNodeConfig->DstAddress;
0670 
0671   /* Configure MDMA Link Node Source address */
0672   pNode->CSAR = pNodeConfig->SrcAddress;
0673 
0674   /* if HW request set the HW request and the requet CleraMask and ClearData MaskData,  */
0675   if(pNodeConfig->Init.Request != MDMA_REQUEST_SW)
0676   {
0677     /* Set the HW request in CTBR register  */
0678     pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL;
0679     /* Set the HW request clear Mask and Data */
0680     pNode->CMAR = pNodeConfig->PostRequestMaskAddress;
0681     pNode->CMDR = pNodeConfig->PostRequestMaskData;
0682   }
0683 
0684   addressMask = pNodeConfig->SrcAddress & 0xFF000000U;
0685   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
0686   {
0687     /*The AHBSbus is used as source (read operation) on channel x */
0688     pNode->CTBR |= MDMA_CTBR_SBUS;
0689   }
0690 
0691   addressMask = pNodeConfig->DstAddress & 0xFF000000U;
0692   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
0693   {
0694     /*The AHB bus is used as destination (write operation) on channel x */
0695     pNode->CTBR |= MDMA_CTBR_DBUS;
0696   }
0697 
0698   return HAL_OK;
0699 }
0700 
0701 /**
0702   * @brief  Connect a node to the linked list.
0703   * @param  hmdma    : Pointer to a MDMA_HandleTypeDef structure that contains
0704   *                    the configuration information for the specified MDMA Channel.
0705   * @param  pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
0706   *                    to be add to the list.
0707   * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
0708   *                    at the end of the list
0709   *
0710   * @retval HAL status
0711   */
0712 HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
0713 {
0714   MDMA_LinkNodeTypeDef *pNode;
0715   uint32_t counter = 0, nodeInserted = 0;
0716   HAL_StatusTypeDef hal_status = HAL_OK;
0717 
0718   /* Check the MDMA peripheral handle */
0719   if((hmdma == NULL) || (pNewNode == NULL))
0720   {
0721     return HAL_ERROR;
0722   }
0723 
0724   /* Process locked */
0725   __HAL_LOCK(hmdma);
0726 
0727   if(HAL_MDMA_STATE_READY == hmdma->State)
0728   {
0729     /* Change MDMA peripheral state */
0730     hmdma->State = HAL_MDMA_STATE_BUSY;
0731 
0732     /* Check if this is the first node (after the Inititlization node) */
0733     if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U)
0734     {
0735       if(pPrevNode == NULL)
0736       {
0737         /* if this is the first node after the initialization
0738         connect this node to the node 0 by updating
0739         the MDMA channel CLAR register to this node address */
0740         hmdma->Instance->CLAR = (uint32_t)pNewNode;
0741         /* Set the MDMA handle First linked List node*/
0742         hmdma->FirstLinkedListNodeAddress = pNewNode;
0743 
0744         /*reset New node link */
0745         pNewNode->CLAR = 0;
0746 
0747         /* Update the Handle last node address */
0748         hmdma->LastLinkedListNodeAddress = pNewNode;
0749 
0750         hmdma->LinkedListNodeCounter = 1;
0751       }
0752       else
0753       {
0754         hal_status = HAL_ERROR;
0755       }
0756     }
0757     else if(hmdma->FirstLinkedListNodeAddress != pNewNode)
0758     {
0759       /* Check if the node to insert already exists*/
0760       pNode = hmdma->FirstLinkedListNodeAddress;
0761       while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
0762       {
0763         if(pNode->CLAR == (uint32_t)pNewNode)
0764         {
0765           hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
0766         }
0767         pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
0768         counter++;
0769       }
0770 
0771       if(hal_status == HAL_OK)
0772       {
0773         /* Check if the previous node is the last one in the current list or zero */
0774         if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL))
0775         {
0776           /* insert the new node at the end of the list */
0777           pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;
0778           hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
0779           /* Update the Handle last node address */
0780           hmdma->LastLinkedListNodeAddress = pNewNode;
0781           /* Increment the linked list node counter */
0782           hmdma->LinkedListNodeCounter++;
0783         }
0784         else
0785         {
0786           /*insert the new node after the pPreviousNode node */
0787           pNode = hmdma->FirstLinkedListNodeAddress;
0788           counter = 0;
0789           while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U))
0790           {
0791             counter++;
0792             if(pNode == pPrevNode)
0793             {
0794               /*Insert the new node after the previous one */
0795               pNewNode->CLAR = pNode->CLAR;
0796               pNode->CLAR = (uint32_t)pNewNode;
0797               /* Increment the linked list node counter */
0798               hmdma->LinkedListNodeCounter++;
0799               nodeInserted = 1;
0800             }
0801             else
0802             {
0803               pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
0804             }
0805           }
0806 
0807           if(nodeInserted == 0U)
0808           {
0809             hal_status = HAL_ERROR;
0810           }
0811         }
0812       }
0813     }
0814     else
0815     {
0816       hal_status = HAL_ERROR;
0817     }
0818 
0819     /* Process unlocked */
0820     __HAL_UNLOCK(hmdma);
0821 
0822     hmdma->State = HAL_MDMA_STATE_READY;
0823 
0824     return hal_status;
0825   }
0826   else
0827   {
0828     /* Process unlocked */
0829     __HAL_UNLOCK(hmdma);
0830 
0831     /* Return error status */
0832     return HAL_BUSY;
0833   }
0834 }
0835 
0836 /**
0837   * @brief  Disconnect/Remove a node from the transfer linked list.
0838   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
0839   *                 the configuration information for the specified MDMA Channel.
0840   * @param  pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
0841   *                 to be removed from the list.
0842   *
0843   * @retval HAL status
0844   */
0845 HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode)
0846 {
0847   MDMA_LinkNodeTypeDef *ptmpNode;
0848   uint32_t counter = 0, nodeDeleted = 0;
0849   HAL_StatusTypeDef hal_status = HAL_OK;
0850 
0851   /* Check the MDMA peripheral handle */
0852   if((hmdma == NULL) || (pNode == NULL))
0853   {
0854     return HAL_ERROR;
0855   }
0856 
0857   /* Process locked */
0858   __HAL_LOCK(hmdma);
0859 
0860   if(HAL_MDMA_STATE_READY == hmdma->State)
0861   {
0862     /* Change MDMA peripheral state */
0863     hmdma->State = HAL_MDMA_STATE_BUSY;
0864 
0865     /* If first and last node are null (no nodes in the list) : return error*/
0866     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
0867     {
0868       hal_status = HAL_ERROR;
0869     }
0870     else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */
0871     {
0872       /* Delete 1st node */
0873       if(hmdma->LastLinkedListNodeAddress == pNode)
0874       {
0875         /*if the last node is at the same time the first one (1 single node after the init node 0)
0876         then update the last node too */
0877 
0878         hmdma->FirstLinkedListNodeAddress = 0;
0879         hmdma->LastLinkedListNodeAddress  = 0;
0880         hmdma->LinkedListNodeCounter = 0;
0881 
0882         hmdma->Instance->CLAR = 0;
0883       }
0884       else
0885       {
0886         if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR)
0887         {
0888           /* if last node is looping to first (circular list) one update the last node connection */
0889           hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR;
0890         }
0891 
0892         /* if deleting the first node after the initialization
0893         connect the next node to the node 0 by updating
0894         the MDMA channel CLAR register to this node address */
0895         hmdma->Instance->CLAR = pNode->CLAR;
0896         hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR;
0897         /* Update the Handle node counter */
0898         hmdma->LinkedListNodeCounter--;
0899       }
0900     }
0901     else /* Deleting any other node */
0902     {
0903       /*Deleted node is not the first one : find it  */
0904       ptmpNode = hmdma->FirstLinkedListNodeAddress;
0905       while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U))
0906       {
0907         counter++;
0908         if(ptmpNode->CLAR == ((uint32_t)pNode))
0909         {
0910           /* if deleting the last node */
0911           if(pNode == hmdma->LastLinkedListNodeAddress)
0912           {
0913             /*Update the linked list last node address in the handle*/
0914             hmdma->LastLinkedListNodeAddress = ptmpNode;
0915           }
0916           /* update the next node link after deleting pMDMA_LinkedListNode */
0917           ptmpNode->CLAR = pNode->CLAR;
0918           nodeDeleted = 1;
0919           /* Update the Handle node counter */
0920           hmdma->LinkedListNodeCounter--;
0921         }
0922         else
0923         {
0924           ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR;
0925         }
0926       }
0927 
0928       if(nodeDeleted == 0U)
0929       {
0930         /* last node reashed without finding the node to delete : return error */
0931         hal_status = HAL_ERROR;
0932       }
0933     }
0934 
0935     /* Process unlocked */
0936     __HAL_UNLOCK(hmdma);
0937 
0938     hmdma->State = HAL_MDMA_STATE_READY;
0939 
0940     return hal_status;
0941   }
0942   else
0943   {
0944     /* Process unlocked */
0945     __HAL_UNLOCK(hmdma);
0946 
0947     /* Return error status */
0948     return HAL_BUSY;
0949   }
0950 }
0951 
0952 /**
0953   * @brief  Make the linked list circular by connecting the last node to the first.
0954   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
0955   *                 the configuration information for the specified MDMA Channel.
0956   * @retval HAL status
0957   */
0958 HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
0959 {
0960   HAL_StatusTypeDef hal_status = HAL_OK;
0961 
0962   /* Check the MDMA peripheral handle */
0963   if(hmdma == NULL)
0964   {
0965     return HAL_ERROR;
0966   }
0967 
0968   /* Process locked */
0969   __HAL_LOCK(hmdma);
0970 
0971   if(HAL_MDMA_STATE_READY == hmdma->State)
0972   {
0973     /* Change MDMA peripheral state */
0974     hmdma->State = HAL_MDMA_STATE_BUSY;
0975 
0976     /* If first and last node are null (no nodes in the list) : return error*/
0977     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
0978     {
0979       hal_status = HAL_ERROR;
0980     }
0981     else
0982     {
0983       /* to enable circular mode Last Node should be connected to first node */
0984       hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
0985     }
0986 
0987   }
0988   /* Process unlocked */
0989   __HAL_UNLOCK(hmdma);
0990 
0991   hmdma->State = HAL_MDMA_STATE_READY;
0992 
0993   return hal_status;
0994 }
0995 
0996 /**
0997   * @brief  Disable the linked list circular mode by setting the last node connection to null
0998   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
0999   *                 the configuration information for the specified MDMA Channel.
1000   * @retval HAL status
1001   */
1002 HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma)
1003 {
1004   HAL_StatusTypeDef hal_status = HAL_OK;
1005 
1006   /* Check the MDMA peripheral handle */
1007   if(hmdma == NULL)
1008   {
1009     return HAL_ERROR;
1010   }
1011 
1012   /* Process locked */
1013   __HAL_LOCK(hmdma);
1014 
1015   if(HAL_MDMA_STATE_READY == hmdma->State)
1016   {
1017     /* Change MDMA peripheral state */
1018     hmdma->State = HAL_MDMA_STATE_BUSY;
1019 
1020     /* If first and last node are null (no nodes in the list) : return error*/
1021     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
1022     {
1023       hal_status = HAL_ERROR;
1024     }
1025     else
1026     {
1027       /* to disable circular mode Last Node should be connected to NULL */
1028       hmdma->LastLinkedListNodeAddress->CLAR = 0;
1029     }
1030 
1031   }
1032   /* Process unlocked */
1033   __HAL_UNLOCK(hmdma);
1034 
1035   hmdma->State = HAL_MDMA_STATE_READY;
1036 
1037   return hal_status;
1038 }
1039 
1040 /**
1041   * @}
1042   */
1043 
1044 /** @addtogroup MDMA_Exported_Functions_Group3
1045  *
1046 @verbatim
1047  ===============================================================================
1048                       #####  IO operation functions  #####
1049  ===============================================================================
1050     [..]  This section provides functions allowing to:
1051       (+) Configure the source, destination address and data length and Start MDMA transfer
1052       (+) Configure the source, destination address and data length and
1053           Start MDMA transfer with interrupt
1054       (+) Abort MDMA transfer
1055       (+) Poll for transfer complete
1056       (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW)
1057       (+) Handle MDMA interrupt request
1058 
1059 @endverbatim
1060   * @{
1061   */
1062 
1063 /**
1064   * @brief  Starts the MDMA Transfer.
1065   * @param  hmdma           : pointer to a MDMA_HandleTypeDef structure that contains
1066   *                           the configuration information for the specified MDMA Channel.
1067   * @param  SrcAddress      : The source memory Buffer address
1068   * @param  DstAddress      : The destination memory Buffer address
1069   * @param  BlockDataLength : The length of a block transfer in bytes
1070   * @param  BlockCount      : The number of a blocks to be transfer
1071   * @retval HAL status
1072   */
1073 HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1074 {
1075   /* Check the parameters */
1076   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1077   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
1078 
1079   /* Check the MDMA peripheral handle */
1080   if(hmdma == NULL)
1081   {
1082     return HAL_ERROR;
1083   }
1084 
1085   /* Process locked */
1086   __HAL_LOCK(hmdma);
1087 
1088   if(HAL_MDMA_STATE_READY == hmdma->State)
1089   {
1090     /* Change MDMA peripheral state */
1091     hmdma->State = HAL_MDMA_STATE_BUSY;
1092 
1093     /* Initialize the error code */
1094     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1095 
1096     /* Disable the peripheral */
1097     __HAL_MDMA_DISABLE(hmdma);
1098 
1099     /* Configure the source, destination address and the data length */
1100     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
1101 
1102     /* Enable the Peripheral */
1103     __HAL_MDMA_ENABLE(hmdma);
1104 
1105     if(hmdma->Init.Request == MDMA_REQUEST_SW)
1106     {
1107       /* activate If SW request mode*/
1108       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
1109     }
1110   }
1111   else
1112   {
1113     /* Process unlocked */
1114     __HAL_UNLOCK(hmdma);
1115 
1116     /* Return error status */
1117     return HAL_BUSY;
1118   }
1119 
1120   return HAL_OK;
1121 }
1122 
1123 /**
1124   * @brief  Starts the MDMA Transfer with interrupts enabled.
1125   * @param  hmdma           : pointer to a MDMA_HandleTypeDef structure that contains
1126   *                           the configuration information for the specified MDMA Channel.
1127   * @param  SrcAddress      : The source memory Buffer address
1128   * @param  DstAddress      : The destination memory Buffer address
1129   * @param  BlockDataLength : The length of a block transfer in bytes
1130   * @param  BlockCount      : The number of a blocks to be transfer
1131   * @retval HAL status
1132   */
1133 HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1134 {
1135   /* Check the parameters */
1136   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1137   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
1138 
1139   /* Check the MDMA peripheral handle */
1140   if(hmdma == NULL)
1141   {
1142     return HAL_ERROR;
1143   }
1144 
1145   /* Process locked */
1146   __HAL_LOCK(hmdma);
1147 
1148   if(HAL_MDMA_STATE_READY == hmdma->State)
1149   {
1150     /* Change MDMA peripheral state */
1151     hmdma->State = HAL_MDMA_STATE_BUSY;
1152 
1153     /* Initialize the error code */
1154     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1155 
1156     /* Disable the peripheral */
1157     __HAL_MDMA_DISABLE(hmdma);
1158 
1159     /* Configure the source, destination address and the data length */
1160     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
1161 
1162     /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/
1163     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
1164 
1165     if(hmdma->XferBlockCpltCallback != NULL)
1166     {
1167       /* if Block transfer complete Callback is set enable the corresponding IT*/
1168       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
1169     }
1170 
1171     if(hmdma->XferRepeatBlockCpltCallback != NULL)
1172     {
1173       /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/
1174       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
1175     }
1176 
1177     if(hmdma->XferBufferCpltCallback != NULL)
1178     {
1179       /* if buffer transfer complete Callback is set enable the corresponding IT*/
1180       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);
1181     }
1182 
1183     /* Enable the Peripheral */
1184     __HAL_MDMA_ENABLE(hmdma);
1185 
1186     if(hmdma->Init.Request == MDMA_REQUEST_SW)
1187     {
1188       /* activate If SW request mode*/
1189       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
1190     }
1191   }
1192   else
1193   {
1194     /* Process unlocked */
1195     __HAL_UNLOCK(hmdma);
1196 
1197     /* Return error status */
1198     return HAL_BUSY;
1199   }
1200 
1201   return HAL_OK;
1202 }
1203 
1204 /**
1205   * @brief  Aborts the MDMA Transfer.
1206   * @param  hmdma  : pointer to a MDMA_HandleTypeDef structure that contains
1207   *                 the configuration information for the specified MDMA Channel.
1208   *
1209   * @note  After disabling a MDMA Channel, a check for wait until the MDMA Channel is
1210   *        effectively disabled is added. If a Channel is disabled
1211   *        while a data transfer is ongoing, the current data will be transferred
1212   *        and the Channel will be effectively disabled only after the transfer of
1213   *        this single data is finished.
1214   * @retval HAL status
1215   */
1216 HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma)
1217 {
1218   uint32_t tickstart =  HAL_GetTick();
1219 
1220   /* Check the MDMA peripheral handle */
1221   if(hmdma == NULL)
1222   {
1223     return HAL_ERROR;
1224   }
1225 
1226   if(HAL_MDMA_STATE_BUSY != hmdma->State)
1227   {
1228     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1229 
1230     /* Process Unlocked */
1231     __HAL_UNLOCK(hmdma);
1232 
1233     return HAL_ERROR;
1234   }
1235   else
1236   {
1237     /* Disable all the transfer interrupts */
1238     __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
1239 
1240     /* Disable the channel */
1241     __HAL_MDMA_DISABLE(hmdma);
1242 
1243     /* Check if the MDMA Channel is effectively disabled */
1244     while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
1245     {
1246       /* Check for the Timeout */
1247       if( (HAL_GetTick()  - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
1248       {
1249         /* Update error code */
1250         hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
1251 
1252         /* Process Unlocked */
1253         __HAL_UNLOCK(hmdma);
1254 
1255         /* Change the MDMA state */
1256         hmdma->State = HAL_MDMA_STATE_ERROR;
1257 
1258         return HAL_ERROR;
1259       }
1260     }
1261 
1262     /* Clear all interrupt flags */
1263     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC));
1264 
1265     /* Process Unlocked */
1266     __HAL_UNLOCK(hmdma);
1267 
1268     /* Change the MDMA state*/
1269     hmdma->State = HAL_MDMA_STATE_READY;
1270   }
1271 
1272   return HAL_OK;
1273 }
1274 
1275 /**
1276   * @brief  Aborts the MDMA Transfer in Interrupt mode.
1277   * @param  hmdma  : pointer to a MDMA_HandleTypeDef structure that contains
1278   *                 the configuration information for the specified MDMA Channel.
1279   * @retval HAL status
1280   */
1281 HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma)
1282 {
1283   /* Check the MDMA peripheral handle */
1284   if(hmdma == NULL)
1285   {
1286     return HAL_ERROR;
1287   }
1288 
1289   if(HAL_MDMA_STATE_BUSY != hmdma->State)
1290   {
1291     /* No transfer ongoing */
1292     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1293 
1294     return HAL_ERROR;
1295   }
1296   else
1297   {
1298     /* Set Abort State  */
1299     hmdma->State = HAL_MDMA_STATE_ABORT;
1300 
1301     /* Disable the stream */
1302     __HAL_MDMA_DISABLE(hmdma);
1303   }
1304 
1305   return HAL_OK;
1306 }
1307 
1308 /**
1309   * @brief  Polling for transfer complete.
1310   * @param  hmdma:          pointer to a MDMA_HandleTypeDef structure that contains
1311   *                        the configuration information for the specified MDMA Channel.
1312   * @param  CompleteLevel: Specifies the MDMA level complete.
1313   * @param  Timeout:       Timeout duration.
1314   * @retval HAL status
1315   */
1316 HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
1317 {
1318   uint32_t levelFlag, errorFlag;
1319   uint32_t tickstart;
1320 
1321   /* Check the parameters */
1322   assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel));
1323 
1324   /* Check the MDMA peripheral handle */
1325   if(hmdma == NULL)
1326   {
1327     return HAL_ERROR;
1328   }
1329 
1330   if(HAL_MDMA_STATE_BUSY != hmdma->State)
1331   {
1332     /* No transfer ongoing */
1333     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1334 
1335     return HAL_ERROR;
1336   }
1337 
1338   /* Get the level transfer complete flag */
1339   levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER)  ? MDMA_FLAG_CTC  : \
1340                (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \
1341                (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT   : \
1342                MDMA_FLAG_BRT);
1343 
1344 
1345   /* Get timeout */
1346   tickstart = HAL_GetTick();
1347 
1348   while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U)
1349   {
1350     if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
1351     {
1352       /* Get the transfer error source flag */
1353       errorFlag = hmdma->Instance->CESR;
1354 
1355       if((errorFlag & MDMA_CESR_TED) == 0U)
1356       {
1357         /* Update error code : Read Transfer error  */
1358         hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
1359       }
1360       else
1361       {
1362         /* Update error code : Write Transfer error */
1363         hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
1364       }
1365 
1366       if((errorFlag & MDMA_CESR_TEMD) != 0U)
1367       {
1368         /* Update error code : Error Mask Data */
1369         hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
1370       }
1371 
1372       if((errorFlag & MDMA_CESR_TELD) != 0U)
1373       {
1374         /* Update error code : Error Linked list */
1375         hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
1376       }
1377 
1378       if((errorFlag & MDMA_CESR_ASE) != 0U)
1379       {
1380         /* Update error code : Address/Size alignment error */
1381         hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
1382       }
1383 
1384       if((errorFlag & MDMA_CESR_BSE) != 0U)
1385       {
1386         /* Update error code : Block Size error */
1387         hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
1388       }
1389 
1390       (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */
1391 
1392       /*
1393         Note that the Abort function will
1394           - Clear all transfer flags
1395           - Unlock
1396           - Set the State
1397       */
1398 
1399       return HAL_ERROR;
1400 
1401     }
1402 
1403     /* Check for the Timeout */
1404     if(Timeout != HAL_MAX_DELAY)
1405     {
1406       if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
1407       {
1408         /* Update error code */
1409         hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
1410 
1411         (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */
1412 
1413         /*
1414           Note that the Abort function will
1415             - Clear all transfer flags
1416             - Unlock
1417             - Set the State
1418         */
1419 
1420         return HAL_ERROR;
1421       }
1422     }
1423   }
1424 
1425   /* Clear the transfer level flag */
1426   if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)
1427   {
1428     __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
1429 
1430   }
1431   else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER)
1432   {
1433     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT));
1434 
1435   }
1436   else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER)
1437   {
1438     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT));
1439   }
1440   else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER)
1441   {
1442     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC));
1443 
1444     /* Process unlocked */
1445     __HAL_UNLOCK(hmdma);
1446 
1447     hmdma->State = HAL_MDMA_STATE_READY;
1448   }
1449   else
1450   {
1451     return HAL_ERROR;
1452   }
1453 
1454   return HAL_OK;
1455 }
1456 
1457 /**
1458   * @brief  Generate an MDMA SW request trigger to activate the request on the given Channel.
1459   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
1460   *                     the configuration information for the specified MDMA Stream.
1461   * @retval HAL status
1462   */
1463 HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma)
1464 {
1465   uint32_t request_mode;
1466 
1467   /* Check the MDMA peripheral handle */
1468   if(hmdma == NULL)
1469   {
1470     return HAL_ERROR;
1471   }
1472 
1473   /* Get the softawre request mode */
1474   request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM;
1475 
1476   if((hmdma->Instance->CCR &  MDMA_CCR_EN) == 0U)
1477   {
1478     /* if no Transfer on going (MDMA enable bit not set) return error */
1479     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1480 
1481     return HAL_ERROR;
1482   }
1483   else if(((hmdma->Instance->CISR &  MDMA_CISR_CRQA) != 0U) || (request_mode == 0U))
1484   {
1485     /* if an MDMA ongoing request has not yet end or if request mode is not SW request return error */
1486     hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY;
1487 
1488     return HAL_ERROR;
1489   }
1490   else
1491   {
1492     /* Set the SW request bit to activate the request on the Channel */
1493     hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
1494 
1495     return HAL_OK;
1496   }
1497 }
1498 
1499 /**
1500   * @brief  Handles MDMA interrupt request.
1501   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1502   *               the configuration information for the specified MDMA Channel.
1503   * @retval None
1504   */
1505 void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma)
1506 {
1507   __IO uint32_t count = 0;
1508   uint32_t timeout = SystemCoreClock / 9600U;
1509 
1510   uint32_t generalIntFlag, errorFlag;
1511 
1512   /* General Interrupt Flag management ****************************************/
1513   generalIntFlag =  1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU);
1514   if((MDMA->GISR0 & generalIntFlag) == 0U)
1515   {
1516     return; /* the  General interrupt flag for the current channel is down , nothing to do */
1517   }
1518 
1519   /* Transfer Error Interrupt management ***************************************/
1520   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
1521   {
1522     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U)
1523     {
1524       /* Disable the transfer error interrupt */
1525       __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE);
1526 
1527       /* Get the transfer error source flag */
1528       errorFlag = hmdma->Instance->CESR;
1529 
1530       if((errorFlag & MDMA_CESR_TED) == 0U)
1531       {
1532         /* Update error code : Read Transfer error  */
1533         hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
1534       }
1535       else
1536       {
1537         /* Update error code : Write Transfer error */
1538         hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
1539       }
1540 
1541       if((errorFlag & MDMA_CESR_TEMD) != 0U)
1542       {
1543         /* Update error code : Error Mask Data */
1544         hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
1545       }
1546 
1547       if((errorFlag & MDMA_CESR_TELD) != 0U)
1548       {
1549         /* Update error code : Error Linked list */
1550         hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
1551       }
1552 
1553       if((errorFlag & MDMA_CESR_ASE) != 0U)
1554       {
1555         /* Update error code : Address/Size alignment error */
1556         hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
1557       }
1558 
1559       if((errorFlag & MDMA_CESR_BSE) != 0U)
1560       {
1561         /* Update error code : Block Size error error */
1562         hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
1563       }
1564 
1565       /* Clear the transfer error flags */
1566       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE);
1567     }
1568   }
1569 
1570   /* Buffer Transfer Complete Interrupt management ******************************/
1571   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U))
1572   {
1573     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U)
1574     {
1575       /* Clear the buffer transfer complete flag */
1576       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
1577 
1578       if(hmdma->XferBufferCpltCallback != NULL)
1579       {
1580         /* Buffer transfer callback */
1581         hmdma->XferBufferCpltCallback(hmdma);
1582       }
1583     }
1584   }
1585 
1586   /* Block Transfer Complete Interrupt management ******************************/
1587   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U))
1588   {
1589     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U)
1590     {
1591       /* Clear the block transfer complete flag */
1592       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT);
1593 
1594       if(hmdma->XferBlockCpltCallback != NULL)
1595       {
1596         /* Block transfer callback */
1597         hmdma->XferBlockCpltCallback(hmdma);
1598       }
1599     }
1600   }
1601 
1602   /* Repeated Block Transfer Complete Interrupt management ******************************/
1603   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U))
1604   {
1605     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U)
1606     {
1607       /* Clear the repeat block transfer complete flag */
1608       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT);
1609 
1610       if(hmdma->XferRepeatBlockCpltCallback != NULL)
1611       {
1612         /* Repeated Block transfer callback */
1613         hmdma->XferRepeatBlockCpltCallback(hmdma);
1614       }
1615     }
1616   }
1617 
1618   /* Channel Transfer Complete Interrupt management ***********************************/
1619   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U))
1620   {
1621     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U)
1622     {
1623       /* Disable all the transfer interrupts */
1624       __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
1625 
1626       if(HAL_MDMA_STATE_ABORT == hmdma->State)
1627       {
1628         /* Process Unlocked */
1629         __HAL_UNLOCK(hmdma);
1630 
1631         /* Change the DMA state */
1632         hmdma->State = HAL_MDMA_STATE_READY;
1633 
1634         if(hmdma->XferAbortCallback != NULL)
1635         {
1636           hmdma->XferAbortCallback(hmdma);
1637         }
1638         return;
1639       }
1640 
1641       /* Clear the Channel Transfer Complete flag */
1642       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC);
1643 
1644       /* Process Unlocked */
1645       __HAL_UNLOCK(hmdma);
1646 
1647       /* Change MDMA peripheral state */
1648       hmdma->State = HAL_MDMA_STATE_READY;
1649 
1650       if(hmdma->XferCpltCallback != NULL)
1651       {
1652         /* Channel Transfer Complete callback */
1653         hmdma->XferCpltCallback(hmdma);
1654       }
1655     }
1656   }
1657 
1658   /* manage error case */
1659   if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE)
1660   {
1661     hmdma->State = HAL_MDMA_STATE_ABORT;
1662 
1663     /* Disable the channel */
1664     __HAL_MDMA_DISABLE(hmdma);
1665 
1666     do
1667     {
1668       if (++count > timeout)
1669       {
1670         break;
1671       }
1672     }
1673     while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U);
1674 
1675     /* Process Unlocked */
1676     __HAL_UNLOCK(hmdma);
1677 
1678     if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
1679     {
1680       /* Change the MDMA state to error if MDMA disable fails */
1681       hmdma->State = HAL_MDMA_STATE_ERROR;
1682     }
1683     else
1684     {
1685       /* Change the MDMA state to Ready if MDMA disable success */
1686       hmdma->State = HAL_MDMA_STATE_READY;
1687     }
1688 
1689 
1690     if (hmdma->XferErrorCallback != NULL)
1691     {
1692       /* Transfer error callback */
1693       hmdma->XferErrorCallback(hmdma);
1694     }
1695   }
1696 }
1697 
1698 /**
1699   * @}
1700   */
1701 
1702 /** @addtogroup MDMA_Exported_Functions_Group4
1703  *
1704 @verbatim
1705  ===============================================================================
1706                     ##### State and Errors functions #####
1707  ===============================================================================
1708     [..]
1709     This subsection provides functions allowing to
1710       (+) Check the MDMA state
1711       (+) Get error code
1712 
1713 @endverbatim
1714   * @{
1715   */
1716 
1717 /**
1718   * @brief  Returns the MDMA state.
1719   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1720   *               the configuration information for the specified MDMA Channel.
1721   * @retval HAL state
1722   */
1723 HAL_MDMA_StateTypeDef HAL_MDMA_GetState(MDMA_HandleTypeDef *hmdma)
1724 {
1725   return hmdma->State;
1726 }
1727 
1728 /**
1729   * @brief  Return the MDMA error code
1730   * @param  hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1731   *              the configuration information for the specified MDMA Channel.
1732   * @retval MDMA Error Code
1733   */
1734 uint32_t HAL_MDMA_GetError(MDMA_HandleTypeDef *hmdma)
1735 {
1736   return hmdma->ErrorCode;
1737 }
1738 
1739 /**
1740   * @}
1741   */
1742 
1743 /**
1744   * @}
1745   */
1746 
1747 /** @addtogroup MDMA_Private_Functions
1748   * @{
1749   */
1750 
1751 /**
1752   * @brief  Sets the MDMA Transfer parameter.
1753   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
1754   *                     the configuration information for the specified MDMA Channel.
1755   * @param  SrcAddress: The source memory Buffer address
1756   * @param  DstAddress: The destination memory Buffer address
1757   * @param  BlockDataLength : The length of a block transfer in bytes
1758   * @param  BlockCount: The number of blocks to be transferred
1759   * @retval HAL status
1760   */
1761 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1762 {
1763   uint32_t addressMask;
1764 
1765   /* Configure the MDMA Channel data length */
1766   MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT));
1767 
1768   /* Configure the MDMA block repeat count */
1769   MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC);
1770 
1771   /* Clear all interrupt flags */
1772   __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF);
1773 
1774   /* Configure MDMA Channel destination address */
1775   hmdma->Instance->CDAR = DstAddress;
1776 
1777   /* Configure MDMA Channel Source address */
1778   hmdma->Instance->CSAR = SrcAddress;
1779 
1780   addressMask = SrcAddress & 0xFF000000U;
1781   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
1782   {
1783     /*The AHBSbus is used as source (read operation) on channel x */
1784     hmdma->Instance->CTBR |= MDMA_CTBR_SBUS;
1785   }
1786   else
1787   {
1788     /*The AXI bus is used as source (read operation) on channel x */
1789     hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS);
1790   }
1791 
1792   addressMask = DstAddress & 0xFF000000U;
1793   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
1794   {
1795     /*The AHB bus is used as destination (write operation) on channel x */
1796     hmdma->Instance->CTBR |= MDMA_CTBR_DBUS;
1797   }
1798   else
1799   {
1800     /*The AXI bus is used as destination (write operation) on channel x */
1801     hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS);
1802   }
1803 
1804   /* Set the linked list register to the first node of the list */
1805   hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
1806 }
1807 
1808 /**
1809   * @brief  Initializes the MDMA handle according to the specified
1810   *         parameters in the MDMA_InitTypeDef
1811   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
1812   *                     the configuration information for the specified MDMA Channel.
1813   * @retval None
1814   */
1815 static void MDMA_Init(MDMA_HandleTypeDef *hmdma)
1816 {
1817   uint32_t blockoffset;
1818 
1819   /* Prepare the MDMA Channel configuration */
1820   hmdma->Instance->CCR = hmdma->Init.Priority  | hmdma->Init.Endianness;
1821 
1822   /* Write new CTCR Register value */
1823   hmdma->Instance->CTCR =  hmdma->Init.SourceInc      | hmdma->Init.DestinationInc | \
1824                            hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize   | \
1825                            hmdma->Init.DataAlignment  | hmdma->Init.SourceBurst    | \
1826                            hmdma->Init.DestBurst                                   | \
1827                            ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
1828                            hmdma->Init.TransferTriggerMode;
1829 
1830   /* If SW request set the CTCR register to SW Request Mode */
1831   if(hmdma->Init.Request == MDMA_REQUEST_SW)
1832   {
1833     /*
1834     -If the request is done by SW : BWM could be set to 1 or 0.
1835     -If the request is done by a peripheral :
1836     If mask address not set (0) => BWM must be set to 0
1837     If mask address set (different than 0) => BWM could be set to 1 or 0
1838     */
1839     hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM);
1840   }
1841 
1842   /* Reset CBNDTR Register */
1843   hmdma->Instance->CBNDTR = 0;
1844 
1845   /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
1846   if(hmdma->Init.SourceBlockAddressOffset < 0)
1847   {
1848     hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM;
1849     /* Write new CBRUR Register value : source repeat block offset */
1850     blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset);
1851     hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU);
1852   }
1853   else
1854   {
1855     /* Write new CBRUR Register value : source repeat block offset */
1856     hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
1857   }
1858 
1859   /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
1860   if(hmdma->Init.DestBlockAddressOffset < 0)
1861   {
1862     hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM;
1863     /* Write new CBRUR Register value : destination repeat block offset */
1864     blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset);
1865     hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
1866   }
1867   else
1868   {
1869     /*write new CBRUR Register value : destination repeat block offset */
1870     hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
1871   }
1872 
1873   /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
1874   if(hmdma->Init.Request != MDMA_REQUEST_SW)
1875   {
1876     /* Set the HW request in CTRB register  */
1877     hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL;
1878   }
1879   else /* SW request : reset the CTBR register */
1880   {
1881     hmdma->Instance->CTBR = 0;
1882   }
1883 
1884   /* Write Link Address Register */
1885   hmdma->Instance->CLAR =  0;
1886 }
1887 
1888 /**
1889   * @}
1890   */
1891 
1892 #endif /* HAL_MDMA_MODULE_ENABLED */
1893 /**
1894   * @}
1895   */
1896 
1897 /**
1898   * @}
1899   */
1900