1 /**
2   ******************************************************************************
3   * @file    stm32mp1xx_hal_mdma.c
4   * @author  MCD Application Team
5   * @brief  This file provides firmware functions to manage the following
6   *         functionalities of the Master Direct Memory Access (MDMA) peripheral:
7   *           + Initialization/de-initialization functions
8   *           + I/O operation functions
9   *           + Peripheral State and errors functions
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2019 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file
17   * in the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21   @verbatim
22   ==============================================================================
23                         ##### How to use this driver #####
24   ==============================================================================
25   [..]
26    (#) Enable and configure the peripheral to be connected to the MDMA Channel
27        (except for internal SRAM/FLASH memories: no initialization is
28        necessary) please refer to Reference manual for connection between peripherals
29        and MDMA requests.
30 
31    (#)
32        For a given Channel use HAL_MDMA_Init function to program the required configuration through the following parameters:
33        transfer request , channel priority, data endianness, Source increment, destination increment ,
34        source data size, destination data size, data alignment, source Burst, destination Burst ,
35        buffer Transfer Length, Transfer Trigger Mode (buffer transfer, block transfer, repeated block transfer
36        or full transfer) source and destination block address offset, mask address and data.
37 
38        If using the MDMA in linked list mode then use function HAL_MDMA_LinkedList_CreateNode to fill a transfer node.
39        Note that parameters given to the function HAL_MDMA_Init corresponds always to the node zero.
40        Use function HAL_MDMA_LinkedList_AddNode to connect the created node to the linked list at a given position.
41        User can make a linked list circular using function HAL_MDMA_LinkedList_EnableCircularMode , this function will automatically connect the
42        last node of the list to the first one in order to make the list circular.
43        In this case the linked list will loop on node 1 : first node connected after the initial transfer defined by the HAL_MDMA_Init
44 
45       -@-   The initial transfer itself (node 0 corresponding to the Init).
46             User can disable the circular mode using function HAL_MDMA_LinkedList_DisableCircularMode, this function will then remove
47             the connection between last node and first one.
48 
49        Function HAL_MDMA_LinkedList_RemoveNode can be used to remove (disconnect) a node from the transfer linked list.
50        When a linked list is circular (last node connected to first one), if removing node1  (node where the linked list loops),
51        the linked list remains circular and node 2 becomes the first one.
52        Note that if the linked list is made circular the transfer will loop infinitely (or until aborted by the user).
53 
54     [..]
55        (+) User can select the transfer trigger mode (parameter TransferTriggerMode) to define the amount of data to be
56            transfer upon a request :
57              (++) MDMA_BUFFER_TRANSFER : each request triggers a transfer of BufferTransferLength data
58                with BufferTransferLength defined within the HAL_MDMA_Init.
59              (++) MDMA_BLOCK_TRANSFER : each request triggers a transfer of a block
60                with block size defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
61                or within the current linked list node parameters.
62              (++) MDMA_REPEAT_BLOCK_TRANSFER : each request triggers a transfer of a number of blocks
63                with block size and number of blocks defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
64                or within the current linked list node parameters.
65              (++) MDMA_FULL_TRANSFER : each request triggers a full transfer
66               all blocks and all nodes(if a linked list has been created using HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode).
67 
68      *** Polling mode IO operation ***
69      =================================
70     [..]
71           (+) Use HAL_MDMA_Start() to start MDMA transfer after the configuration of Source
72               address and destination address and the Length of data to be transferred.
73           (+) Use HAL_MDMA_PollForTransfer() to poll for the end of current transfer or a transfer level
74              In this case a fixed Timeout can be configured by User depending from his application.
75           (+) Use HAL_MDMA_Abort() function to abort the current transfer : blocking method this API returns
76               when the abort ends or timeout (should not be called from an interrupt service routine).
77 
78      *** Interrupt mode IO operation ***
79      ===================================
80     [..]
81           (+) Configure the MDMA interrupt priority using HAL_NVIC_SetPriority()
82           (+) Enable the MDMA IRQ handler using HAL_NVIC_EnableIRQ()
83           (+) Use HAL_MDMA_Start_IT() to start MDMA transfer after the configuration of
84               Source address and destination address and the Length of data to be transferred. In this
85               case the MDMA interrupt is configured.
86           (+) Use HAL_MDMA_IRQHandler() called under MDMA_IRQHandler() Interrupt subroutine
87           (+) At the end of data transfer HAL_MDMA_IRQHandler() function is executed and user can
88               add his own function by customization of function pointer XferCpltCallback and
89               XferErrorCallback (i.e a member of MDMA handle structure).
90 
91           (+) Use HAL_MDMA_Abort_IT() function to abort the current transfer : non-blocking method. This API will finish the execution immediately
92               then the callback XferAbortCallback (if specified  by the user) is asserted once the MDMA channel has effectively aborted.
93               (could be called from an interrupt service routine).
94 
95           (+) Use functions HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback respectevely to register unregister user callbacks
96               from the following list :
97               (++) XferCpltCallback            : transfer complete callback.
98               (++) XferBufferCpltCallback      : buffer transfer complete callback.
99               (++) XferBlockCpltCallback       : block transfer complete callback.
100               (++) XferRepeatBlockCpltCallback : repeated block transfer complete callback.
101               (++) XferErrorCallback           : transfer error callback.
102               (++) XferAbortCallback           : transfer abort complete callback.
103 
104     [..]
105          (+)  If the transfer Request corresponds to SW request (MDMA_REQUEST_SW) User can use function HAL_MDMA_GenerateSWRequest to
106               trigger requests manually. Function HAL_MDMA_GenerateSWRequest must be used with the following precautions:
107               (++) This function returns an error if used while the Transfer has ended or not started.
108               (++) If used while the current request has not been served yet (current request transfer on going)
109                 this function returns an error and the new request is ignored.
110 
111               Generally this function should be used in conjunctions with the MDMA callbacks:
112               (++) example 1:
113                  (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BUFFER_TRANSFER
114                  (+++) Register a callback for buffer transfer complete (using callback ID set to HAL_MDMA_XFER_BUFFERCPLT_CB_ID)
115                  (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first BufferTransferLength data.
116                  (+++) When the buffer transfer complete callback is asserted first buffer has been transferred and user can ask for a new buffer transfer
117                    request using HAL_MDMA_GenerateSWRequest.
118 
119               (++) example 2:
120                  (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BLOCK_TRANSFER
121                  (+++) Register a callback for block transfer complete (using callback ID HAL_MDMA_XFER_BLOCKCPLT_CB_ID)
122                  (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first block of data.
123                  (+++) When the block transfer complete callback is asserted the first block has been transferred and user can ask
124                    for a new block transfer request using HAL_MDMA_GenerateSWRequest.
125 
126     [..]  Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection.
127 
128      *** MDMA HAL driver macros list ***
129      =============================================
130      [..]
131        Below the list of most used macros in MDMA HAL driver.
132 
133       (+) __HAL_MDMA_ENABLE: Enable the specified MDMA Channel.
134       (+) __HAL_MDMA_DISABLE: Disable the specified MDMA Channel.
135       (+) __HAL_MDMA_GET_FLAG: Get the MDMA Channel pending flags.
136       (+) __HAL_MDMA_CLEAR_FLAG: Clear the MDMA Channel pending flags.
137       (+) __HAL_MDMA_ENABLE_IT: Enable the specified MDMA Channel interrupts.
138       (+) __HAL_MDMA_DISABLE_IT: Disable the specified MDMA Channel interrupts.
139       (+) __HAL_MDMA_GET_IT_SOURCE: Check whether the specified MDMA Channel interrupt has occurred or not.
140 
141      [..]
142       (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
143 
144     [..]
145 
146     @endverbatim
147   ******************************************************************************
148   */
149 
150 /* Includes ------------------------------------------------------------------*/
151 #include "stm32mp1xx_hal.h"
152 
153 /** @addtogroup STM32MP1xx_HAL_Driver
154   * @{
155   */
156 
157 /** @defgroup MDMA  MDMA
158   * @brief MDMA HAL module driver
159   * @{
160   */
161 
162 #ifdef HAL_MDMA_MODULE_ENABLED
163 
164 /* Private typedef -----------------------------------------------------------*/
165 /* Private constants ---------------------------------------------------------*/
166 /** @addtogroup MDMA_Private_Constants
167  * @{
168  */
169 #define HAL_TIMEOUT_MDMA_ABORT    5U    /* 5 ms */
170 #define HAL_MDMA_CHANNEL_SIZE     0x40U /* an MDMA instance channel size is 64 byte  */
171 /**
172   * @}
173   */
174 /* Private macro -------------------------------------------------------------*/
175 /* Private variables ---------------------------------------------------------*/
176 /* Private function prototypes -----------------------------------------------*/
177 /** @addtogroup MDMA_Private_Functions_Prototypes
178   * @{
179   */
180 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount);
181 static void MDMA_Init(MDMA_HandleTypeDef *hmdma);
182 
183 /**
184   * @}
185   */
186 
187 /** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
188   * @{
189   */
190 
191 /** @addtogroup MDMA_Exported_Functions_Group1
192   *
193 @verbatim
194  ===============================================================================
195              ##### Initialization and de-initialization functions  #####
196  ===============================================================================
197     [..]
198     This section provides functions allowing to :
199       Initialize and de-initialize the MDMA channel.
200       Register and Unregister MDMA callbacks
201     [..]
202     The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in
203     reference manual.
204     The HAL_MDMA_DeInit function allows to deinitialize the MDMA channel.
205     HAL_MDMA_RegisterCallback and  HAL_MDMA_UnRegisterCallback functions allows
206     respectevely to register/unregister an MDMA callback function.
207 
208 @endverbatim
209   * @{
210   */
211 
212 /**
213   * @brief  Initializes the MDMA according to the specified
214   *         parameters in the MDMA_InitTypeDef and create the associated handle.
215   * @param  hmdma: Pointer to a MDMA_HandleTypeDef structure that contains
216   *               the configuration information for the specified MDMA Channel.
217   * @retval HAL status
218   */
HAL_MDMA_Init(MDMA_HandleTypeDef * hmdma)219 HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
220 {
221   uint32_t tickstart = HAL_GetTick();
222 
223   /* Check the MDMA peripheral handle */
224   if(hmdma == NULL)
225   {
226     return HAL_ERROR;
227   }
228 
229   /* Check the parameters */
230   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
231   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
232   assert_param(IS_MDMA_SECURE_MODE(hmdma->Init.SecureMode));
233   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));
234   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
235   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
236   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
237   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
238   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
239   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
240   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
241   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
242   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));
243   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
244   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
245   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
246 
247 
248   /* Allocate lock resource */
249   __HAL_UNLOCK(hmdma);
250 
251   if(hmdma->State == HAL_MDMA_STATE_RESET)
252   {
253     /* Init the low level hardware : GPIO, CLOCK */
254     HAL_MDMA_MspInit(hmdma);
255   }
256 
257   /* Change MDMA peripheral state */
258   hmdma->State = HAL_MDMA_STATE_BUSY;
259 
260   /* Disable the MDMA channel */
261   __HAL_MDMA_DISABLE(hmdma);
262 
263   /* Check if the MDMA channel is effectively disabled */
264   while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
265   {
266     /* Check for the Timeout */
267     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
268     {
269       /* Update error code */
270       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
271 
272       /* Change the MDMA state */
273       hmdma->State = HAL_MDMA_STATE_ERROR;
274 
275       return HAL_ERROR;
276     }
277   }
278 
279   /* Initialize the MDMA channel registers */
280   MDMA_Init(hmdma);
281 
282   /* Reset the MDMA first/last linkedlist node addresses and node counter */
283   hmdma->FirstLinkedListNodeAddress  = 0;
284   hmdma->LastLinkedListNodeAddress   = 0;
285   hmdma->LinkedListNodeCounter  = 0;
286 
287   /* Initialize the error code */
288   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
289 
290   /* Initialize the MDMA state */
291   hmdma->State = HAL_MDMA_STATE_READY;
292 
293   return HAL_OK;
294 }
295 
296 /**
297   * @brief  DeInitializes the MDMA peripheral
298   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
299   *               the configuration information for the specified MDMA Channel.
300   * @retval HAL status
301   */
HAL_MDMA_DeInit(MDMA_HandleTypeDef * hmdma)302 HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma)
303 {
304 
305   /* Check the MDMA peripheral handle */
306   if(hmdma == NULL)
307   {
308     return HAL_ERROR;
309   }
310 
311   /* Disable the selected MDMA Channelx */
312   __HAL_MDMA_DISABLE(hmdma);
313 
314   /* Reset MDMA Channel control register */
315   hmdma->Instance->CCR  = 0;
316   hmdma->Instance->CTCR = 0;
317   hmdma->Instance->CBNDTR = 0;
318   hmdma->Instance->CSAR = 0;
319   hmdma->Instance->CDAR = 0;
320   hmdma->Instance->CBRUR = 0;
321   hmdma->Instance->CLAR = 0;
322   hmdma->Instance->CTBR = 0;
323   hmdma->Instance->CMAR = 0;
324   hmdma->Instance->CMDR = 0;
325 
326   /* Clear all flags */
327   __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC));
328 
329   /* DeInit the low level hardware */
330   HAL_MDMA_MspDeInit(hmdma);
331 
332   /* Reset the  MDMA first/last linkedlist node addresses and node counter */
333   hmdma->FirstLinkedListNodeAddress  = 0;
334   hmdma->LastLinkedListNodeAddress   = 0;
335   hmdma->LinkedListNodeCounter  = 0;
336 
337   /* Initialize the error code */
338   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
339 
340   /* Initialize the MDMA state */
341   hmdma->State = HAL_MDMA_STATE_RESET;
342 
343   /* Release Lock */
344   __HAL_UNLOCK(hmdma);
345 
346   return HAL_OK;
347 }
348 
349 /**
350   * @brief  Config the Post request Mask address and Mask data
351   * @param  hmdma      : pointer to a MDMA_HandleTypeDef structure that contains
352   *                               the configuration information for the specified MDMA Channel.
353   * @param  MaskAddress: specifies the address to be updated (written) with MaskData after a request is served.
354   * @param  MaskData:    specifies the value to be written to MaskAddress after a request is served.
355   *                      MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served.
356   * @retval HAL status
357   */
HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef * hmdma,uint32_t MaskAddress,uint32_t MaskData)358 HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData)
359 {
360   HAL_StatusTypeDef  status = HAL_OK;
361 
362   /* Check the MDMA peripheral handle */
363   if(hmdma == NULL)
364   {
365     return HAL_ERROR;
366   }
367 
368   /* Process locked */
369   __HAL_LOCK(hmdma);
370 
371   if(HAL_MDMA_STATE_READY == hmdma->State)
372   {
373     /* if HW request set Post Request MaskAddress and MaskData,  */
374     if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U)
375     {
376       /* Set the HW request clear Mask and Data */
377       hmdma->Instance->CMAR = MaskAddress;
378       hmdma->Instance->CMDR = MaskData;
379 
380       /*
381       -If the request is done by SW : BWM could be set to 1 or 0.
382       -If the request is done by a peripheral :
383          If mask address not set (0) => BWM must be set to 0
384          If mask address set (different than 0) => BWM could be set to 1 or 0
385       */
386       if(MaskAddress == 0U)
387       {
388         hmdma->Instance->CTCR &=  ~MDMA_CTCR_BWM;
389       }
390       else
391       {
392         hmdma->Instance->CTCR |=  MDMA_CTCR_BWM;
393       }
394     }
395     else
396     {
397       /* Return error status */
398       status =  HAL_ERROR;
399     }
400   }
401   else
402   {
403     /* Return error status */
404     status =  HAL_ERROR;
405   }
406   /* Release Lock */
407   __HAL_UNLOCK(hmdma);
408 
409   return status;
410 }
411 
412 /**
413   * @brief  Register callbacks
414   * @param  hmdma:                pointer to a MDMA_HandleTypeDef structure that contains
415   *                               the configuration information for the specified MDMA Channel.
416   * @param  CallbackID:           User Callback identifier
417   * @param  pCallback:            pointer to callbacsk function.
418   * @retval HAL status
419   */
HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef * hmdma,HAL_MDMA_CallbackIDTypeDef CallbackID,void (* pCallback)(MDMA_HandleTypeDef * _hmdma))420 HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma))
421 {
422   HAL_StatusTypeDef status = HAL_OK;
423 
424   /* Check the MDMA peripheral handle */
425   if(hmdma == NULL)
426   {
427     return HAL_ERROR;
428   }
429 
430   /* Process locked */
431   __HAL_LOCK(hmdma);
432 
433   if(HAL_MDMA_STATE_READY == hmdma->State)
434   {
435     switch (CallbackID)
436     {
437     case  HAL_MDMA_XFER_CPLT_CB_ID:
438       hmdma->XferCpltCallback = pCallback;
439       break;
440 
441     case  HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
442       hmdma->XferBufferCpltCallback = pCallback;
443       break;
444 
445     case  HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
446       hmdma->XferBlockCpltCallback = pCallback;
447       break;
448 
449     case  HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
450       hmdma->XferRepeatBlockCpltCallback = pCallback;
451       break;
452 
453     case  HAL_MDMA_XFER_ERROR_CB_ID:
454       hmdma->XferErrorCallback = pCallback;
455       break;
456 
457     case  HAL_MDMA_XFER_ABORT_CB_ID:
458       hmdma->XferAbortCallback = pCallback;
459       break;
460 
461     default:
462       break;
463     }
464   }
465   else
466   {
467     /* Return error status */
468     status =  HAL_ERROR;
469   }
470 
471   /* Release Lock */
472   __HAL_UNLOCK(hmdma);
473 
474   return status;
475 }
476 
477 /**
478   * @brief  UnRegister callbacks
479   * @param  hmdma:                 pointer to a MDMA_HandleTypeDef structure that contains
480   *                               the configuration information for the specified MDMA Channel.
481   * @param  CallbackID:           User Callback identifier
482   *                               a HAL_MDMA_CallbackIDTypeDef ENUM as parameter.
483   * @retval HAL status
484   */
HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef * hmdma,HAL_MDMA_CallbackIDTypeDef CallbackID)485 HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID)
486 {
487   HAL_StatusTypeDef status = HAL_OK;
488 
489   /* Check the MDMA peripheral handle */
490   if(hmdma == NULL)
491   {
492     return HAL_ERROR;
493   }
494 
495   /* Process locked */
496   __HAL_LOCK(hmdma);
497 
498   if(HAL_MDMA_STATE_READY == hmdma->State)
499   {
500     switch (CallbackID)
501     {
502     case  HAL_MDMA_XFER_CPLT_CB_ID:
503       hmdma->XferCpltCallback = NULL;
504       break;
505 
506     case  HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
507       hmdma->XferBufferCpltCallback = NULL;
508       break;
509 
510     case  HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
511       hmdma->XferBlockCpltCallback = NULL;
512       break;
513 
514     case  HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
515       hmdma->XferRepeatBlockCpltCallback = NULL;
516       break;
517 
518     case  HAL_MDMA_XFER_ERROR_CB_ID:
519       hmdma->XferErrorCallback = NULL;
520       break;
521 
522     case  HAL_MDMA_XFER_ABORT_CB_ID:
523       hmdma->XferAbortCallback = NULL;
524       break;
525 
526     case   HAL_MDMA_XFER_ALL_CB_ID:
527       hmdma->XferCpltCallback = NULL;
528       hmdma->XferBufferCpltCallback = NULL;
529       hmdma->XferBlockCpltCallback = NULL;
530       hmdma->XferRepeatBlockCpltCallback = NULL;
531       hmdma->XferErrorCallback = NULL;
532       hmdma->XferAbortCallback = NULL;
533       break;
534 
535     default:
536       status = HAL_ERROR;
537       break;
538     }
539   }
540   else
541   {
542     status = HAL_ERROR;
543   }
544 
545   /* Release Lock */
546   __HAL_UNLOCK(hmdma);
547 
548   return status;
549 }
550 
551 /**
552   * @}
553   */
554 
555 /** @addtogroup MDMA_Exported_Functions_Group2
556  *
557 @verbatim
558  ===============================================================================
559                       #####  Linked list operation functions  #####
560  ===============================================================================
561     [..]  This section provides functions allowing to:
562       (+) Create a linked list node
563       (+) Add a node to the MDMA linked list
564       (+) Remove a node from the MDMA linked list
565       (+) Enable/Disable linked list circular mode
566 @endverbatim
567   * @{
568   */
569 
570 /**
571   * @brief  Initializes an MDMA Link Node according to the specified
572   *         parameters in the pMDMA_LinkedListNodeConfig .
573   * @param  pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
574   *         registers configurations.
575   * @param  pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains
576   *               the configuration information for the specified MDMA Linked List Node.
577   * @retval HAL status
578   */
HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef * pNode,MDMA_LinkNodeConfTypeDef * pNodeConfig)579 HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig)
580 {
581   uint32_t addressMask;
582   uint32_t blockoffset;
583 
584   /* Check the MDMA peripheral state */
585   if((pNode == NULL) || (pNodeConfig == NULL))
586   {
587     return HAL_ERROR;
588   }
589 
590   /* Check the parameters */
591   assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority));
592   assert_param(IS_MDMA_SECURE_MODE(pNodeConfig->Init.SecureMode));
593   assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness));
594   assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request));
595   assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc));
596   assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc));
597   assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize));
598   assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize));
599   assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment));
600   assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst));
601   assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst));
602   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength));
603   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode));
604   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset));
605   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset));
606 
607   assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength));
608   assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount));
609 
610 
611   /* Configure next Link node Address Register to zero */
612   pNode->CLAR =  0;
613 
614   /* Configure the Link Node registers*/
615   pNode->CTBR   = 0;
616   pNode->CMAR   = 0;
617   pNode->CMDR   = 0;
618   pNode->Reserved = 0;
619 
620   /* Write new CTCR Register value */
621   pNode->CTCR =  pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \
622     pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize           | \
623       pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst            | \
624         pNodeConfig->Init.DestBurst                                             | \
625           ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
626             pNodeConfig->Init.TransferTriggerMode;
627 
628   /* If SW request set the CTCR register to SW Request Mode*/
629   if(pNodeConfig->Init.Request == MDMA_REQUEST_SW)
630   {
631     pNode->CTCR |= MDMA_CTCR_SWRM;
632   }
633 
634   /*
635   -If the request is done by SW : BWM could be set to 1 or 0.
636   -If the request is done by a peripheral :
637      If mask address not set (0) => BWM must be set to 0
638      If mask address set (different than 0) => BWM could be set to 1 or 0
639   */
640   if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U))
641   {
642     pNode->CTCR |=  MDMA_CTCR_BWM;
643   }
644 
645   /* Set the new CBNDTR Register value */
646   pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC;
647 
648   /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
649   if(pNodeConfig->Init.SourceBlockAddressOffset < 0)
650   {
651     pNode->CBNDTR |= MDMA_CBNDTR_BRSUM;
652     /*write new CBRUR Register value : source repeat block offset */
653     blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset);
654     pNode->CBRUR = blockoffset & 0x0000FFFFU;
655   }
656   else
657   {
658     /*write new CBRUR Register value : source repeat block offset */
659     pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
660   }
661 
662   /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
663   if(pNodeConfig->Init.DestBlockAddressOffset < 0)
664   {
665     pNode->CBNDTR |= MDMA_CBNDTR_BRDUM;
666     /*write new CBRUR Register value : destination repeat block offset */
667     blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset);
668     pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
669   }
670   else
671   {
672     /*write new CBRUR Register value : destination repeat block offset */
673     pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
674   }
675 
676   /* Configure MDMA Link Node data length */
677   pNode->CBNDTR |=  pNodeConfig->BlockDataLength;
678 
679   /* Configure MDMA Link Node destination address */
680   pNode->CDAR = pNodeConfig->DstAddress;
681 
682   /* Configure MDMA Link Node Source address */
683   pNode->CSAR = pNodeConfig->SrcAddress;
684 
685   /* if HW request set the HW request and the requet CleraMask and ClearData MaskData,  */
686   if(pNodeConfig->Init.Request != MDMA_REQUEST_SW)
687   {
688     /* Set the HW request in CTBR register  */
689     pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL;
690     /* Set the HW request clear Mask and Data */
691     pNode->CMAR = pNodeConfig->PostRequestMaskAddress;
692     pNode->CMDR = pNodeConfig->PostRequestMaskData;
693   }
694 
695   addressMask = pNodeConfig->SrcAddress & 0xFF000000U;
696   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
697   {
698     /*The AHBSbus is used as source (read operation) on channel x */
699     pNode->CTBR |= MDMA_CTBR_SBUS;
700   }
701 
702   addressMask = pNodeConfig->DstAddress & 0xFF000000U;
703   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
704   {
705     /*The AHB bus is used as destination (write operation) on channel x */
706     pNode->CTBR |= MDMA_CTBR_DBUS;
707   }
708 
709   return HAL_OK;
710 }
711 
712 /**
713   * @brief  Connect a node to the linked list.
714   * @param  hmdma    : Pointer to a MDMA_HandleTypeDef structure that contains
715   *                    the configuration information for the specified MDMA Channel.
716   * @param  pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
717   *                    to be add to the list.
718   * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
719   *                    at the end of the list
720   *
721   * @retval HAL status
722   */
HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef * hmdma,MDMA_LinkNodeTypeDef * pNewNode,MDMA_LinkNodeTypeDef * pPrevNode)723 HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
724 {
725   MDMA_LinkNodeTypeDef *pNode;
726   uint32_t counter = 0, nodeInserted = 0;
727   HAL_StatusTypeDef hal_status = HAL_OK;
728 
729   /* Check the MDMA peripheral handle */
730   if((hmdma == NULL) || (pNewNode == NULL))
731   {
732     return HAL_ERROR;
733   }
734 
735   /* Process locked */
736   __HAL_LOCK(hmdma);
737 
738   if(HAL_MDMA_STATE_READY == hmdma->State)
739   {
740     /* Change MDMA peripheral state */
741     hmdma->State = HAL_MDMA_STATE_BUSY;
742 
743     /* Check if this is the first node (after the Inititlization node) */
744     if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U)
745     {
746       if(pPrevNode == NULL)
747       {
748         /* if this is the first node after the initialization
749         connect this node to the node 0 by updating
750         the MDMA channel CLAR register to this node address */
751         hmdma->Instance->CLAR = (uint32_t)pNewNode;
752         /* Set the MDMA handle First linked List node*/
753         hmdma->FirstLinkedListNodeAddress = pNewNode;
754 
755         /*reset New node link */
756         pNewNode->CLAR = 0;
757 
758         /* Update the Handle last node address */
759         hmdma->LastLinkedListNodeAddress = pNewNode;
760 
761         hmdma->LinkedListNodeCounter = 1;
762       }
763       else
764       {
765         hal_status = HAL_ERROR;
766       }
767     }
768     else if(hmdma->FirstLinkedListNodeAddress != pNewNode)
769     {
770       /* Check if the node to insert already exists*/
771       pNode = hmdma->FirstLinkedListNodeAddress;
772       while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
773       {
774         if(pNode->CLAR == (uint32_t)pNewNode)
775         {
776           hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
777         }
778         pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
779         counter++;
780       }
781 
782       if(hal_status == HAL_OK)
783       {
784         /* Check if the previous node is the last one in the current list or zero */
785         if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL))
786         {
787           /* insert the new node at the end of the list */
788           pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;
789           hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
790           /* Update the Handle last node address */
791           hmdma->LastLinkedListNodeAddress = pNewNode;
792           /* Increment the linked list node counter */
793           hmdma->LinkedListNodeCounter++;
794         }
795         else
796         {
797           /*insert the new node after the pPreviousNode node */
798           pNode = hmdma->FirstLinkedListNodeAddress;
799           counter = 0;
800           while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U))
801           {
802             counter++;
803             if(pNode == pPrevNode)
804             {
805               /*Insert the new node after the previous one */
806               pNewNode->CLAR = pNode->CLAR;
807               pNode->CLAR = (uint32_t)pNewNode;
808               /* Increment the linked list node counter */
809               hmdma->LinkedListNodeCounter++;
810               nodeInserted = 1;
811             }
812             else
813             {
814               pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
815             }
816           }
817 
818           if(nodeInserted == 0U)
819           {
820             hal_status = HAL_ERROR;
821           }
822         }
823       }
824     }
825     else
826     {
827       hal_status = HAL_ERROR;
828     }
829 
830     /* Process unlocked */
831     __HAL_UNLOCK(hmdma);
832 
833     hmdma->State = HAL_MDMA_STATE_READY;
834 
835     return hal_status;
836   }
837   else
838   {
839     /* Process unlocked */
840     __HAL_UNLOCK(hmdma);
841 
842     /* Return error status */
843     return HAL_BUSY;
844   }
845 }
846 
847 /**
848   * @brief  Disconnect/Remove a node from the transfer linked list.
849   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
850   *                 the configuration information for the specified MDMA Channel.
851   * @param  pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
852   *                 to be removed from the list.
853   *
854   * @retval HAL status
855   */
HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef * hmdma,MDMA_LinkNodeTypeDef * pNode)856 HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode)
857 {
858   MDMA_LinkNodeTypeDef *ptmpNode;
859   uint32_t counter = 0, nodeDeleted = 0;
860   HAL_StatusTypeDef hal_status = HAL_OK;
861 
862   /* Check the MDMA peripheral handle */
863   if((hmdma == NULL) || (pNode == NULL))
864   {
865     return HAL_ERROR;
866   }
867 
868   /* Process locked */
869   __HAL_LOCK(hmdma);
870 
871   if(HAL_MDMA_STATE_READY == hmdma->State)
872   {
873     /* Change MDMA peripheral state */
874     hmdma->State = HAL_MDMA_STATE_BUSY;
875 
876     /* If first and last node are null (no nodes in the list) : return error*/
877     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
878     {
879       hal_status = HAL_ERROR;
880     }
881     else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */
882     {
883       /* Delete 1st node */
884       if(hmdma->LastLinkedListNodeAddress == pNode)
885       {
886         /*if the last node is at the same time the first one (1 single node after the init node 0)
887         then update the last node too */
888 
889         hmdma->FirstLinkedListNodeAddress = 0;
890         hmdma->LastLinkedListNodeAddress  = 0;
891         hmdma->LinkedListNodeCounter = 0;
892 
893         hmdma->Instance->CLAR = 0;
894       }
895       else
896       {
897         if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR)
898         {
899           /* if last node is looping to first (circular list) one update the last node connection */
900           hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR;
901         }
902 
903         /* if deleting the first node after the initialization
904         connect the next node to the node 0 by updating
905         the MDMA channel CLAR register to this node address */
906         hmdma->Instance->CLAR = pNode->CLAR;
907         hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR;
908         /* Update the Handle node counter */
909         hmdma->LinkedListNodeCounter--;
910       }
911     }
912     else /* Deleting any other node */
913     {
914       /*Deleted node is not the first one : find it  */
915       ptmpNode = hmdma->FirstLinkedListNodeAddress;
916       while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U))
917       {
918         counter++;
919         if(ptmpNode->CLAR == ((uint32_t)pNode))
920         {
921           /* if deleting the last node */
922           if(pNode == hmdma->LastLinkedListNodeAddress)
923           {
924             /*Update the linked list last node address in the handle*/
925             hmdma->LastLinkedListNodeAddress = ptmpNode;
926           }
927           /* update the next node link after deleting pMDMA_LinkedListNode */
928           ptmpNode->CLAR = pNode->CLAR;
929           nodeDeleted = 1;
930           /* Update the Handle node counter */
931           hmdma->LinkedListNodeCounter--;
932         }
933         else
934         {
935           ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR;
936         }
937       }
938 
939       if(nodeDeleted == 0U)
940       {
941         /* last node reashed without finding the node to delete : return error */
942         hal_status = HAL_ERROR;
943       }
944     }
945 
946     /* Process unlocked */
947     __HAL_UNLOCK(hmdma);
948 
949     hmdma->State = HAL_MDMA_STATE_READY;
950 
951     return hal_status;
952   }
953   else
954   {
955     /* Process unlocked */
956     __HAL_UNLOCK(hmdma);
957 
958     /* Return error status */
959     return HAL_BUSY;
960   }
961 }
962 
963 /**
964   * @brief  Make the linked list circular by connecting the last node to the first.
965   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
966   *                 the configuration information for the specified MDMA Channel.
967   * @retval HAL status
968   */
HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef * hmdma)969 HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
970 {
971   HAL_StatusTypeDef hal_status = HAL_OK;
972 
973   /* Check the MDMA peripheral handle */
974   if(hmdma == NULL)
975   {
976     return HAL_ERROR;
977   }
978 
979   /* Process locked */
980   __HAL_LOCK(hmdma);
981 
982   if(HAL_MDMA_STATE_READY == hmdma->State)
983   {
984     /* Change MDMA peripheral state */
985     hmdma->State = HAL_MDMA_STATE_BUSY;
986 
987     /* If first and last node are null (no nodes in the list) : return error*/
988     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
989     {
990       hal_status = HAL_ERROR;
991     }
992     else
993     {
994       /* to enable circular mode Last Node should be connected to first node */
995       hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
996     }
997 
998   }
999   /* Process unlocked */
1000   __HAL_UNLOCK(hmdma);
1001 
1002   hmdma->State = HAL_MDMA_STATE_READY;
1003 
1004   return hal_status;
1005 }
1006 
1007 /**
1008   * @brief  Disable the linked list circular mode by setting the last node connection to null
1009   * @param  hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
1010   *                 the configuration information for the specified MDMA Channel.
1011   * @retval HAL status
1012   */
HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef * hmdma)1013 HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma)
1014 {
1015   HAL_StatusTypeDef hal_status = HAL_OK;
1016 
1017   /* Check the MDMA peripheral handle */
1018   if(hmdma == NULL)
1019   {
1020     return HAL_ERROR;
1021   }
1022 
1023   /* Process locked */
1024   __HAL_LOCK(hmdma);
1025 
1026   if(HAL_MDMA_STATE_READY == hmdma->State)
1027   {
1028     /* Change MDMA peripheral state */
1029     hmdma->State = HAL_MDMA_STATE_BUSY;
1030 
1031     /* If first and last node are null (no nodes in the list) : return error*/
1032     if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
1033     {
1034       hal_status = HAL_ERROR;
1035     }
1036     else
1037     {
1038       /* to disable circular mode Last Node should be connected to NULL */
1039       hmdma->LastLinkedListNodeAddress->CLAR = 0;
1040     }
1041 
1042   }
1043   /* Process unlocked */
1044   __HAL_UNLOCK(hmdma);
1045 
1046   hmdma->State = HAL_MDMA_STATE_READY;
1047 
1048   return hal_status;
1049 }
1050 
1051 /**
1052   * @}
1053   */
1054 
1055 /** @addtogroup MDMA_Exported_Functions_Group3
1056  *
1057 @verbatim
1058  ===============================================================================
1059                       #####  IO operation functions  #####
1060  ===============================================================================
1061     [..]  This section provides functions allowing to:
1062       (+) Configure the source, destination address and data length and Start MDMA transfer
1063       (+) Configure the source, destination address and data length and
1064           Start MDMA transfer with interrupt
1065       (+) Abort MDMA transfer
1066       (+) Poll for transfer complete
1067       (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW)
1068       (+) Handle MDMA interrupt request
1069 
1070 @endverbatim
1071   * @{
1072   */
1073 
1074 /**
1075   * @brief  Starts the MDMA Transfer.
1076   * @param  hmdma           : pointer to a MDMA_HandleTypeDef structure that contains
1077   *                           the configuration information for the specified MDMA Channel.
1078   * @param  SrcAddress      : The source memory Buffer address
1079   * @param  DstAddress      : The destination memory Buffer address
1080   * @param  BlockDataLength : The length of a block transfer in bytes
1081   * @param  BlockCount      : The number of a blocks to be transfer
1082   * @retval HAL status
1083   */
HAL_MDMA_Start(MDMA_HandleTypeDef * hmdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t BlockDataLength,uint32_t BlockCount)1084 HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1085 {
1086   /* Check the parameters */
1087   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1088   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
1089 
1090   /* Check the MDMA peripheral handle */
1091   if(hmdma == NULL)
1092   {
1093     return HAL_ERROR;
1094   }
1095 
1096   /* Process locked */
1097   __HAL_LOCK(hmdma);
1098 
1099   if(HAL_MDMA_STATE_READY == hmdma->State)
1100   {
1101     /* Change MDMA peripheral state */
1102     hmdma->State = HAL_MDMA_STATE_BUSY;
1103 
1104     /* Initialize the error code */
1105     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1106 
1107     /* Disable the peripheral */
1108     __HAL_MDMA_DISABLE(hmdma);
1109 
1110     /* Configure the source, destination address and the data length */
1111     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
1112 
1113     /* Enable the Peripheral */
1114     __HAL_MDMA_ENABLE(hmdma);
1115 
1116     if(hmdma->Init.Request == MDMA_REQUEST_SW)
1117     {
1118       /* activate If SW request mode*/
1119       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
1120     }
1121   }
1122   else
1123   {
1124     /* Process unlocked */
1125     __HAL_UNLOCK(hmdma);
1126 
1127     /* Return error status */
1128     return HAL_BUSY;
1129   }
1130 
1131   return HAL_OK;
1132 }
1133 
1134 /**
1135   * @brief  Starts the MDMA Transfer with interrupts enabled.
1136   * @param  hmdma           : pointer to a MDMA_HandleTypeDef structure that contains
1137   *                           the configuration information for the specified MDMA Channel.
1138   * @param  SrcAddress      : The source memory Buffer address
1139   * @param  DstAddress      : The destination memory Buffer address
1140   * @param  BlockDataLength : The length of a block transfer in bytes
1141   * @param  BlockCount      : The number of a blocks to be transfer
1142   * @retval HAL status
1143   */
HAL_MDMA_Start_IT(MDMA_HandleTypeDef * hmdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t BlockDataLength,uint32_t BlockCount)1144 HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1145 {
1146   /* Check the parameters */
1147   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1148   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
1149 
1150   /* Check the MDMA peripheral handle */
1151   if(hmdma == NULL)
1152   {
1153     return HAL_ERROR;
1154   }
1155 
1156   /* Process locked */
1157   __HAL_LOCK(hmdma);
1158 
1159   if(HAL_MDMA_STATE_READY == hmdma->State)
1160   {
1161     /* Change MDMA peripheral state */
1162     hmdma->State = HAL_MDMA_STATE_BUSY;
1163 
1164     /* Initialize the error code */
1165     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1166 
1167     /* Disable the peripheral */
1168     __HAL_MDMA_DISABLE(hmdma);
1169 
1170     /* Configure the source, destination address and the data length */
1171     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
1172 
1173     /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/
1174     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
1175 
1176     if(hmdma->XferBlockCpltCallback != NULL)
1177     {
1178       /* if Block transfer complete Callback is set enable the corresponding IT*/
1179       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
1180     }
1181 
1182     if(hmdma->XferRepeatBlockCpltCallback != NULL)
1183     {
1184       /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/
1185       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
1186     }
1187 
1188     if(hmdma->XferBufferCpltCallback != NULL)
1189     {
1190       /* if buffer transfer complete Callback is set enable the corresponding IT*/
1191       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);
1192     }
1193 
1194     /* Enable the Peripheral */
1195     __HAL_MDMA_ENABLE(hmdma);
1196 
1197     if(hmdma->Init.Request == MDMA_REQUEST_SW)
1198     {
1199       /* activate If SW request mode*/
1200       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
1201     }
1202   }
1203   else
1204   {
1205     /* Process unlocked */
1206     __HAL_UNLOCK(hmdma);
1207 
1208     /* Return error status */
1209     return HAL_BUSY;
1210   }
1211 
1212   return HAL_OK;
1213 }
1214 
1215 /**
1216   * @brief  Aborts the MDMA Transfer.
1217   * @param  hmdma  : pointer to a MDMA_HandleTypeDef structure that contains
1218   *                 the configuration information for the specified MDMA Channel.
1219   *
1220   * @note  After disabling a MDMA Channel, a check for wait until the MDMA Channel is
1221   *        effectively disabled is added. If a Channel is disabled
1222   *        while a data transfer is ongoing, the current data will be transferred
1223   *        and the Channel will be effectively disabled only after the transfer of
1224   *        this single data is finished.
1225   * @retval HAL status
1226   */
HAL_MDMA_Abort(MDMA_HandleTypeDef * hmdma)1227 HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma)
1228 {
1229   uint32_t tickstart =  HAL_GetTick();
1230 
1231   /* Check the MDMA peripheral handle */
1232   if(hmdma == NULL)
1233   {
1234     return HAL_ERROR;
1235   }
1236 
1237   if(HAL_MDMA_STATE_BUSY != hmdma->State)
1238   {
1239     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1240 
1241     /* Process Unlocked */
1242     __HAL_UNLOCK(hmdma);
1243 
1244     return HAL_ERROR;
1245   }
1246   else
1247   {
1248     /* Disable all the transfer interrupts */
1249     __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
1250 
1251     /* Disable the channel */
1252     __HAL_MDMA_DISABLE(hmdma);
1253 
1254     /* Check if the MDMA Channel is effectively disabled */
1255     while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
1256     {
1257       /* Check for the Timeout */
1258       if( (HAL_GetTick()  - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
1259       {
1260         /* Update error code */
1261         hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
1262 
1263         /* Process Unlocked */
1264         __HAL_UNLOCK(hmdma);
1265 
1266         /* Change the MDMA state */
1267         hmdma->State = HAL_MDMA_STATE_ERROR;
1268 
1269         return HAL_ERROR;
1270       }
1271     }
1272 
1273     /* Clear all interrupt flags */
1274     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC));
1275 
1276     /* Process Unlocked */
1277     __HAL_UNLOCK(hmdma);
1278 
1279     /* Change the MDMA state*/
1280     hmdma->State = HAL_MDMA_STATE_READY;
1281   }
1282 
1283   return HAL_OK;
1284 }
1285 
1286 /**
1287   * @brief  Aborts the MDMA Transfer in Interrupt mode.
1288   * @param  hmdma  : pointer to a MDMA_HandleTypeDef structure that contains
1289   *                 the configuration information for the specified MDMA Channel.
1290   * @retval HAL status
1291   */
HAL_MDMA_Abort_IT(MDMA_HandleTypeDef * hmdma)1292 HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma)
1293 {
1294   /* Check the MDMA peripheral handle */
1295   if(hmdma == NULL)
1296   {
1297     return HAL_ERROR;
1298   }
1299 
1300   if(HAL_MDMA_STATE_BUSY != hmdma->State)
1301   {
1302     /* No transfer ongoing */
1303     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1304 
1305     return HAL_ERROR;
1306   }
1307   else
1308   {
1309     /* Set Abort State  */
1310     hmdma->State = HAL_MDMA_STATE_ABORT;
1311 
1312     /* Disable the stream */
1313     __HAL_MDMA_DISABLE(hmdma);
1314   }
1315 
1316   return HAL_OK;
1317 }
1318 
1319 /**
1320   * @brief  Polling for transfer complete.
1321   * @param  hmdma:          pointer to a MDMA_HandleTypeDef structure that contains
1322   *                        the configuration information for the specified MDMA Channel.
1323   * @param  CompleteLevel: Specifies the MDMA level complete.
1324   * @param  Timeout:       Timeout duration.
1325   * @retval HAL status
1326   */
HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef * hmdma,HAL_MDMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)1327 HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
1328 {
1329   uint32_t levelFlag, errorFlag;
1330   uint32_t tickstart;
1331 
1332   /* Check the parameters */
1333   assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel));
1334 
1335   /* Check the MDMA peripheral handle */
1336   if(hmdma == NULL)
1337   {
1338     return HAL_ERROR;
1339   }
1340 
1341   if(HAL_MDMA_STATE_BUSY != hmdma->State)
1342   {
1343     /* No transfer ongoing */
1344     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1345 
1346     return HAL_ERROR;
1347   }
1348 
1349   /* Get the level transfer complete flag */
1350   levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER)  ? MDMA_FLAG_CTC  : \
1351                (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \
1352                (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT   : \
1353                MDMA_FLAG_BRT);
1354 
1355 
1356   /* Get timeout */
1357   tickstart = HAL_GetTick();
1358 
1359   while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U)
1360   {
1361     if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
1362     {
1363       /* Get the transfer error source flag */
1364       errorFlag = hmdma->Instance->CESR;
1365 
1366       if((errorFlag & MDMA_CESR_TED) == 0U)
1367       {
1368         /* Update error code : Read Transfer error  */
1369         hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
1370       }
1371       else
1372       {
1373         /* Update error code : Write Transfer error */
1374         hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
1375       }
1376 
1377       if((errorFlag & MDMA_CESR_TEMD) != 0U)
1378       {
1379         /* Update error code : Error Mask Data */
1380         hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
1381       }
1382 
1383       if((errorFlag & MDMA_CESR_TELD) != 0U)
1384       {
1385         /* Update error code : Error Linked list */
1386         hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
1387       }
1388 
1389       if((errorFlag & MDMA_CESR_ASE) != 0U)
1390       {
1391         /* Update error code : Address/Size alignment error */
1392         hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
1393       }
1394 
1395       if((errorFlag & MDMA_CESR_BSE) != 0U)
1396       {
1397         /* Update error code : Block Size error */
1398         hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
1399       }
1400 
1401       (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */
1402 
1403       /*
1404         Note that the Abort function will
1405           - Clear all transfer flags
1406           - Unlock
1407           - Set the State
1408       */
1409 
1410       return HAL_ERROR;
1411 
1412     }
1413 
1414     /* Check for the Timeout */
1415     if(Timeout != HAL_MAX_DELAY)
1416     {
1417       if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
1418       {
1419         /* Update error code */
1420         hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
1421 
1422         (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */
1423 
1424         /*
1425           Note that the Abort function will
1426             - Clear all transfer flags
1427             - Unlock
1428             - Set the State
1429         */
1430 
1431         return HAL_ERROR;
1432       }
1433     }
1434   }
1435 
1436   /* Clear the transfer level flag */
1437   if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)
1438   {
1439     __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
1440 
1441   }
1442   else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER)
1443   {
1444     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT));
1445 
1446   }
1447   else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER)
1448   {
1449     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT));
1450   }
1451   else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER)
1452   {
1453     __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC));
1454 
1455     /* Process unlocked */
1456     __HAL_UNLOCK(hmdma);
1457 
1458     hmdma->State = HAL_MDMA_STATE_READY;
1459   }
1460   else
1461   {
1462     return HAL_ERROR;
1463   }
1464 
1465   return HAL_OK;
1466 }
1467 
1468 /**
1469   * @brief  Generate an MDMA SW request trigger to activate the request on the given Channel.
1470   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
1471   *                     the configuration information for the specified MDMA Stream.
1472   * @retval HAL status
1473   */
HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef * hmdma)1474 HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma)
1475 {
1476   uint32_t request_mode;
1477 
1478   /* Check the MDMA peripheral handle */
1479   if(hmdma == NULL)
1480   {
1481     return HAL_ERROR;
1482   }
1483 
1484   /* Get the softawre request mode */
1485   request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM;
1486 
1487   if((hmdma->Instance->CCR &  MDMA_CCR_EN) == 0U)
1488   {
1489     /* if no Transfer on going (MDMA enable bit not set) retrun error */
1490     hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1491 
1492     return HAL_ERROR;
1493   }
1494   else if(((hmdma->Instance->CISR &  MDMA_CISR_CRQA) != 0U) || (request_mode == 0U))
1495   {
1496     /* if an MDMA ongoing request has not yet end or if request mode is not SW request retrun error */
1497     hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY;
1498 
1499     return HAL_ERROR;
1500   }
1501   else
1502   {
1503     /* Set the SW request bit to activate the request on the Channel */
1504     hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
1505 
1506     return HAL_OK;
1507   }
1508 }
1509 
1510 /**
1511   * @brief  Handles MDMA interrupt request.
1512   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1513   *               the configuration information for the specified MDMA Channel.
1514   * @retval None
1515   */
HAL_MDMA_IRQHandler(MDMA_HandleTypeDef * hmdma)1516 void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma)
1517 {
1518   __IO uint32_t count = 0;
1519   uint32_t timeout = SystemCoreClock / 9600U;
1520 
1521   uint32_t generalIntFlag, errorFlag;
1522 
1523   /* General Interrupt Flag management ****************************************/
1524   generalIntFlag =  1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU);
1525  if((hmdma->Instance->CCR & MDMA_CCR_SM) != MDMA_CCR_SM)
1526   {
1527     /*Check non secure mode general flag */
1528     if((MDMA->GISR0 & generalIntFlag) == 0U)
1529     {
1530      return; /* the  General interrupt flag for the current channel is down , nothing to do */
1531     }
1532   }
1533   else
1534   {
1535     /*Check secure mode general flag */
1536     if((MDMA->SGISR0 & generalIntFlag) == 0U)
1537     {
1538      return; /* the  General interrupt flag for the current channel is down , nothing to do */
1539     }
1540   }
1541 
1542   /* Transfer Error Interrupt management ***************************************/
1543   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
1544   {
1545     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U)
1546     {
1547       /* Disable the transfer error interrupt */
1548       __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE);
1549 
1550       /* Get the transfer error source flag */
1551       errorFlag = hmdma->Instance->CESR;
1552 
1553       if((errorFlag & MDMA_CESR_TED) == 0U)
1554       {
1555         /* Update error code : Read Transfer error  */
1556         hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
1557       }
1558       else
1559       {
1560         /* Update error code : Write Transfer error */
1561         hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
1562       }
1563 
1564       if((errorFlag & MDMA_CESR_TEMD) != 0U)
1565       {
1566         /* Update error code : Error Mask Data */
1567         hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
1568       }
1569 
1570       if((errorFlag & MDMA_CESR_TELD) != 0U)
1571       {
1572         /* Update error code : Error Linked list */
1573         hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
1574       }
1575 
1576       if((errorFlag & MDMA_CESR_ASE) != 0U)
1577       {
1578         /* Update error code : Address/Size alignment error */
1579         hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
1580       }
1581 
1582       if((errorFlag & MDMA_CESR_BSE) != 0U)
1583       {
1584         /* Update error code : Block Size error error */
1585         hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
1586       }
1587 
1588       /* Clear the transfer error flags */
1589       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE);
1590     }
1591   }
1592 
1593   /* Buffer Transfer Complete Interrupt management ******************************/
1594   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U))
1595   {
1596     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U)
1597     {
1598       /* Clear the buffer transfer complete flag */
1599       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
1600 
1601       if(hmdma->XferBufferCpltCallback != NULL)
1602       {
1603         /* Buffer transfer callback */
1604         hmdma->XferBufferCpltCallback(hmdma);
1605       }
1606     }
1607   }
1608 
1609   /* Block Transfer Complete Interrupt management ******************************/
1610   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U))
1611   {
1612     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U)
1613     {
1614       /* Clear the block transfer complete flag */
1615       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT);
1616 
1617       if(hmdma->XferBlockCpltCallback != NULL)
1618       {
1619         /* Block transfer callback */
1620         hmdma->XferBlockCpltCallback(hmdma);
1621       }
1622     }
1623   }
1624 
1625   /* Repeated Block Transfer Complete Interrupt management ******************************/
1626   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U))
1627   {
1628     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U)
1629     {
1630       /* Clear the repeat block transfer complete flag */
1631       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT);
1632 
1633       if(hmdma->XferRepeatBlockCpltCallback != NULL)
1634       {
1635         /* Repeated Block transfer callback */
1636         hmdma->XferRepeatBlockCpltCallback(hmdma);
1637       }
1638     }
1639   }
1640 
1641   /* Channel Transfer Complete Interrupt management ***********************************/
1642   if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U))
1643   {
1644     if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U)
1645     {
1646       /* Disable all the transfer interrupts */
1647       __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
1648 
1649       if(HAL_MDMA_STATE_ABORT == hmdma->State)
1650       {
1651         /* Process Unlocked */
1652         __HAL_UNLOCK(hmdma);
1653 
1654         /* Change the DMA state */
1655         hmdma->State = HAL_MDMA_STATE_READY;
1656 
1657         if(hmdma->XferAbortCallback != NULL)
1658         {
1659           hmdma->XferAbortCallback(hmdma);
1660         }
1661         return;
1662       }
1663 
1664       /* Clear the Channel Transfer Complete flag */
1665       __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC);
1666 
1667       /* Process Unlocked */
1668       __HAL_UNLOCK(hmdma);
1669 
1670       /* Change MDMA peripheral state */
1671       hmdma->State = HAL_MDMA_STATE_READY;
1672 
1673       if(hmdma->XferCpltCallback != NULL)
1674       {
1675         /* Channel Transfer Complete callback */
1676         hmdma->XferCpltCallback(hmdma);
1677       }
1678     }
1679   }
1680 
1681   /* manage error case */
1682   if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE)
1683   {
1684     hmdma->State = HAL_MDMA_STATE_ABORT;
1685 
1686     /* Disable the channel */
1687     __HAL_MDMA_DISABLE(hmdma);
1688 
1689     do
1690     {
1691       if (++count > timeout)
1692       {
1693         break;
1694       }
1695     }
1696     while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U);
1697 
1698     /* Process Unlocked */
1699     __HAL_UNLOCK(hmdma);
1700 
1701     if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
1702     {
1703       /* Change the MDMA state to error if MDMA disable fails */
1704       hmdma->State = HAL_MDMA_STATE_ERROR;
1705     }
1706     else
1707     {
1708       /* Change the MDMA state to Ready if MDMA disable success */
1709       hmdma->State = HAL_MDMA_STATE_READY;
1710     }
1711 
1712 
1713     if (hmdma->XferErrorCallback != NULL)
1714     {
1715       /* Transfer error callback */
1716       hmdma->XferErrorCallback(hmdma);
1717     }
1718   }
1719 }
1720 
1721 /**
1722   * @}
1723   */
1724 
1725 /** @addtogroup MDMA_Exported_Functions_Group4
1726  *
1727 @verbatim
1728  ===============================================================================
1729                     ##### State and Errors functions #####
1730  ===============================================================================
1731     [..]
1732     This subsection provides functions allowing to
1733       (+) Check the MDMA state
1734       (+) Get error code
1735 
1736 @endverbatim
1737   * @{
1738   */
1739 
1740 /**
1741   * @brief  Returns the MDMA state.
1742   * @param  hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1743   *               the configuration information for the specified MDMA Channel.
1744   * @retval HAL state
1745   */
HAL_MDMA_GetState(MDMA_HandleTypeDef * hmdma)1746 HAL_MDMA_StateTypeDef HAL_MDMA_GetState(MDMA_HandleTypeDef *hmdma)
1747 {
1748   return hmdma->State;
1749 }
1750 
1751 /**
1752   * @brief  Return the MDMA error code
1753   * @param  hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1754   *              the configuration information for the specified MDMA Channel.
1755   * @retval MDMA Error Code
1756   */
HAL_MDMA_GetError(MDMA_HandleTypeDef * hmdma)1757 uint32_t HAL_MDMA_GetError(MDMA_HandleTypeDef *hmdma)
1758 {
1759   return hmdma->ErrorCode;
1760 }
1761 
1762 /**
1763   * @}
1764   */
1765 
1766 /**
1767   * @}
1768   */
1769 
1770 /** @addtogroup MDMA_Private_Functions
1771   * @{
1772   */
1773 
1774 /**
1775   * @brief  Sets the MDMA Transfer parameter.
1776   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
1777   *                     the configuration information for the specified MDMA Channel.
1778   * @param  SrcAddress: The source memory Buffer address
1779   * @param  DstAddress: The destination memory Buffer address
1780   * @param  BlockDataLength : The length of a block transfer in bytes
1781   * @param  BlockCount: The number of blocks to be transfered
1782   * @retval HAL status
1783   */
MDMA_SetConfig(MDMA_HandleTypeDef * hmdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t BlockDataLength,uint32_t BlockCount)1784 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1785 {
1786   uint32_t addressMask;
1787 
1788   /* Configure the MDMA Channel data length */
1789   MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT));
1790 
1791   /* Configure the MDMA block repeat count */
1792   MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC);
1793 
1794   /* Clear all interrupt flags */
1795   __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF);
1796 
1797   /* Configure MDMA Channel destination address */
1798   hmdma->Instance->CDAR = DstAddress;
1799 
1800   /* Configure MDMA Channel Source address */
1801   hmdma->Instance->CSAR = SrcAddress;
1802 
1803   addressMask = SrcAddress & 0xFF000000U;
1804   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
1805   {
1806     /*The AHBSbus is used as source (read operation) on channel x */
1807     hmdma->Instance->CTBR |= MDMA_CTBR_SBUS;
1808   }
1809   else
1810   {
1811     /*The AXI bus is used as source (read operation) on channel x */
1812     hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS);
1813   }
1814 
1815   addressMask = DstAddress & 0xFF000000U;
1816   if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
1817   {
1818     /*The AHB bus is used as destination (write operation) on channel x */
1819     hmdma->Instance->CTBR |= MDMA_CTBR_DBUS;
1820   }
1821   else
1822   {
1823     /*The AXI bus is used as destination (write operation) on channel x */
1824     hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS);
1825   }
1826 
1827   /* Set the linked list register to the first node of the list */
1828   hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
1829 }
1830 
1831 /**
1832   * @brief  Initializes the MDMA handle according to the specified
1833   *         parameters in the MDMA_InitTypeDef
1834   * @param  hmdma:       pointer to a MDMA_HandleTypeDef structure that contains
1835   *                     the configuration information for the specified MDMA Channel.
1836   * @retval None
1837   */
MDMA_Init(MDMA_HandleTypeDef * hmdma)1838 static void MDMA_Init(MDMA_HandleTypeDef *hmdma)
1839 {
1840   uint32_t blockoffset;
1841 
1842   /* Prepare the MDMA Channel configuration */
1843   hmdma->Instance->CCR = hmdma->Init.Priority  | hmdma->Init.SecureMode | hmdma->Init.Endianness;
1844 
1845   /* Write new CTCR Register value */
1846   hmdma->Instance->CTCR =  hmdma->Init.SourceInc      | hmdma->Init.DestinationInc | \
1847                            hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize   | \
1848                            hmdma->Init.DataAlignment  | hmdma->Init.SourceBurst    | \
1849                            hmdma->Init.DestBurst                                   | \
1850                            ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
1851                            hmdma->Init.TransferTriggerMode;
1852 
1853   /* If SW request set the CTCR register to SW Request Mode */
1854   if(hmdma->Init.Request == MDMA_REQUEST_SW)
1855   {
1856     /*
1857     -If the request is done by SW : BWM could be set to 1 or 0.
1858     -If the request is done by a peripheral :
1859     If mask address not set (0) => BWM must be set to 0
1860     If mask address set (different than 0) => BWM could be set to 1 or 0
1861     */
1862     hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM);
1863   }
1864 
1865   /* Reset CBNDTR Register */
1866   hmdma->Instance->CBNDTR = 0;
1867 
1868   /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
1869   if(hmdma->Init.SourceBlockAddressOffset < 0)
1870   {
1871     hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM;
1872     /* Write new CBRUR Register value : source repeat block offset */
1873     blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset);
1874     hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU);
1875   }
1876   else
1877   {
1878     /* Write new CBRUR Register value : source repeat block offset */
1879     hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
1880   }
1881 
1882   /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
1883   if(hmdma->Init.DestBlockAddressOffset < 0)
1884   {
1885     hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM;
1886     /* Write new CBRUR Register value : destination repeat block offset */
1887     blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset);
1888     hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
1889   }
1890   else
1891   {
1892     /*write new CBRUR Register value : destination repeat block offset */
1893     hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
1894   }
1895 
1896   /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
1897   if(hmdma->Init.Request != MDMA_REQUEST_SW)
1898   {
1899     /* Set the HW request in CTRB register  */
1900     hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL;
1901   }
1902   else /* SW request : reset the CTBR register */
1903   {
1904     hmdma->Instance->CTBR = 0;
1905   }
1906 
1907   /* Write Link Address Register */
1908   hmdma->Instance->CLAR =  0;
1909 }
1910 
1911 /**
1912   * @}
1913   */
1914 /**
1915   * @brief MDMA MSP Init
1916   * @param hmdma: MDMA handle
1917   * @retval None
1918   */
HAL_MDMA_MspInit(MDMA_HandleTypeDef * hmdma)1919  __weak void HAL_MDMA_MspInit(MDMA_HandleTypeDef *hmdma)
1920 {
1921   /* NOTE : This function should not be modified, when the callback is needed,
1922             the HAL_MDMA_MspInit can be implemented in the user file
1923    */
1924 }
1925 
1926 /**
1927   * @brief MDMA MSP DeInit
1928   * @param hmdma: MDMA handle
1929   * @retval None
1930   */
HAL_MDMA_MspDeInit(MDMA_HandleTypeDef * hmdma)1931  __weak void HAL_MDMA_MspDeInit(MDMA_HandleTypeDef *hmdma)
1932 {
1933   /* NOTE : This function should not be modified, when the callback is needed,
1934             the HAL_MDMA_MspDeInit can be implemented in the user file
1935    */
1936 }
1937 
1938 /**
1939   * @}
1940   */
1941 #endif /* HAL_MDMA_MODULE_ENABLED */
1942 /**
1943   * @}
1944   */
1945 
1946 /**
1947   * @}
1948   */
1949