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
11 ==============================================================================
12 ##### How to use this driver #####
13 ==============================================================================
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
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).
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 =================================
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 ===================================
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.
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:
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.
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 =============================================
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.
131 (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
136 ******************************************************************************
139 * <h2><center>© 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
157 /** @defgroup MDMA MDMA
158 * @brief MDMA HAL module driver
162 #ifdef HAL_MDMA_MODULE_ENABLED
164 /* Private typedef -----------------------------------------------------------*/
165 /* Private constants ---------------------------------------------------------*/
166 /** @addtogroup MDMA_Private_Constants
169 #define HAL_TIMEOUT_MDMA_ABORT 5U /* 5 ms */
170 #define HAL_MDMA_CHANNEL_SIZE 0x40U /* an MDMA instance channel size is 64 byte */
174 /* Private macro -------------------------------------------------------------*/
175 /* Private variables ---------------------------------------------------------*/
176 /* Private function prototypes -----------------------------------------------*/
177 /** @addtogroup MDMA_Private_Functions_Prototypes
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
);
187 /** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
191 /** @addtogroup MDMA_Exported_Functions_Group1
194 ===============================================================================
195 ##### Initialization and de-initialization functions #####
196 ===============================================================================
198 This section provides functions allowing to :
199 Initialize and de-initialize the MDMA channel.
200 Register and Unregister MDMA callbacks
202 The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in
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.
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.
219 HAL_StatusTypeDef
HAL_MDMA_Init(MDMA_HandleTypeDef
*hmdma
)
221 uint32_t tickstart
= HAL_GetTick();
223 /* Check the MDMA peripheral handle */
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 */
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
;
272 /* Initialize the MDMA channel registers */
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
;
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.
295 HAL_StatusTypeDef
HAL_MDMA_DeInit(MDMA_HandleTypeDef
*hmdma
)
298 /* Check the MDMA peripheral handle */
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
;
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.
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 */
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
;
382 hmdma
->Instance
->CTCR
|= MDMA_CTCR_BWM
;
387 /* Return error status */
393 /* Return error 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.
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 */
423 if(HAL_MDMA_STATE_READY
== hmdma
->State
)
427 case HAL_MDMA_XFER_CPLT_CB_ID
:
428 hmdma
->XferCpltCallback
= pCallback
;
431 case HAL_MDMA_XFER_BUFFERCPLT_CB_ID
:
432 hmdma
->XferBufferCpltCallback
= pCallback
;
435 case HAL_MDMA_XFER_BLOCKCPLT_CB_ID
:
436 hmdma
->XferBlockCpltCallback
= pCallback
;
439 case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID
:
440 hmdma
->XferRepeatBlockCpltCallback
= pCallback
;
443 case HAL_MDMA_XFER_ERROR_CB_ID
:
444 hmdma
->XferErrorCallback
= pCallback
;
447 case HAL_MDMA_XFER_ABORT_CB_ID
:
448 hmdma
->XferAbortCallback
= pCallback
;
457 /* Return error 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.
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 */
488 if(HAL_MDMA_STATE_READY
== hmdma
->State
)
492 case HAL_MDMA_XFER_CPLT_CB_ID
:
493 hmdma
->XferCpltCallback
= NULL
;
496 case HAL_MDMA_XFER_BUFFERCPLT_CB_ID
:
497 hmdma
->XferBufferCpltCallback
= NULL
;
500 case HAL_MDMA_XFER_BLOCKCPLT_CB_ID
:
501 hmdma
->XferBlockCpltCallback
= NULL
;
504 case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID
:
505 hmdma
->XferRepeatBlockCpltCallback
= NULL
;
508 case HAL_MDMA_XFER_ERROR_CB_ID
:
509 hmdma
->XferErrorCallback
= NULL
;
512 case HAL_MDMA_XFER_ABORT_CB_ID
:
513 hmdma
->XferAbortCallback
= NULL
;
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
;
545 /** @addtogroup MDMA_Exported_Functions_Group2
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
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.
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
))
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 */
603 /* Configure the Link Node registers*/
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
;
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
);
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
;
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
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
))
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 */
747 /* Update the Handle last node address */
748 hmdma
->LastLinkedListNodeAddress
= pNewNode
;
750 hmdma
->LinkedListNodeCounter
= 1;
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
;
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
++;
786 /*insert the new node after the pPreviousNode node */
787 pNode
= hmdma
->FirstLinkedListNodeAddress
;
789 while((counter
< hmdma
->LinkedListNodeCounter
) && (nodeInserted
== 0U))
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
++;
803 pNode
= (MDMA_LinkNodeTypeDef
*)pNode
->CLAR
;
807 if(nodeInserted
== 0U)
809 hal_status
= HAL_ERROR
;
816 hal_status
= HAL_ERROR
;
819 /* Process unlocked */
822 hmdma
->State
= HAL_MDMA_STATE_READY
;
828 /* Process unlocked */
831 /* Return error status */
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.
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
))
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;
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))
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
;
919 /* Update the Handle node counter */
920 hmdma
->LinkedListNodeCounter
--;
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 */
938 hmdma
->State
= HAL_MDMA_STATE_READY
;
944 /* Process unlocked */
947 /* Return error status */
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.
958 HAL_StatusTypeDef
HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef
*hmdma
)
960 HAL_StatusTypeDef hal_status
= HAL_OK
;
962 /* Check the MDMA peripheral handle */
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
;
983 /* to enable circular mode Last Node should be connected to first node */
984 hmdma
->LastLinkedListNodeAddress
->CLAR
= (uint32_t)hmdma
->FirstLinkedListNodeAddress
;
988 /* Process unlocked */
991 hmdma
->State
= HAL_MDMA_STATE_READY
;
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 */
1012 /* Process locked */
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
;
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
;
1044 /** @addtogroup MDMA_Exported_Functions_Group3
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
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 */
1085 /* Process locked */
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
;
1113 /* Process unlocked */
1114 __HAL_UNLOCK(hmdma
);
1116 /* Return error status */
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 */
1145 /* Process locked */
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
;
1194 /* Process unlocked */
1195 __HAL_UNLOCK(hmdma
);
1197 /* Return error status */
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 */
1226 if(HAL_MDMA_STATE_BUSY
!= hmdma
->State
)
1228 hmdma
->ErrorCode
= HAL_MDMA_ERROR_NO_XFER
;
1230 /* Process Unlocked */
1231 __HAL_UNLOCK(hmdma
);
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
;
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
;
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 */
1289 if(HAL_MDMA_STATE_BUSY
!= hmdma
->State
)
1291 /* No transfer ongoing */
1292 hmdma
->ErrorCode
= HAL_MDMA_ERROR_NO_XFER
;
1298 /* Set Abort State */
1299 hmdma
->State
= HAL_MDMA_STATE_ABORT
;
1301 /* Disable the stream */
1302 __HAL_MDMA_DISABLE(hmdma
);
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
;
1321 /* Check the parameters */
1322 assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel
));
1324 /* Check the MDMA peripheral handle */
1330 if(HAL_MDMA_STATE_BUSY
!= hmdma
->State
)
1332 /* No transfer ongoing */
1333 hmdma
->ErrorCode
= HAL_MDMA_ERROR_NO_XFER
;
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
: \
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
;
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
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
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
;
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 */
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
;
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
;
1492 /* Set the SW request bit to activate the request on the Channel */
1493 hmdma
->Instance
->CCR
|= MDMA_CCR_SWRQ
;
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.
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
;
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
);
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
)
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
;
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
);
1702 /** @addtogroup MDMA_Exported_Functions_Group4
1705 ===============================================================================
1706 ##### State and Errors functions #####
1707 ===============================================================================
1709 This subsection provides functions allowing to
1710 (+) Check the MDMA state
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.
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
;
1747 /** @addtogroup MDMA_Private_Functions
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
;
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
;
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.
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
);
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
);
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;
1892 #endif /* HAL_MDMA_MODULE_ENABLED */
1901 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/