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