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