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