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