Create release.yml
[betaflight.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_mdma.c
blob4e606000ef190c5f279793f9bcbf9e8cd4fa720e
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.
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.
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
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.
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).
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).
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).
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).
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).
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.
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.
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.
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.
115 [..] Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection.
117 *** MDMA HAL driver macros list ***
118 =============================================
119 [..]
120 Below the list of most used macros in MDMA HAL driver.
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.
130 [..]
131 (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
133 [..]
135 @endverbatim
136 ******************************************************************************
137 * @attention
139 * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics.
140 * All rights reserved.</center></h2>
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
147 ******************************************************************************
150 /* Includes ------------------------------------------------------------------*/
151 #include "stm32h7xx_hal.h"
153 /** @addtogroup STM32H7xx_HAL_Driver
154 * @{
157 /** @defgroup MDMA MDMA
158 * @brief MDMA HAL module driver
159 * @{
162 #ifdef HAL_MDMA_MODULE_ENABLED
164 /* Private typedef -----------------------------------------------------------*/
165 /* Private constants ---------------------------------------------------------*/
166 /** @addtogroup MDMA_Private_Constants
167 * @{
169 #define HAL_TIMEOUT_MDMA_ABORT 5U /* 5 ms */
170 #define HAL_MDMA_CHANNEL_SIZE 0x40U /* an MDMA instance channel size is 64 byte */
172 * @}
174 /* Private macro -------------------------------------------------------------*/
175 /* Private variables ---------------------------------------------------------*/
176 /* Private function prototypes -----------------------------------------------*/
177 /** @addtogroup MDMA_Private_Functions_Prototypes
178 * @{
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);
184 * @}
187 /** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
188 * @{
191 /** @addtogroup MDMA_Exported_Functions_Group1
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.
208 @endverbatim
209 * @{
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
219 HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
221 uint32_t tickstart = HAL_GetTick();
223 /* Check the MDMA peripheral handle */
224 if(hmdma == NULL)
226 return HAL_ERROR;
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));
247 /* Allocate lock resource */
248 __HAL_UNLOCK(hmdma);
250 /* Change MDMA peripheral state */
251 hmdma->State = HAL_MDMA_STATE_BUSY;
253 /* Disable the MDMA channel */
254 __HAL_MDMA_DISABLE(hmdma);
256 /* Check if the MDMA channel is effectively disabled */
257 while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
259 /* Check for the Timeout */
260 if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
262 /* Update error code */
263 hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
265 /* Change the MDMA state */
266 hmdma->State = HAL_MDMA_STATE_ERROR;
268 return HAL_ERROR;
272 /* Initialize the MDMA channel registers */
273 MDMA_Init(hmdma);
275 /* Reset the MDMA first/last linkedlist node addresses and node counter */
276 hmdma->FirstLinkedListNodeAddress = 0;
277 hmdma->LastLinkedListNodeAddress = 0;
278 hmdma->LinkedListNodeCounter = 0;
280 /* Initialize the error code */
281 hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
283 /* Initialize the MDMA state */
284 hmdma->State = HAL_MDMA_STATE_READY;
286 return HAL_OK;
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
295 HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma)
298 /* Check the MDMA peripheral handle */
299 if(hmdma == NULL)
301 return HAL_ERROR;
304 /* Disable the selected MDMA Channelx */
305 __HAL_MDMA_DISABLE(hmdma);
307 /* Reset MDMA Channel control register */
308 hmdma->Instance->CCR = 0;
309 hmdma->Instance->CTCR = 0;
310 hmdma->Instance->CBNDTR = 0;
311 hmdma->Instance->CSAR = 0;
312 hmdma->Instance->CDAR = 0;
313 hmdma->Instance->CBRUR = 0;
314 hmdma->Instance->CLAR = 0;
315 hmdma->Instance->CTBR = 0;
316 hmdma->Instance->CMAR = 0;
317 hmdma->Instance->CMDR = 0;
319 /* Clear all flags */
320 __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC));
322 /* Reset the MDMA first/last linkedlist node addresses and node counter */
323 hmdma->FirstLinkedListNodeAddress = 0;
324 hmdma->LastLinkedListNodeAddress = 0;
325 hmdma->LinkedListNodeCounter = 0;
327 /* Initialize the error code */
328 hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
330 /* Initialize the MDMA state */
331 hmdma->State = HAL_MDMA_STATE_RESET;
333 /* Release Lock */
334 __HAL_UNLOCK(hmdma);
336 return HAL_OK;
340 * @brief Config the Post request Mask address and Mask data
341 * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
342 * the configuration information for the specified MDMA Channel.
343 * @param MaskAddress: specifies the address to be updated (written) with MaskData after a request is served.
344 * @param MaskData: specifies the value to be written to MaskAddress after a request is served.
345 * MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served.
346 * @retval HAL status
348 HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData)
350 HAL_StatusTypeDef status = HAL_OK;
352 /* Check the MDMA peripheral handle */
353 if(hmdma == NULL)
355 return HAL_ERROR;
358 /* Process locked */
359 __HAL_LOCK(hmdma);
361 if(HAL_MDMA_STATE_READY == hmdma->State)
363 /* if HW request set Post Request MaskAddress and MaskData, */
364 if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U)
366 /* Set the HW request clear Mask and Data */
367 hmdma->Instance->CMAR = MaskAddress;
368 hmdma->Instance->CMDR = MaskData;
371 -If the request is done by SW : BWM could be set to 1 or 0.
372 -If the request is done by a peripheral :
373 If mask address not set (0) => BWM must be set to 0
374 If mask address set (different than 0) => BWM could be set to 1 or 0
376 if(MaskAddress == 0U)
378 hmdma->Instance->CTCR &= ~MDMA_CTCR_BWM;
380 else
382 hmdma->Instance->CTCR |= MDMA_CTCR_BWM;
385 else
387 /* Return error status */
388 status = HAL_ERROR;
391 else
393 /* Return error status */
394 status = HAL_ERROR;
396 /* Release Lock */
397 __HAL_UNLOCK(hmdma);
399 return status;
403 * @brief Register callbacks
404 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
405 * the configuration information for the specified MDMA Channel.
406 * @param CallbackID: User Callback identifier
407 * @param pCallback: pointer to callbacsk function.
408 * @retval HAL status
410 HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma))
412 HAL_StatusTypeDef status = HAL_OK;
414 /* Check the MDMA peripheral handle */
415 if(hmdma == NULL)
417 return HAL_ERROR;
420 /* Process locked */
421 __HAL_LOCK(hmdma);
423 if(HAL_MDMA_STATE_READY == hmdma->State)
425 switch (CallbackID)
427 case HAL_MDMA_XFER_CPLT_CB_ID:
428 hmdma->XferCpltCallback = pCallback;
429 break;
431 case HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
432 hmdma->XferBufferCpltCallback = pCallback;
433 break;
435 case HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
436 hmdma->XferBlockCpltCallback = pCallback;
437 break;
439 case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
440 hmdma->XferRepeatBlockCpltCallback = pCallback;
441 break;
443 case HAL_MDMA_XFER_ERROR_CB_ID:
444 hmdma->XferErrorCallback = pCallback;
445 break;
447 case HAL_MDMA_XFER_ABORT_CB_ID:
448 hmdma->XferAbortCallback = pCallback;
449 break;
451 default:
452 break;
455 else
457 /* Return error status */
458 status = HAL_ERROR;
461 /* Release Lock */
462 __HAL_UNLOCK(hmdma);
464 return status;
468 * @brief UnRegister callbacks
469 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
470 * the configuration information for the specified MDMA Channel.
471 * @param CallbackID: User Callback identifier
472 * a HAL_MDMA_CallbackIDTypeDef ENUM as parameter.
473 * @retval HAL status
475 HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID)
477 HAL_StatusTypeDef status = HAL_OK;
479 /* Check the MDMA peripheral handle */
480 if(hmdma == NULL)
482 return HAL_ERROR;
485 /* Process locked */
486 __HAL_LOCK(hmdma);
488 if(HAL_MDMA_STATE_READY == hmdma->State)
490 switch (CallbackID)
492 case HAL_MDMA_XFER_CPLT_CB_ID:
493 hmdma->XferCpltCallback = NULL;
494 break;
496 case HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
497 hmdma->XferBufferCpltCallback = NULL;
498 break;
500 case HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
501 hmdma->XferBlockCpltCallback = NULL;
502 break;
504 case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
505 hmdma->XferRepeatBlockCpltCallback = NULL;
506 break;
508 case HAL_MDMA_XFER_ERROR_CB_ID:
509 hmdma->XferErrorCallback = NULL;
510 break;
512 case HAL_MDMA_XFER_ABORT_CB_ID:
513 hmdma->XferAbortCallback = NULL;
514 break;
516 case HAL_MDMA_XFER_ALL_CB_ID:
517 hmdma->XferCpltCallback = NULL;
518 hmdma->XferBufferCpltCallback = NULL;
519 hmdma->XferBlockCpltCallback = NULL;
520 hmdma->XferRepeatBlockCpltCallback = NULL;
521 hmdma->XferErrorCallback = NULL;
522 hmdma->XferAbortCallback = NULL;
523 break;
525 default:
526 status = HAL_ERROR;
527 break;
530 else
532 status = HAL_ERROR;
535 /* Release Lock */
536 __HAL_UNLOCK(hmdma);
538 return status;
542 * @}
545 /** @addtogroup MDMA_Exported_Functions_Group2
547 @verbatim
548 ===============================================================================
549 ##### Linked list operation functions #####
550 ===============================================================================
551 [..] This section provides functions allowing to:
552 (+) Create a linked list node
553 (+) Add a node to the MDMA linked list
554 (+) Remove a node from the MDMA linked list
555 (+) Enable/Disable linked list circular mode
556 @endverbatim
557 * @{
561 * @brief Initializes an MDMA Link Node according to the specified
562 * parameters in the pMDMA_LinkedListNodeConfig .
563 * @param pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
564 * registers configurations.
565 * @param pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains
566 * the configuration information for the specified MDMA Linked List Node.
567 * @retval HAL status
569 HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig)
571 uint32_t addressMask;
572 uint32_t blockoffset;
574 /* Check the MDMA peripheral state */
575 if((pNode == NULL) || (pNodeConfig == NULL))
577 return HAL_ERROR;
580 /* Check the parameters */
581 assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority));
582 assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness));
583 assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request));
584 assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc));
585 assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc));
586 assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize));
587 assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize));
588 assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment));
589 assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst));
590 assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst));
591 assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength));
592 assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode));
593 assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset));
594 assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset));
596 assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength));
597 assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount));
600 /* Configure next Link node Address Register to zero */
601 pNode->CLAR = 0;
603 /* Configure the Link Node registers*/
604 pNode->CTBR = 0;
605 pNode->CMAR = 0;
606 pNode->CMDR = 0;
607 pNode->Reserved = 0;
609 /* Write new CTCR Register value */
610 pNode->CTCR = pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \
611 pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize | \
612 pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst | \
613 pNodeConfig->Init.DestBurst | \
614 ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
615 pNodeConfig->Init.TransferTriggerMode;
617 /* If SW request set the CTCR register to SW Request Mode*/
618 if(pNodeConfig->Init.Request == MDMA_REQUEST_SW)
620 pNode->CTCR |= MDMA_CTCR_SWRM;
624 -If the request is done by SW : BWM could be set to 1 or 0.
625 -If the request is done by a peripheral :
626 If mask address not set (0) => BWM must be set to 0
627 If mask address set (different than 0) => BWM could be set to 1 or 0
629 if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U))
631 pNode->CTCR |= MDMA_CTCR_BWM;
634 /* Set the new CBNDTR Register value */
635 pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC;
637 /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
638 if(pNodeConfig->Init.SourceBlockAddressOffset < 0)
640 pNode->CBNDTR |= MDMA_CBNDTR_BRSUM;
641 /*write new CBRUR Register value : source repeat block offset */
642 blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset);
643 pNode->CBRUR = blockoffset & 0x0000FFFFU;
645 else
647 /*write new CBRUR Register value : source repeat block offset */
648 pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
651 /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
652 if(pNodeConfig->Init.DestBlockAddressOffset < 0)
654 pNode->CBNDTR |= MDMA_CBNDTR_BRDUM;
655 /*write new CBRUR Register value : destination repeat block offset */
656 blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset);
657 pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
659 else
661 /*write new CBRUR Register value : destination repeat block offset */
662 pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
665 /* Configure MDMA Link Node data length */
666 pNode->CBNDTR |= pNodeConfig->BlockDataLength;
668 /* Configure MDMA Link Node destination address */
669 pNode->CDAR = pNodeConfig->DstAddress;
671 /* Configure MDMA Link Node Source address */
672 pNode->CSAR = pNodeConfig->SrcAddress;
674 /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
675 if(pNodeConfig->Init.Request != MDMA_REQUEST_SW)
677 /* Set the HW request in CTBR register */
678 pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL;
679 /* Set the HW request clear Mask and Data */
680 pNode->CMAR = pNodeConfig->PostRequestMaskAddress;
681 pNode->CMDR = pNodeConfig->PostRequestMaskData;
684 addressMask = pNodeConfig->SrcAddress & 0xFF000000U;
685 if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
687 /*The AHBSbus is used as source (read operation) on channel x */
688 pNode->CTBR |= MDMA_CTBR_SBUS;
691 addressMask = pNodeConfig->DstAddress & 0xFF000000U;
692 if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
694 /*The AHB bus is used as destination (write operation) on channel x */
695 pNode->CTBR |= MDMA_CTBR_DBUS;
698 return HAL_OK;
702 * @brief Connect a node to the linked list.
703 * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
704 * the configuration information for the specified MDMA Channel.
705 * @param pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
706 * to be add to the list.
707 * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
708 * at the end of the list
710 * @retval HAL status
712 HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, MDMA_LinkNodeTypeDef *pPrevNode)
714 MDMA_LinkNodeTypeDef *pNode;
715 uint32_t counter = 0, nodeInserted = 0;
716 HAL_StatusTypeDef hal_status = HAL_OK;
718 /* Check the MDMA peripheral handle */
719 if((hmdma == NULL) || (pNewNode == NULL))
721 return HAL_ERROR;
724 /* Process locked */
725 __HAL_LOCK(hmdma);
727 if(HAL_MDMA_STATE_READY == hmdma->State)
729 /* Change MDMA peripheral state */
730 hmdma->State = HAL_MDMA_STATE_BUSY;
732 /* Check if this is the first node (after the Inititlization node) */
733 if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U)
735 if(pPrevNode == NULL)
737 /* if this is the first node after the initialization
738 connect this node to the node 0 by updating
739 the MDMA channel CLAR register to this node address */
740 hmdma->Instance->CLAR = (uint32_t)pNewNode;
741 /* Set the MDMA handle First linked List node*/
742 hmdma->FirstLinkedListNodeAddress = pNewNode;
744 /*reset New node link */
745 pNewNode->CLAR = 0;
747 /* Update the Handle last node address */
748 hmdma->LastLinkedListNodeAddress = pNewNode;
750 hmdma->LinkedListNodeCounter = 1;
752 else
754 hal_status = HAL_ERROR;
757 else if(hmdma->FirstLinkedListNodeAddress != pNewNode)
759 /* Check if the node to insert already exists*/
760 pNode = hmdma->FirstLinkedListNodeAddress;
761 while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
763 if(pNode->CLAR == (uint32_t)pNewNode)
765 hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
767 pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
768 counter++;
771 if(hal_status == HAL_OK)
773 /* Check if the previous node is the last one in the current list or zero */
774 if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL))
776 /* insert the new node at the end of the list */
777 pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;
778 hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
779 /* Update the Handle last node address */
780 hmdma->LastLinkedListNodeAddress = pNewNode;
781 /* Increment the linked list node counter */
782 hmdma->LinkedListNodeCounter++;
784 else
786 /*insert the new node after the pPreviousNode node */
787 pNode = hmdma->FirstLinkedListNodeAddress;
788 counter = 0;
789 while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U))
791 counter++;
792 if(pNode == pPrevNode)
794 /*Insert the new node after the previous one */
795 pNewNode->CLAR = pNode->CLAR;
796 pNode->CLAR = (uint32_t)pNewNode;
797 /* Increment the linked list node counter */
798 hmdma->LinkedListNodeCounter++;
799 nodeInserted = 1;
801 else
803 pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
807 if(nodeInserted == 0U)
809 hal_status = HAL_ERROR;
814 else
816 hal_status = HAL_ERROR;
819 /* Process unlocked */
820 __HAL_UNLOCK(hmdma);
822 hmdma->State = HAL_MDMA_STATE_READY;
824 return hal_status;
826 else
828 /* Process unlocked */
829 __HAL_UNLOCK(hmdma);
831 /* Return error status */
832 return HAL_BUSY;
837 * @brief Disconnect/Remove a node from the transfer linked list.
838 * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
839 * the configuration information for the specified MDMA Channel.
840 * @param pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
841 * to be removed from the list.
843 * @retval HAL status
845 HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode)
847 MDMA_LinkNodeTypeDef *ptmpNode;
848 uint32_t counter = 0, nodeDeleted = 0;
849 HAL_StatusTypeDef hal_status = HAL_OK;
851 /* Check the MDMA peripheral handle */
852 if((hmdma == NULL) || (pNode == NULL))
854 return HAL_ERROR;
857 /* Process locked */
858 __HAL_LOCK(hmdma);
860 if(HAL_MDMA_STATE_READY == hmdma->State)
862 /* Change MDMA peripheral state */
863 hmdma->State = HAL_MDMA_STATE_BUSY;
865 /* If first and last node are null (no nodes in the list) : return error*/
866 if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
868 hal_status = HAL_ERROR;
870 else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */
872 /* Delete 1st node */
873 if(hmdma->LastLinkedListNodeAddress == pNode)
875 /*if the last node is at the same time the first one (1 single node after the init node 0)
876 then update the last node too */
878 hmdma->FirstLinkedListNodeAddress = 0;
879 hmdma->LastLinkedListNodeAddress = 0;
880 hmdma->LinkedListNodeCounter = 0;
882 hmdma->Instance->CLAR = 0;
884 else
886 if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR)
888 /* if last node is looping to first (circular list) one update the last node connection */
889 hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR;
892 /* if deleting the first node after the initialization
893 connect the next node to the node 0 by updating
894 the MDMA channel CLAR register to this node address */
895 hmdma->Instance->CLAR = pNode->CLAR;
896 hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR;
897 /* Update the Handle node counter */
898 hmdma->LinkedListNodeCounter--;
901 else /* Deleting any other node */
903 /*Deleted node is not the first one : find it */
904 ptmpNode = hmdma->FirstLinkedListNodeAddress;
905 while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U))
907 counter++;
908 if(ptmpNode->CLAR == ((uint32_t)pNode))
910 /* if deleting the last node */
911 if(pNode == hmdma->LastLinkedListNodeAddress)
913 /*Update the linked list last node address in the handle*/
914 hmdma->LastLinkedListNodeAddress = ptmpNode;
916 /* update the next node link after deleting pMDMA_LinkedListNode */
917 ptmpNode->CLAR = pNode->CLAR;
918 nodeDeleted = 1;
919 /* Update the Handle node counter */
920 hmdma->LinkedListNodeCounter--;
922 else
924 ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR;
928 if(nodeDeleted == 0U)
930 /* last node reashed without finding the node to delete : return error */
931 hal_status = HAL_ERROR;
935 /* Process unlocked */
936 __HAL_UNLOCK(hmdma);
938 hmdma->State = HAL_MDMA_STATE_READY;
940 return hal_status;
942 else
944 /* Process unlocked */
945 __HAL_UNLOCK(hmdma);
947 /* Return error status */
948 return HAL_BUSY;
953 * @brief Make the linked list circular by connecting the last node to the first.
954 * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
955 * the configuration information for the specified MDMA Channel.
956 * @retval HAL status
958 HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
960 HAL_StatusTypeDef hal_status = HAL_OK;
962 /* Check the MDMA peripheral handle */
963 if(hmdma == NULL)
965 return HAL_ERROR;
968 /* Process locked */
969 __HAL_LOCK(hmdma);
971 if(HAL_MDMA_STATE_READY == hmdma->State)
973 /* Change MDMA peripheral state */
974 hmdma->State = HAL_MDMA_STATE_BUSY;
976 /* If first and last node are null (no nodes in the list) : return error*/
977 if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
979 hal_status = HAL_ERROR;
981 else
983 /* to enable circular mode Last Node should be connected to first node */
984 hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
988 /* Process unlocked */
989 __HAL_UNLOCK(hmdma);
991 hmdma->State = HAL_MDMA_STATE_READY;
993 return hal_status;
997 * @brief Disable the linked list circular mode by setting the last node connection to null
998 * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
999 * the configuration information for the specified MDMA Channel.
1000 * @retval HAL status
1002 HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma)
1004 HAL_StatusTypeDef hal_status = HAL_OK;
1006 /* Check the MDMA peripheral handle */
1007 if(hmdma == NULL)
1009 return HAL_ERROR;
1012 /* Process locked */
1013 __HAL_LOCK(hmdma);
1015 if(HAL_MDMA_STATE_READY == hmdma->State)
1017 /* Change MDMA peripheral state */
1018 hmdma->State = HAL_MDMA_STATE_BUSY;
1020 /* If first and last node are null (no nodes in the list) : return error*/
1021 if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
1023 hal_status = HAL_ERROR;
1025 else
1027 /* to disable circular mode Last Node should be connected to NULL */
1028 hmdma->LastLinkedListNodeAddress->CLAR = 0;
1032 /* Process unlocked */
1033 __HAL_UNLOCK(hmdma);
1035 hmdma->State = HAL_MDMA_STATE_READY;
1037 return hal_status;
1041 * @}
1044 /** @addtogroup MDMA_Exported_Functions_Group3
1046 @verbatim
1047 ===============================================================================
1048 ##### IO operation functions #####
1049 ===============================================================================
1050 [..] This section provides functions allowing to:
1051 (+) Configure the source, destination address and data length and Start MDMA transfer
1052 (+) Configure the source, destination address and data length and
1053 Start MDMA transfer with interrupt
1054 (+) Abort MDMA transfer
1055 (+) Poll for transfer complete
1056 (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW)
1057 (+) Handle MDMA interrupt request
1059 @endverbatim
1060 * @{
1064 * @brief Starts the MDMA Transfer.
1065 * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1066 * the configuration information for the specified MDMA Channel.
1067 * @param SrcAddress : The source memory Buffer address
1068 * @param DstAddress : The destination memory Buffer address
1069 * @param BlockDataLength : The length of a block transfer in bytes
1070 * @param BlockCount : The number of a blocks to be transfer
1071 * @retval HAL status
1073 HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1075 /* Check the parameters */
1076 assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1077 assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
1079 /* Check the MDMA peripheral handle */
1080 if(hmdma == NULL)
1082 return HAL_ERROR;
1085 /* Process locked */
1086 __HAL_LOCK(hmdma);
1088 if(HAL_MDMA_STATE_READY == hmdma->State)
1090 /* Change MDMA peripheral state */
1091 hmdma->State = HAL_MDMA_STATE_BUSY;
1093 /* Initialize the error code */
1094 hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1096 /* Disable the peripheral */
1097 __HAL_MDMA_DISABLE(hmdma);
1099 /* Configure the source, destination address and the data length */
1100 MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
1102 /* Enable the Peripheral */
1103 __HAL_MDMA_ENABLE(hmdma);
1105 if(hmdma->Init.Request == MDMA_REQUEST_SW)
1107 /* activate If SW request mode*/
1108 hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
1111 else
1113 /* Process unlocked */
1114 __HAL_UNLOCK(hmdma);
1116 /* Return error status */
1117 return HAL_BUSY;
1120 return HAL_OK;
1124 * @brief Starts the MDMA Transfer with interrupts enabled.
1125 * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1126 * the configuration information for the specified MDMA Channel.
1127 * @param SrcAddress : The source memory Buffer address
1128 * @param DstAddress : The destination memory Buffer address
1129 * @param BlockDataLength : The length of a block transfer in bytes
1130 * @param BlockCount : The number of a blocks to be transfer
1131 * @retval HAL status
1133 HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1135 /* Check the parameters */
1136 assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
1137 assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
1139 /* Check the MDMA peripheral handle */
1140 if(hmdma == NULL)
1142 return HAL_ERROR;
1145 /* Process locked */
1146 __HAL_LOCK(hmdma);
1148 if(HAL_MDMA_STATE_READY == hmdma->State)
1150 /* Change MDMA peripheral state */
1151 hmdma->State = HAL_MDMA_STATE_BUSY;
1153 /* Initialize the error code */
1154 hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
1156 /* Disable the peripheral */
1157 __HAL_MDMA_DISABLE(hmdma);
1159 /* Configure the source, destination address and the data length */
1160 MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
1162 /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/
1163 __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
1165 if(hmdma->XferBlockCpltCallback != NULL)
1167 /* if Block transfer complete Callback is set enable the corresponding IT*/
1168 __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
1171 if(hmdma->XferRepeatBlockCpltCallback != NULL)
1173 /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/
1174 __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
1177 if(hmdma->XferBufferCpltCallback != NULL)
1179 /* if buffer transfer complete Callback is set enable the corresponding IT*/
1180 __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);
1183 /* Enable the Peripheral */
1184 __HAL_MDMA_ENABLE(hmdma);
1186 if(hmdma->Init.Request == MDMA_REQUEST_SW)
1188 /* activate If SW request mode*/
1189 hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
1192 else
1194 /* Process unlocked */
1195 __HAL_UNLOCK(hmdma);
1197 /* Return error status */
1198 return HAL_BUSY;
1201 return HAL_OK;
1205 * @brief Aborts the MDMA Transfer.
1206 * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1207 * the configuration information for the specified MDMA Channel.
1209 * @note After disabling a MDMA Channel, a check for wait until the MDMA Channel is
1210 * effectively disabled is added. If a Channel is disabled
1211 * while a data transfer is ongoing, the current data will be transferred
1212 * and the Channel will be effectively disabled only after the transfer of
1213 * this single data is finished.
1214 * @retval HAL status
1216 HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma)
1218 uint32_t tickstart = HAL_GetTick();
1220 /* Check the MDMA peripheral handle */
1221 if(hmdma == NULL)
1223 return HAL_ERROR;
1226 if(HAL_MDMA_STATE_BUSY != hmdma->State)
1228 hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1230 /* Process Unlocked */
1231 __HAL_UNLOCK(hmdma);
1233 return HAL_ERROR;
1235 else
1237 /* Disable all the transfer interrupts */
1238 __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
1240 /* Disable the channel */
1241 __HAL_MDMA_DISABLE(hmdma);
1243 /* Check if the MDMA Channel is effectively disabled */
1244 while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
1246 /* Check for the Timeout */
1247 if( (HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
1249 /* Update error code */
1250 hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
1252 /* Process Unlocked */
1253 __HAL_UNLOCK(hmdma);
1255 /* Change the MDMA state */
1256 hmdma->State = HAL_MDMA_STATE_ERROR;
1258 return HAL_ERROR;
1262 /* Clear all interrupt flags */
1263 __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC));
1265 /* Process Unlocked */
1266 __HAL_UNLOCK(hmdma);
1268 /* Change the MDMA state*/
1269 hmdma->State = HAL_MDMA_STATE_READY;
1272 return HAL_OK;
1276 * @brief Aborts the MDMA Transfer in Interrupt mode.
1277 * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1278 * the configuration information for the specified MDMA Channel.
1279 * @retval HAL status
1281 HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma)
1283 /* Check the MDMA peripheral handle */
1284 if(hmdma == NULL)
1286 return HAL_ERROR;
1289 if(HAL_MDMA_STATE_BUSY != hmdma->State)
1291 /* No transfer ongoing */
1292 hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1294 return HAL_ERROR;
1296 else
1298 /* Set Abort State */
1299 hmdma->State = HAL_MDMA_STATE_ABORT;
1301 /* Disable the stream */
1302 __HAL_MDMA_DISABLE(hmdma);
1305 return HAL_OK;
1309 * @brief Polling for transfer complete.
1310 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1311 * the configuration information for the specified MDMA Channel.
1312 * @param CompleteLevel: Specifies the MDMA level complete.
1313 * @param Timeout: Timeout duration.
1314 * @retval HAL status
1316 HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
1318 uint32_t levelFlag, errorFlag;
1319 uint32_t tickstart;
1321 /* Check the parameters */
1322 assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel));
1324 /* Check the MDMA peripheral handle */
1325 if(hmdma == NULL)
1327 return HAL_ERROR;
1330 if(HAL_MDMA_STATE_BUSY != hmdma->State)
1332 /* No transfer ongoing */
1333 hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1335 return HAL_ERROR;
1338 /* Get the level transfer complete flag */
1339 levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER) ? MDMA_FLAG_CTC : \
1340 (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \
1341 (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT : \
1342 MDMA_FLAG_BRT);
1345 /* Get timeout */
1346 tickstart = HAL_GetTick();
1348 while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U)
1350 if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
1352 /* Get the transfer error source flag */
1353 errorFlag = hmdma->Instance->CESR;
1355 if((errorFlag & MDMA_CESR_TED) == 0U)
1357 /* Update error code : Read Transfer error */
1358 hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
1360 else
1362 /* Update error code : Write Transfer error */
1363 hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
1366 if((errorFlag & MDMA_CESR_TEMD) != 0U)
1368 /* Update error code : Error Mask Data */
1369 hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
1372 if((errorFlag & MDMA_CESR_TELD) != 0U)
1374 /* Update error code : Error Linked list */
1375 hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
1378 if((errorFlag & MDMA_CESR_ASE) != 0U)
1380 /* Update error code : Address/Size alignment error */
1381 hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
1384 if((errorFlag & MDMA_CESR_BSE) != 0U)
1386 /* Update error code : Block Size error */
1387 hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
1390 (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */
1393 Note that the Abort function will
1394 - Clear all transfer flags
1395 - Unlock
1396 - Set the State
1399 return HAL_ERROR;
1403 /* Check for the Timeout */
1404 if(Timeout != HAL_MAX_DELAY)
1406 if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
1408 /* Update error code */
1409 hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
1411 (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */
1414 Note that the Abort function will
1415 - Clear all transfer flags
1416 - Unlock
1417 - Set the State
1420 return HAL_ERROR;
1425 /* Clear the transfer level flag */
1426 if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)
1428 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
1431 else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER)
1433 __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT));
1436 else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER)
1438 __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT));
1440 else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER)
1442 __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC));
1444 /* Process unlocked */
1445 __HAL_UNLOCK(hmdma);
1447 hmdma->State = HAL_MDMA_STATE_READY;
1449 else
1451 return HAL_ERROR;
1454 return HAL_OK;
1458 * @brief Generate an MDMA SW request trigger to activate the request on the given Channel.
1459 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1460 * the configuration information for the specified MDMA Stream.
1461 * @retval HAL status
1463 HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma)
1465 uint32_t request_mode;
1467 /* Check the MDMA peripheral handle */
1468 if(hmdma == NULL)
1470 return HAL_ERROR;
1473 /* Get the softawre request mode */
1474 request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM;
1476 if((hmdma->Instance->CCR & MDMA_CCR_EN) == 0U)
1478 /* if no Transfer on going (MDMA enable bit not set) retrun error */
1479 hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
1481 return HAL_ERROR;
1483 else if(((hmdma->Instance->CISR & MDMA_CISR_CRQA) != 0U) || (request_mode == 0U))
1485 /* if an MDMA ongoing request has not yet end or if request mode is not SW request retrun error */
1486 hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY;
1488 return HAL_ERROR;
1490 else
1492 /* Set the SW request bit to activate the request on the Channel */
1493 hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
1495 return HAL_OK;
1500 * @brief Handles MDMA interrupt request.
1501 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1502 * the configuration information for the specified MDMA Channel.
1503 * @retval None
1505 void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma)
1507 __IO uint32_t count = 0;
1508 uint32_t timeout = SystemCoreClock / 9600U;
1510 uint32_t generalIntFlag, errorFlag;
1512 /* General Interrupt Flag management ****************************************/
1513 generalIntFlag = 1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU);
1514 if((MDMA->GISR0 & generalIntFlag) == 0U)
1516 return; /* the General interrupt flag for the current channel is down , nothing to do */
1519 /* Transfer Error Interrupt management ***************************************/
1520 if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
1522 if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U)
1524 /* Disable the transfer error interrupt */
1525 __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE);
1527 /* Get the transfer error source flag */
1528 errorFlag = hmdma->Instance->CESR;
1530 if((errorFlag & MDMA_CESR_TED) == 0U)
1532 /* Update error code : Read Transfer error */
1533 hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
1535 else
1537 /* Update error code : Write Transfer error */
1538 hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
1541 if((errorFlag & MDMA_CESR_TEMD) != 0U)
1543 /* Update error code : Error Mask Data */
1544 hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
1547 if((errorFlag & MDMA_CESR_TELD) != 0U)
1549 /* Update error code : Error Linked list */
1550 hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
1553 if((errorFlag & MDMA_CESR_ASE) != 0U)
1555 /* Update error code : Address/Size alignment error */
1556 hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
1559 if((errorFlag & MDMA_CESR_BSE) != 0U)
1561 /* Update error code : Block Size error error */
1562 hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
1565 /* Clear the transfer error flags */
1566 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE);
1570 /* Buffer Transfer Complete Interrupt management ******************************/
1571 if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U))
1573 if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U)
1575 /* Clear the buffer transfer complete flag */
1576 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
1578 if(hmdma->XferBufferCpltCallback != NULL)
1580 /* Buffer transfer callback */
1581 hmdma->XferBufferCpltCallback(hmdma);
1586 /* Block Transfer Complete Interrupt management ******************************/
1587 if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U))
1589 if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U)
1591 /* Clear the block transfer complete flag */
1592 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT);
1594 if(hmdma->XferBlockCpltCallback != NULL)
1596 /* Block transfer callback */
1597 hmdma->XferBlockCpltCallback(hmdma);
1602 /* Repeated Block Transfer Complete Interrupt management ******************************/
1603 if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U))
1605 if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U)
1607 /* Clear the repeat block transfer complete flag */
1608 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT);
1610 if(hmdma->XferRepeatBlockCpltCallback != NULL)
1612 /* Repeated Block transfer callback */
1613 hmdma->XferRepeatBlockCpltCallback(hmdma);
1618 /* Channel Transfer Complete Interrupt management ***********************************/
1619 if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U))
1621 if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U)
1623 /* Disable all the transfer interrupts */
1624 __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
1626 if(HAL_MDMA_STATE_ABORT == hmdma->State)
1628 /* Process Unlocked */
1629 __HAL_UNLOCK(hmdma);
1631 /* Change the DMA state */
1632 hmdma->State = HAL_MDMA_STATE_READY;
1634 if(hmdma->XferAbortCallback != NULL)
1636 hmdma->XferAbortCallback(hmdma);
1638 return;
1641 /* Clear the Channel Transfer Complete flag */
1642 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC);
1644 /* Process Unlocked */
1645 __HAL_UNLOCK(hmdma);
1647 /* Change MDMA peripheral state */
1648 hmdma->State = HAL_MDMA_STATE_READY;
1650 if(hmdma->XferCpltCallback != NULL)
1652 /* Channel Transfer Complete callback */
1653 hmdma->XferCpltCallback(hmdma);
1658 /* manage error case */
1659 if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE)
1661 hmdma->State = HAL_MDMA_STATE_ABORT;
1663 /* Disable the channel */
1664 __HAL_MDMA_DISABLE(hmdma);
1668 if (++count > timeout)
1670 break;
1673 while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U);
1675 /* Process Unlocked */
1676 __HAL_UNLOCK(hmdma);
1678 if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
1680 /* Change the MDMA state to error if MDMA disable fails */
1681 hmdma->State = HAL_MDMA_STATE_ERROR;
1683 else
1685 /* Change the MDMA state to Ready if MDMA disable success */
1686 hmdma->State = HAL_MDMA_STATE_READY;
1690 if (hmdma->XferErrorCallback != NULL)
1692 /* Transfer error callback */
1693 hmdma->XferErrorCallback(hmdma);
1699 * @}
1702 /** @addtogroup MDMA_Exported_Functions_Group4
1704 @verbatim
1705 ===============================================================================
1706 ##### State and Errors functions #####
1707 ===============================================================================
1708 [..]
1709 This subsection provides functions allowing to
1710 (+) Check the MDMA state
1711 (+) Get error code
1713 @endverbatim
1714 * @{
1718 * @brief Returns the MDMA state.
1719 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1720 * the configuration information for the specified MDMA Channel.
1721 * @retval HAL state
1723 HAL_MDMA_StateTypeDef HAL_MDMA_GetState(MDMA_HandleTypeDef *hmdma)
1725 return hmdma->State;
1729 * @brief Return the MDMA error code
1730 * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
1731 * the configuration information for the specified MDMA Channel.
1732 * @retval MDMA Error Code
1734 uint32_t HAL_MDMA_GetError(MDMA_HandleTypeDef *hmdma)
1736 return hmdma->ErrorCode;
1740 * @}
1744 * @}
1747 /** @addtogroup MDMA_Private_Functions
1748 * @{
1752 * @brief Sets the MDMA Transfer parameter.
1753 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1754 * the configuration information for the specified MDMA Channel.
1755 * @param SrcAddress: The source memory Buffer address
1756 * @param DstAddress: The destination memory Buffer address
1757 * @param BlockDataLength : The length of a block transfer in bytes
1758 * @param BlockCount: The number of blocks to be transfered
1759 * @retval HAL status
1761 static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
1763 uint32_t addressMask;
1765 /* Configure the MDMA Channel data length */
1766 MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT));
1768 /* Configure the MDMA block repeat count */
1769 MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC);
1771 /* Clear all interrupt flags */
1772 __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF);
1774 /* Configure MDMA Channel destination address */
1775 hmdma->Instance->CDAR = DstAddress;
1777 /* Configure MDMA Channel Source address */
1778 hmdma->Instance->CSAR = SrcAddress;
1780 addressMask = SrcAddress & 0xFF000000U;
1781 if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
1783 /*The AHBSbus is used as source (read operation) on channel x */
1784 hmdma->Instance->CTBR |= MDMA_CTBR_SBUS;
1786 else
1788 /*The AXI bus is used as source (read operation) on channel x */
1789 hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS);
1792 addressMask = DstAddress & 0xFF000000U;
1793 if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
1795 /*The AHB bus is used as destination (write operation) on channel x */
1796 hmdma->Instance->CTBR |= MDMA_CTBR_DBUS;
1798 else
1800 /*The AXI bus is used as destination (write operation) on channel x */
1801 hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS);
1804 /* Set the linked list register to the first node of the list */
1805 hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
1809 * @brief Initializes the MDMA handle according to the specified
1810 * parameters in the MDMA_InitTypeDef
1811 * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
1812 * the configuration information for the specified MDMA Channel.
1813 * @retval None
1815 static void MDMA_Init(MDMA_HandleTypeDef *hmdma)
1817 uint32_t blockoffset;
1819 /* Prepare the MDMA Channel configuration */
1820 hmdma->Instance->CCR = hmdma->Init.Priority | hmdma->Init.Endianness;
1822 /* Write new CTCR Register value */
1823 hmdma->Instance->CTCR = hmdma->Init.SourceInc | hmdma->Init.DestinationInc | \
1824 hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize | \
1825 hmdma->Init.DataAlignment | hmdma->Init.SourceBurst | \
1826 hmdma->Init.DestBurst | \
1827 ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
1828 hmdma->Init.TransferTriggerMode;
1830 /* If SW request set the CTCR register to SW Request Mode */
1831 if(hmdma->Init.Request == MDMA_REQUEST_SW)
1834 -If the request is done by SW : BWM could be set to 1 or 0.
1835 -If the request is done by a peripheral :
1836 If mask address not set (0) => BWM must be set to 0
1837 If mask address set (different than 0) => BWM could be set to 1 or 0
1839 hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM);
1842 /* Reset CBNDTR Register */
1843 hmdma->Instance->CBNDTR = 0;
1845 /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
1846 if(hmdma->Init.SourceBlockAddressOffset < 0)
1848 hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM;
1849 /* Write new CBRUR Register value : source repeat block offset */
1850 blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset);
1851 hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU);
1853 else
1855 /* Write new CBRUR Register value : source repeat block offset */
1856 hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
1859 /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
1860 if(hmdma->Init.DestBlockAddressOffset < 0)
1862 hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM;
1863 /* Write new CBRUR Register value : destination repeat block offset */
1864 blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset);
1865 hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
1867 else
1869 /*write new CBRUR Register value : destination repeat block offset */
1870 hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
1873 /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
1874 if(hmdma->Init.Request != MDMA_REQUEST_SW)
1876 /* Set the HW request in CTRB register */
1877 hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL;
1879 else /* SW request : reset the CTBR register */
1881 hmdma->Instance->CTBR = 0;
1884 /* Write Link Address Register */
1885 hmdma->Instance->CLAR = 0;
1889 * @}
1892 #endif /* HAL_MDMA_MODULE_ENABLED */
1894 * @}
1898 * @}
1901 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/