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