1 /**
2   **********************************************************************************************************************
3   * @file    stm32h5xx_hal_dma.c
4   * @author  MCD Application Team
5   * @brief   This file provides firmware functions to manage the following functionalities of the Direct Memory Access
6   *          (DMA) peripheral:
7   *            + Initialization/De-Initialization Functions
8   *            + I/O Operation Functions
9   *            + State and Errors Functions
10   *            + DMA Attributes Functions
11   *
12   **********************************************************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2022 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   **********************************************************************************************************************
23   @verbatim
24   ======================================================================================================================
25                                  ############### How to use this driver ###############
26   ======================================================================================================================
27     [..]
28       DMA transfer modes are divided to 2 major categories :
29           (+) Normal transfers (legacy)
30           (+) Linked-list transfers
31 
32     [..]
33       Normal transfers mode is initialized via the standard module and linked-list mode is configured via the extended
34       module.
35 
36     [..]
37       Additionally to linked-list capability, all advanced DMA features are managed and configured via the extended
38       module as extensions to normal mode.
39       Advanced features are :
40           (+) Repeated block feature.
41           (+) Trigger feature.
42           (+) Data handling feature.
43 
44     [..]
45       DMA Legacy circular transfer, is replaced by circular linked-list configuration.
46 
47 
48     *** Initialization and De-Initialization ***
49     ============================================
50     [..]
51       For a given channel, enable and configure the peripheral to be connected to the DMA Channel (except for internal
52       SRAM/FLASH memories: no initialization is necessary) please refer to Reference manual for connection between
53       peripherals and DMA requests.
54 
55     [..]
56       For a given channel, use HAL_DMA_Init function to program the required configuration for normal transfer through
57       the following parameters:
58 
59           (+) Request               : Specifies the DMA channel request
60               Request parameters    :
61               (++) can be a value of @ref DMA_Request_Selection
62 
63           (+) BlkHWRequest          : Specifies the Block hardware request mode for DMA channel
64               (++) can be a value of @ref DMA_Block_Request
65 
66           (+) Direction             : Specifies the transfer direction for DMA channel
67               (++) can be a value of @ref DMA_Transfer_Direction
68 
69           (+) SrcInc                : Specifies the source increment mode for the DMA channel
70               (++) can be a value of @ref DMA_Source_Increment_Mode
71 
72           (+) DestInc               : Specifies the destination increment mode for the DMA channel
73               (++) can be a value of @ref DMA_Destination_Increment_Mode
74 
75           (+) SrcDataWidth          : Specifies the source data width for the DMA channel
76               (++) can be a value of @ref DMA_Source_Data_Width
77 
78           (+) DestDataWidth         : Specifies the destination data width for the DMA channel
79               (++) can be a value of @ref DMA_Destination_Data_Width
80 
81           (+) Priority              : Specifies the priority for the DMA channel
82               (++) can be a value of @ref DMA_Priority_Level
83 
84           (+) SrcBurstLength        : Specifies the source burst length (number of beats) for the DMA channel
85               (++) can be a value of between 1 and 64
86 
87           (+) DestBurstLength       : Specifies the destination burst length (number of beats) for the DMA channel
88               (++) can be a value of between 1 and 64
89 
90           (+) TransferAllocatedPort : Specifies the source and destination allocated ports
91               (++) can be a value of @ref DMA_Transfer_Allocated_Port
92 
93           (+) TransferEventMode     : Specifies the transfer event mode for the DMA channel
94               (++) can be a value of @ref DMA_Transfer_Event_Mode
95 
96           (+) Mode                  : Specifies the transfer mode for the DMA channel
97               (++) can be a value of @ref DMA_Transfer_Mode
98 
99 
100     *** Polling mode IO operation ***
101     =================================
102     [..]
103           (+) Use HAL_DMA_Start() to start a DMA normal transfer after the configuration of source address, destination
104               address and the size of data to be transferred.
105 
106           (+) Use HAL_DMA_PollForTransfer() to poll for selected transfer level. In this case a fixed Timeout can be
107               configured by User depending on his application.
108               Transfer level can be :
109               (++) HAL_DMA_HALF_TRANSFER
110               (++) HAL_DMA_FULL_TRANSFER
111               For circular transfer, this API returns an HAL_ERROR with HAL_DMA_ERROR_NOT_SUPPORTED error code.
112 
113           (+) Use HAL_DMA_Abort() function to abort any ongoing DMA transfer in blocking mode.
114               This API returns HAL_ERROR when there is no ongoing transfer or timeout is reached when disabling the DMA
115               channel. (This API should not be called from an interrupt service routine)
116 
117 
118     *** Interrupt mode IO operation ***
119     ===================================
120     [..]
121           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
122 
123           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
124 
125           (+) Use HAL_DMA_RegisterCallback() function to register user callbacks from the following list :
126               (++) XferCpltCallback     : transfer complete callback.
127               (++) XferHalfCpltCallback : half transfer complete callback.
128               (++) XferErrorCallback    : transfer error callback.
129               (++) XferAbortCallback    : transfer abort complete callback.
130               (++) XferSuspendCallback  : transfer suspend complete callback.
131 
132           (+) Use HAL_DMA_Start_IT() to start the DMA transfer after the enable of DMA interrupts and the configuration
133               of source address,destination address and the size of data to be transferred.
134 
135           (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() interrupt subroutine to handle any DMA interrupt.
136 
137           (+) Use HAL_DMA_Abort_IT() function to abort any on-going DMA transfer in non-blocking mode.
138               This API will suspend immediately the DMA channel execution. When the transfer is effectively suspended,
139               an interrupt is generated and HAL_DMA_IRQHandler() will reset the channel and execute the callback
140               XferAbortCallback. (This API could be called from an interrupt service routine)
141 
142 
143     *** State and errors ***
144     ========================
145     [..]
146           (+) Use HAL_DMA_GetState() function to get the DMA state.
147           (+) Use HAL_DMA_GetError() function to get the DMA error code.
148 
149 
150     *** Security and privilege attributes ***
151     =========================================
152     [..]
153           (+) Use HAL_DMA_ConfigChannelAttributes() function to configure DMA channel security and privilege attributes.
154               (++) Security  : at channel level, at source level and at destination level.
155               (++) Privilege : at channel level.
156           (+) Use HAL_DMA_GetConfigChannelAttributes() function to get the DMA channel attributes.
157           (+) Use HAL_DMA_LockChannelAttributes() function to lock the DMA channel security and privilege attributes
158               configuration. This API is called once after each system boot.
159               When this API is called, HAL_DMA_ConfigChannelAttributes() API cannot be used anymore.
160           (+) Use HAL_DMA_GetLockChannelAttributes() function to get the attributes lock status.
161 
162 
163     *** DMA HAL driver macros list ***
164     ==================================
165     [..]
166       Below the list of most used macros in DMA HAL driver.
167 
168           (+) __HAL_DMA_ENABLE        : Enable the specified DMA Channel.
169           (+) __HAL_DMA_DISABLE       : Disable the specified DMA Channel.
170           (+) __HAL_DMA_GET_FLAG      : Get the DMA Channel pending flags.
171           (+) __HAL_DMA_CLEAR_FLAG    : Clear the DMA Channel pending flags.
172           (+) __HAL_DMA_ENABLE_IT     : Enable the specified DMA Channel interrupts.
173           (+) __HAL_DMA_DISABLE_IT    : Disable the specified DMA Channel interrupts.
174           (+) __HAL_DMA_GET_IT_SOURCE : Check whether the specified DMA Channel interrupt has occurred or not.
175 
176     [..]
177      (@) You can refer to the header file of the DMA HAL driver for more useful macros.
178 
179     @endverbatim
180   **********************************************************************************************************************
181   */
182 
183 /* Includes ----------------------------------------------------------------------------------------------------------*/
184 #include "stm32h5xx_hal.h"
185 
186 /** @addtogroup STM32H5xx_HAL_Driver
187   * @{
188   */
189 
190 /** @defgroup DMA DMA
191   * @brief DMA HAL module driver
192   * @{
193   */
194 
195 #ifdef HAL_DMA_MODULE_ENABLED
196 
197 /* Private typedef ---------------------------------------------------------------------------------------------------*/
198 /* Private constants -------------------------------------------------------------------------------------------------*/
199 /* Private macro -----------------------------------------------------------------------------------------------------*/
200 /* Private variables -------------------------------------------------------------------------------------------------*/
201 /* Private function prototypes ---------------------------------------------------------------------------------------*/
202 static void DMA_SetConfig(DMA_HandleTypeDef const *const hdma,
203                           uint32_t SrcAddress,
204                           uint32_t DstAddress,
205                           uint32_t SrcDataSize);
206 static void DMA_Init(DMA_HandleTypeDef const *const hdma);
207 
208 /* Exported functions ------------------------------------------------------------------------------------------------*/
209 
210 /** @addtogroup DMA_Exported_Functions DMA Exported Functions
211   * @{
212   */
213 
214 /** @addtogroup DMA_Exported_Functions_Group1
215   *
216 @verbatim
217   ======================================================================================================================
218                        ############### Initialization and de-initialization functions ###############
219   ======================================================================================================================
220     [..]
221       This section provides functions allowing to initialize and de-initialize the DMA channel in normal mode.
222 
223     [..]
224       (+) The HAL_DMA_Init() function follows the DMA channel configuration procedures as described in reference manual.
225       (+) The HAL_DMA_DeInit() function allows to de-initialize the DMA channel.
226 
227 @endverbatim
228   * @{
229   */
230 
231 /**
232   * @brief  Initialize the DMA channel in normal mode according to the specified parameters in the DMA_InitTypeDef and
233   *         create the associated handle.
234   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
235   *                specified DMA Channel.
236   * @retval HAL status.
237   */
HAL_DMA_Init(DMA_HandleTypeDef * const hdma)238 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *const hdma)
239 {
240   /* Get tick number */
241   uint32_t tickstart = HAL_GetTick();
242 
243   /* Check the DMA peripheral handle parameter */
244   if (hdma == NULL)
245   {
246     return HAL_ERROR;
247   }
248 
249   /* Check the parameters */
250   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
251   assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
252   if ((hdma->Init.Direction == DMA_MEMORY_TO_PERIPH) || (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY))
253   {
254     assert_param(IS_DMA_REQUEST(hdma->Init.Request));
255   }
256   assert_param(IS_DMA_BLOCK_HW_REQUEST(hdma->Init.BlkHWRequest));
257   assert_param(IS_DMA_SOURCE_INC(hdma->Init.SrcInc));
258   assert_param(IS_DMA_DESTINATION_INC(hdma->Init.DestInc));
259   assert_param(IS_DMA_SOURCE_DATA_WIDTH(hdma->Init.SrcDataWidth));
260   assert_param(IS_DMA_DESTINATION_DATA_WIDTH(hdma->Init.DestDataWidth));
261   assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
262   assert_param(IS_DMA_TCEM_EVENT_MODE(hdma->Init.TransferEventMode));
263   assert_param(IS_DMA_MODE(hdma->Init.Mode));
264   /* Check DMA channel instance */
265   if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
266   {
267     assert_param(IS_DMA_BURST_LENGTH(hdma->Init.SrcBurstLength));
268     assert_param(IS_DMA_BURST_LENGTH(hdma->Init.DestBurstLength));
269     assert_param(IS_DMA_TRANSFER_ALLOCATED_PORT(hdma->Init.TransferAllocatedPort));
270   }
271 
272   /* Allocate lock resource */
273   __HAL_UNLOCK(hdma);
274 
275   /* Update the DMA channel state */
276   hdma->State = HAL_DMA_STATE_BUSY;
277 
278   /* Disable the DMA channel */
279   __HAL_DMA_DISABLE(hdma);
280 
281   /* Check if the DMA channel is effectively disabled */
282   while ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
283   {
284     /* Check for the Timeout */
285     if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
286     {
287       /* Update the DMA channel error code */
288       hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
289 
290       /* Update the DMA channel state */
291       hdma->State = HAL_DMA_STATE_ERROR;
292 
293       return HAL_ERROR;
294     }
295   }
296 
297   /* Initialize the DMA channel registers */
298   DMA_Init(hdma);
299 
300   /* Update DMA channel operation mode */
301   hdma->Mode = hdma->Init.Mode;
302 
303   /* Update the DMA channel error code */
304   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
305 
306   /* Update the DMA channel state */
307   hdma->State = HAL_DMA_STATE_READY;
308 
309   return HAL_OK;
310 }
311 
312 /**
313   * @brief  DeInitialize the DMA channel when it is configured in normal mode.
314   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
315   *                specified DMA Channel.
316   * @retval HAL status.
317   */
HAL_DMA_DeInit(DMA_HandleTypeDef * const hdma)318 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *const hdma)
319 {
320   DMA_TypeDef *p_dma_instance;
321   uint32_t tickstart = HAL_GetTick();
322 
323   /* Check the DMA peripheral handle parameter */
324   if (hdma == NULL)
325   {
326     return HAL_ERROR;
327   }
328 
329   /* Check the parameters */
330   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
331 
332   /* Get DMA instance */
333   p_dma_instance = GET_DMA_INSTANCE(hdma);
334 
335   /* Disable the selected DMA Channel */
336   __HAL_DMA_DISABLE(hdma);
337 
338   /* Check if the DMA channel is effectively disabled */
339   while ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
340   {
341     /* Check for the Timeout */
342     if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
343     {
344       /* Update the DMA channel error code */
345       hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
346 
347       /* Update the DMA channel state */
348       hdma->State = HAL_DMA_STATE_ERROR;
349 
350       return HAL_ERROR;
351     }
352   }
353 
354   /* Reset DMA Channel registers */
355   hdma->Instance->CLBAR = 0U;
356   hdma->Instance->CCR   = 0U;
357   hdma->Instance->CTR1  = 0U;
358   hdma->Instance->CTR2  = 0U;
359   hdma->Instance->CBR1  = 0U;
360   hdma->Instance->CSAR  = 0U;
361   hdma->Instance->CDAR  = 0U;
362   hdma->Instance->CLLR  = 0U;
363 
364   /* Reset 2D Addressing registers */
365   if (IS_DMA_2D_ADDRESSING_INSTANCE(hdma->Instance) != 0U)
366   {
367     hdma->Instance->CTR3 = 0U;
368     hdma->Instance->CBR2 = 0U;
369   }
370 
371   /* Clear privilege attribute */
372   CLEAR_BIT(p_dma_instance->PRIVCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
373 
374 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
375   /* Clear secure attribute */
376   CLEAR_BIT(p_dma_instance->SECCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
377 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
378 
379   /* Clear all flags */
380   __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
381                               DMA_FLAG_TO));
382 
383   /* Clean all callbacks */
384   hdma->XferCpltCallback     = NULL;
385   hdma->XferHalfCpltCallback = NULL;
386   hdma->XferErrorCallback    = NULL;
387   hdma->XferAbortCallback    = NULL;
388   hdma->XferSuspendCallback  = NULL;
389 
390   /* Clean DMA queue */
391   hdma->LinkedListQueue = NULL;
392 
393   /* Clean DMA parent */
394   if (hdma->Parent != NULL)
395   {
396     hdma->Parent = NULL;
397   }
398 
399   /* Update DMA channel operation mode */
400   hdma->Mode = DMA_NORMAL;
401 
402   /* Update the DMA channel error code */
403   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
404 
405   /* Update the DMA channel state */
406   hdma->State = HAL_DMA_STATE_RESET;
407 
408   /* Release Lock */
409   __HAL_UNLOCK(hdma);
410 
411   return HAL_OK;
412 }
413 /**
414   * @}
415   */
416 
417 /** @addtogroup DMA_Exported_Functions_Group2
418   *
419 @verbatim
420   ======================================================================================================================
421                                 ############### IO operation functions ###############
422   ======================================================================================================================
423     [..]
424       This section provides functions allowing to :
425       (+) Configure the source, destination address and data size and Start DMA transfer in normal mode
426       (+) Abort DMA transfer
427       (+) Poll for transfer complete
428       (+) Handle DMA interrupt request
429       (+) Register and Unregister DMA callbacks
430 
431     [..]
432       (+) The HAL_DMA_Start() function allows to start the DMA channel transfer in normal mode (Blocking mode).
433       (+) The HAL_DMA_Start_IT() function allows to start the DMA channel transfer in normal mode (Non-blocking mode).
434       (+) The HAL_DMA_Abort() function allows to abort any on-going transfer (Blocking mode).
435       (+) The HAL_DMA_Abort_IT() function allows to abort any on-going transfer (Non-blocking mode).
436       (+) The HAL_DMA_PollForTransfer() function allows to poll on half transfer and transfer complete (Blocking mode).
437           This API cannot be used for circular transfers.
438       (+) The HAL_DMA_IRQHandler() function allows to handle any DMA channel interrupt (Non-blocking mode).
439       (+) The HAL_DMA_RegisterCallback() and HAL_DMA_UnRegisterCallback() functions allow respectively to register and
440           unregister user customized callbacks.
441           User callbacks are called under HAL_DMA_IRQHandler().
442 
443 @endverbatim
444   * @{
445   */
446 
447 /**
448   * @brief  Start the DMA channel transfer in normal mode (Blocking mode).
449   * @param  hdma        : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for
450   *                       the specified DMA Channel.
451   * @param  SrcAddress  : The source data address.
452   * @param  DstAddress  : The destination data address.
453   * @param  SrcDataSize : The length of data to be transferred from source to destination in bytes.
454   * @retval HAL status.
455   */
HAL_DMA_Start(DMA_HandleTypeDef * const hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SrcDataSize)456 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *const hdma,
457                                 uint32_t SrcAddress,
458                                 uint32_t DstAddress,
459                                 uint32_t SrcDataSize)
460 {
461   /* Check the DMA peripheral handle parameter */
462   if (hdma == NULL)
463   {
464     return HAL_ERROR;
465   }
466 
467   /* Check the parameters */
468   assert_param(IS_DMA_BLOCK_SIZE(SrcDataSize));
469 
470   /* Process locked */
471   __HAL_LOCK(hdma);
472 
473   /* Check DMA channel state */
474   if (hdma->State == HAL_DMA_STATE_READY)
475   {
476     /* Update the DMA channel state */
477     hdma->State = HAL_DMA_STATE_BUSY;
478 
479     /* Update the DMA channel error code */
480     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
481 
482     /* Configure the source address, destination address, the data size and clear flags */
483     DMA_SetConfig(hdma, SrcAddress, DstAddress, SrcDataSize);
484 
485     /* Enable DMA channel */
486     __HAL_DMA_ENABLE(hdma);
487   }
488   else
489   {
490     /* Update the DMA channel error code */
491     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
492 
493     /* Process unlocked */
494     __HAL_UNLOCK(hdma);
495 
496     return HAL_ERROR;
497   }
498 
499   return HAL_OK;
500 }
501 
502 /**
503   * @brief  Starts the DMA channel transfer in normal mode with interrupts enabled (Non-blocking mode).
504   * @param  hdma         : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
505   *                        specified DMA Channel.
506   * @param  SrcAddress   : The source data address.
507   * @param  DstAddress   : The destination data address.
508   * @param  SrcDataSize  : The length of data to be transferred from source to destination in bytes.
509   * @retval HAL status.
510   */
HAL_DMA_Start_IT(DMA_HandleTypeDef * const hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SrcDataSize)511 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *const hdma,
512                                    uint32_t SrcAddress,
513                                    uint32_t DstAddress,
514                                    uint32_t SrcDataSize)
515 {
516   /* Check the DMA peripheral handle parameter */
517   if (hdma == NULL)
518   {
519     return HAL_ERROR;
520   }
521 
522   /* Check the parameters */
523   assert_param(IS_DMA_BLOCK_SIZE(SrcDataSize));
524 
525   /* Process locked */
526   __HAL_LOCK(hdma);
527 
528   /* Check DMA channel state */
529   if (hdma->State == HAL_DMA_STATE_READY)
530   {
531     /* Update the DMA channel state */
532     hdma->State = HAL_DMA_STATE_BUSY;
533 
534     /* Update the DMA channel error code */
535     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
536 
537     /* Configure the source address, destination address, the data size and clear flags */
538     DMA_SetConfig(hdma, SrcAddress, DstAddress, SrcDataSize);
539 
540     /* Enable common interrupts: Transfer Complete and Transfer Errors ITs */
541     __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_DTE | DMA_IT_ULE | DMA_IT_USE | DMA_IT_TO));
542 
543     /* Check half transfer complete callback */
544     if (hdma->XferHalfCpltCallback != NULL)
545     {
546       /* If Half Transfer complete callback is set, enable the corresponding IT */
547       __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
548     }
549 
550     /* Check Half suspend callback */
551     if (hdma->XferSuspendCallback != NULL)
552     {
553       /* If Transfer suspend callback is set, enable the corresponding IT */
554       __HAL_DMA_ENABLE_IT(hdma, DMA_IT_SUSP);
555     }
556 
557     /* Enable DMA channel */
558     __HAL_DMA_ENABLE(hdma);
559   }
560   else
561   {
562     /* Update the DMA channel error code */
563     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
564 
565     /* Process unlocked */
566     __HAL_UNLOCK(hdma);
567 
568     return HAL_ERROR;
569   }
570 
571   return HAL_OK;
572 }
573 
574 /**
575   * @brief  Abort any on-going DMA channel transfer (Blocking mode).
576   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
577   *                specified DMA Channel.
578   * @note   After suspending a DMA channel, a wait until the DMA channel is effectively stopped is added. If a channel
579   *         is suspended while a data transfer is on-going, the current data will be transferred and the channel will be
580   *         effectively suspended only after the transfer of any on-going data is finished.
581   * @retval HAL status.
582   */
HAL_DMA_Abort(DMA_HandleTypeDef * const hdma)583 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *const hdma)
584 {
585   /* Get tick number */
586   uint32_t tickstart =  HAL_GetTick();
587 
588   /* Check the DMA peripheral handle parameter */
589   if (hdma == NULL)
590   {
591     return HAL_ERROR;
592   }
593 
594   /* Check DMA channel state */
595   if (hdma->State != HAL_DMA_STATE_BUSY)
596   {
597     /* Update the DMA channel error code */
598     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
599 
600     /* Process Unlocked */
601     __HAL_UNLOCK(hdma);
602 
603     return HAL_ERROR;
604   }
605   else
606   {
607     /* Suspend the channel */
608     hdma->Instance->CCR |= DMA_CCR_SUSP;
609 
610     /* Update the DMA channel state */
611     hdma->State = HAL_DMA_STATE_SUSPEND;
612 
613     /* Check if the DMA Channel is suspended */
614     while ((hdma->Instance->CSR & DMA_CSR_SUSPF) == 0U)
615     {
616       /* Check for the Timeout */
617       if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
618       {
619         /* Update the DMA channel error code */
620         hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
621 
622         /* Update the DMA channel state */
623         hdma->State = HAL_DMA_STATE_ERROR;
624 
625         /* Check DMA channel transfer mode */
626         if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
627         {
628           /* Update the linked-list queue state */
629           hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
630         }
631 
632         /* Process Unlocked */
633         __HAL_UNLOCK(hdma);
634 
635         return HAL_ERROR;
636       }
637     }
638 
639     /* Reset the channel */
640     hdma->Instance->CCR |= DMA_CCR_RESET;
641 
642     /* Update the DMA channel state */
643     hdma->State = HAL_DMA_STATE_ABORT;
644 
645     /* Clear all status flags */
646     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
647                                 DMA_FLAG_TO));
648 
649     /* Update the DMA channel state */
650     hdma->State = HAL_DMA_STATE_READY;
651 
652     /* Check DMA channel transfer mode */
653     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
654     {
655       /* Update the linked-list queue state */
656       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
657 
658       /* Clear remaining data size to ensure loading linked-list from memory next start */
659       hdma->Instance->CBR1 = 0U;
660     }
661 
662     /* Process Unlocked */
663     __HAL_UNLOCK(hdma);
664   }
665 
666   return HAL_OK;
667 }
668 
669 /**
670   * @brief  Abort any on-going DMA channel transfer in interrupt mode (Non-blocking mode).
671   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
672   *                specified DMA Channel.
673   * @retval HAL status.
674   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * const hdma)675 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *const hdma)
676 {
677   /* Check the DMA peripheral handle parameter */
678   if (hdma == NULL)
679   {
680     return HAL_ERROR;
681   }
682 
683   /* Check DMA channel state */
684   if (hdma->State != HAL_DMA_STATE_BUSY)
685   {
686     /* Update the DMA channel error code */
687     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
688 
689     return HAL_ERROR;
690   }
691   else
692   {
693     /* Update the DMA channel state */
694     hdma->State = HAL_DMA_STATE_ABORT;
695 
696     /* Suspend the channel and activate suspend interrupt */
697     hdma->Instance->CCR |= (DMA_CCR_SUSP | DMA_CCR_SUSPIE);
698   }
699 
700   return HAL_OK;
701 }
702 
703 /**
704   * @brief  Polling for transfer status (Blocking mode).
705   * @param  hdma          : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
706   *                         specified DMA Channel.
707   * @param  CompleteLevel : Specifies the DMA level complete.
708   * @param  Timeout       : Timeout duration.
709   * @retval HAL status
710   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * const hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)711 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *const hdma,
712                                           HAL_DMA_LevelCompleteTypeDef CompleteLevel,
713                                           uint32_t Timeout)
714 {
715   /* Get tick number */
716   uint32_t tickstart = HAL_GetTick();
717   uint32_t level_flag;
718   uint32_t tmp_csr;
719 
720   /* Check the DMA peripheral handle parameter */
721   if (hdma == NULL)
722   {
723     return HAL_ERROR;
724   }
725 
726   /* Check the parameters */
727   assert_param(IS_DMA_LEVEL_COMPLETE(CompleteLevel));
728 
729   /* Check DMA channel state */
730   if (hdma->State != HAL_DMA_STATE_BUSY)
731   {
732     /* Update the DMA channel error code */
733     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
734 
735     /* Process Unlocked */
736     __HAL_UNLOCK(hdma);
737 
738     return HAL_ERROR;
739   }
740 
741   /* Polling mode is not supported in circular mode */
742   if ((hdma->Mode & DMA_LINKEDLIST_CIRCULAR) == DMA_LINKEDLIST_CIRCULAR)
743   {
744     /* Update the DMA channel error code */
745     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
746 
747     return HAL_ERROR;
748   }
749 
750   /* Get the level transfer complete flag */
751   level_flag = ((CompleteLevel == HAL_DMA_FULL_TRANSFER) ? DMA_FLAG_IDLE : DMA_FLAG_HT);
752 
753   /* Get DMA channel status */
754   tmp_csr = hdma->Instance->CSR;
755 
756   while ((tmp_csr & level_flag) == 0U)
757   {
758     /* Check for the timeout */
759     if (Timeout != HAL_MAX_DELAY)
760     {
761       if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
762       {
763         /* Update the DMA channel error code */
764         hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
765 
766         /*
767           If timeout, abort the current transfer.
768           Note that the Abort function will
769           - Clear all transfer flags.
770           - Unlock.
771           - Set the State.
772         */
773         (void)HAL_DMA_Abort(hdma);
774 
775         return HAL_ERROR;
776       }
777     }
778 
779     /* Get a newer CSR register value */
780     tmp_csr = hdma->Instance->CSR;
781   }
782 
783   /* Check trigger overrun flag */
784   if ((tmp_csr & DMA_FLAG_TO) != 0U)
785   {
786     /* Update the DMA channel error code */
787     hdma->ErrorCode |= HAL_DMA_ERROR_TO;
788 
789     /* Clear the error flag */
790     __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_TO);
791   }
792 
793   /* Check error flags */
794   if ((tmp_csr & (DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE)) != 0U)
795   {
796     /* Check the data transfer error flag */
797     if ((tmp_csr & DMA_FLAG_DTE) != 0U)
798     {
799       /* Update the DMA channel error code */
800       hdma->ErrorCode |= HAL_DMA_ERROR_DTE;
801 
802       /* Clear the error flag */
803       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_DTE);
804     }
805 
806     /* Check the update link error flag */
807     if ((tmp_csr & DMA_FLAG_ULE) != 0U)
808     {
809       /* Update the DMA channel error code */
810       hdma->ErrorCode |= HAL_DMA_ERROR_ULE;
811 
812       /* Clear the error flag */
813       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_ULE);
814     }
815 
816     /* Check the user setting error flag */
817     if ((tmp_csr & DMA_FLAG_USE) != 0U)
818     {
819       /* Update the DMA channel error code */
820       hdma->ErrorCode |= HAL_DMA_ERROR_USE;
821 
822       /* Clear the error flag */
823       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_USE);
824     }
825 
826     /* Reset the channel */
827     hdma->Instance->CCR |= DMA_CCR_RESET;
828 
829     /* Update the DMA channel state */
830     hdma->State = HAL_DMA_STATE_READY;
831 
832     /* Check DMA channel transfer mode */
833     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
834     {
835       /* Update the linked-list queue state */
836       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
837     }
838 
839     /* Process Unlocked */
840     __HAL_UNLOCK(hdma);
841 
842     return HAL_ERROR;
843   }
844 
845   /* Clear the transfer level flag */
846   if (CompleteLevel == HAL_DMA_HALF_TRANSFER)
847   {
848     /* Clear the Half Transfer flag */
849     __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_HT);
850   }
851   else if (CompleteLevel == HAL_DMA_FULL_TRANSFER)
852   {
853     /* Clear the transfer flags */
854     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT));
855 
856     /* Update the DMA channel state */
857     hdma->State = HAL_DMA_STATE_READY;
858 
859     /* Check DMA channel transfer mode */
860     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
861     {
862       /* Update the linked-list queue state */
863       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
864     }
865 
866     /* Process unlocked */
867     __HAL_UNLOCK(hdma);
868   }
869   else
870   {
871     return HAL_ERROR;
872   }
873 
874   return HAL_OK;
875 }
876 
877 /**
878   * @brief  Handle DMA interrupt request (Non-blocking mode).
879   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
880   *                specified DMA Channel.
881   * @retval None.
882   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * const hdma)883 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *const hdma)
884 {
885   DMA_TypeDef *p_dma_instance = GET_DMA_INSTANCE(hdma);
886   uint32_t global_it_flag =  1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
887 
888   /* Global Interrupt Flag management *********************************************************************************/
889   if (IS_DMA_GLOBAL_ACTIVE_FLAG(p_dma_instance, global_it_flag) == 0U)
890   {
891     return; /* the global interrupt flag for the current channel is down , nothing to do */
892   }
893 
894   /* Data Transfer Error Interrupt management *************************************************************************/
895   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_DTE) != 0U))
896   {
897     /* Check if interrupt source is enabled */
898     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DTE) != 0U)
899     {
900       /* Clear the transfer error flag */
901       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_DTE);
902 
903       /* Update the DMA channel error code */
904       hdma->ErrorCode |= HAL_DMA_ERROR_DTE;
905     }
906   }
907 
908   /* Update Linked-list Error Interrupt management ********************************************************************/
909   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_ULE) != 0U))
910   {
911     /* Check if interrupt source is enabled */
912     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_ULE) != 0U)
913     {
914       /* Clear the update linked-list error flag */
915       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_ULE);
916 
917       /* Update the DMA channel error code */
918       hdma->ErrorCode |= HAL_DMA_ERROR_ULE;
919     }
920   }
921 
922   /* User Setting Error Interrupt management **************************************************************************/
923   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_USE) != 0U))
924   {
925     /* Check if interrupt source is enabled */
926     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_USE) != 0U)
927     {
928       /* Clear the user setting error flag */
929       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_USE);
930 
931       /* Update the DMA channel error code */
932       hdma->ErrorCode |= HAL_DMA_ERROR_USE;
933     }
934   }
935 
936   /* Trigger Overrun Interrupt management *****************************************************************************/
937   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_TO) != 0U))
938   {
939     /* Check if interrupt source is enabled */
940     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TO) != 0U)
941     {
942       /* Clear the trigger overrun flag */
943       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_TO);
944 
945       /* Update the DMA channel error code */
946       hdma->ErrorCode |= HAL_DMA_ERROR_TO;
947     }
948   }
949 
950   /* Half Transfer Complete Interrupt management **********************************************************************/
951   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_HT) != 0U))
952   {
953     /* Check if interrupt source is enabled */
954     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U)
955     {
956       /* Clear the half transfer flag */
957       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_HT);
958 
959       /* Check half transfer complete callback */
960       if (hdma->XferHalfCpltCallback != NULL)
961       {
962         /* Half transfer callback */
963         hdma->XferHalfCpltCallback(hdma);
964       }
965     }
966   }
967 
968   /* Suspend Transfer Interrupt management ****************************************************************************/
969   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_SUSP) != 0U))
970   {
971     /* Check if interrupt source is enabled */
972     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_SUSP) != 0U)
973     {
974       /* Clear the block transfer complete flag */
975       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_SUSP);
976 
977       /* Check DMA channel state */
978       if (hdma->State == HAL_DMA_STATE_ABORT)
979       {
980         /* Disable the suspend transfer interrupt */
981         __HAL_DMA_DISABLE_IT(hdma, DMA_IT_SUSP);
982 
983         /* Reset the channel internal state and reset the FIFO */
984         hdma->Instance->CCR |= DMA_CCR_RESET;
985 
986         if ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
987         {
988           /* Update the DMA channel state */
989           hdma->State = HAL_DMA_STATE_ERROR;
990         }
991         else
992         {
993           /* Update the DMA channel state */
994           hdma->State = HAL_DMA_STATE_READY;
995         }
996 
997         /* Check DMA channel transfer mode */
998         if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
999         {
1000           /* Update the linked-list queue state */
1001           hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
1002         }
1003 
1004         /* Process Unlocked */
1005         __HAL_UNLOCK(hdma);
1006 
1007         /* Check transfer abort callback */
1008         if (hdma->XferAbortCallback != NULL)
1009         {
1010           /* Transfer abort callback */
1011           hdma->XferAbortCallback(hdma);
1012         }
1013 
1014         return;
1015       }
1016       else
1017       {
1018         /* Update the DMA channel state */
1019         hdma->State = HAL_DMA_STATE_SUSPEND;
1020 
1021         /* Check transfer suspend callback */
1022         if (hdma->XferSuspendCallback != NULL)
1023         {
1024           /* Transfer suspend callback */
1025           hdma->XferSuspendCallback(hdma);
1026         }
1027       }
1028     }
1029   }
1030 
1031   /* Transfer Complete Interrupt management ***************************************************************************/
1032   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_TC) != 0U))
1033   {
1034     /* Check if interrupt source is enabled */
1035     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U)
1036     {
1037       /* Check DMA channel transfer mode */
1038       if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1039       {
1040         /* If linked-list transfer */
1041         if (hdma->Instance->CLLR == 0U)
1042         {
1043           if (hdma->Instance->CBR1 == 0U)
1044           {
1045             /* Update the DMA channel state */
1046             hdma->State = HAL_DMA_STATE_READY;
1047 
1048             /* Update the linked-list queue state */
1049             hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
1050           }
1051         }
1052       }
1053       else
1054       {
1055         /* If normal transfer */
1056         if (hdma->Instance->CBR1 == 0U)
1057         {
1058           /* Update the DMA channel state */
1059           hdma->State = HAL_DMA_STATE_READY;
1060         }
1061       }
1062 
1063       /* Clear TC and HT transfer flags */
1064       __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT));
1065 
1066       /* Process Unlocked */
1067       __HAL_UNLOCK(hdma);
1068 
1069       /* Check transfer complete callback */
1070       if (hdma->XferCpltCallback != NULL)
1071       {
1072         /* Channel Transfer Complete callback */
1073         hdma->XferCpltCallback(hdma);
1074       }
1075     }
1076   }
1077 
1078   /* Manage error case ************************************************************************************************/
1079   if (hdma->ErrorCode != HAL_DMA_ERROR_NONE)
1080   {
1081     /* Reset the channel internal state and reset the FIFO */
1082     hdma->Instance->CCR |= DMA_CCR_RESET;
1083 
1084     if ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
1085     {
1086       /* Update the DMA channel state */
1087       hdma->State = HAL_DMA_STATE_ERROR;
1088     }
1089     else
1090     {
1091       /* Update the DMA channel state */
1092       hdma->State = HAL_DMA_STATE_READY;
1093     }
1094 
1095     /* Check DMA channel transfer mode */
1096     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1097     {
1098       /* Update the linked-list queue state */
1099       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
1100     }
1101 
1102     /* Process Unlocked */
1103     __HAL_UNLOCK(hdma);
1104 
1105     /* Check transfer error callback */
1106     if (hdma->XferErrorCallback != NULL)
1107     {
1108       /* Transfer error callback */
1109       hdma->XferErrorCallback(hdma);
1110     }
1111   }
1112 }
1113 
1114 /**
1115   * @brief  Register callback according to specified ID.
1116   * @param  hdma       : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1117   *                      specified DMA Channel.
1118   * @param  CallbackID : User Callback identifier which could be a value of HAL_DMA_CallbackIDTypeDef enumeration.
1119   * @param  pCallback  : Pointer to private callback function.
1120   * @retval HAL status.
1121   */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * const hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* const pCallback)(DMA_HandleTypeDef * const _hdma))1122 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *const hdma,
1123                                            HAL_DMA_CallbackIDTypeDef CallbackID,
1124                                            void (*const pCallback)(DMA_HandleTypeDef *const _hdma))
1125 {
1126   HAL_StatusTypeDef status = HAL_OK;
1127 
1128   /* Check the DMA peripheral handle parameter */
1129   if (hdma == NULL)
1130   {
1131     return HAL_ERROR;
1132   }
1133 
1134   /* Process locked */
1135   __HAL_LOCK(hdma);
1136 
1137   /* Check DMA channel state */
1138   if (hdma->State == HAL_DMA_STATE_READY)
1139   {
1140     /* Check callback ID */
1141     switch (CallbackID)
1142     {
1143       case HAL_DMA_XFER_CPLT_CB_ID:
1144       {
1145         /* Register transfer complete callback */
1146         hdma->XferCpltCallback = pCallback;
1147         break;
1148       }
1149 
1150       case HAL_DMA_XFER_HALFCPLT_CB_ID:
1151       {
1152         /* Register half transfer callback */
1153         hdma->XferHalfCpltCallback = pCallback;
1154         break;
1155       }
1156 
1157       case HAL_DMA_XFER_ERROR_CB_ID:
1158       {
1159         /* Register transfer error callback */
1160         hdma->XferErrorCallback = pCallback;
1161         break;
1162       }
1163 
1164       case HAL_DMA_XFER_ABORT_CB_ID:
1165       {
1166         /* Register abort callback */
1167         hdma->XferAbortCallback = pCallback;
1168         break;
1169       }
1170 
1171       case HAL_DMA_XFER_SUSPEND_CB_ID:
1172       {
1173         /* Register suspend callback */
1174         hdma->XferSuspendCallback = pCallback;
1175         break;
1176       }
1177 
1178       default:
1179       {
1180         /* Update error status */
1181         status = HAL_ERROR;
1182         break;
1183       }
1184     }
1185   }
1186   else
1187   {
1188     /* Update error status */
1189     status =  HAL_ERROR;
1190   }
1191 
1192   /* Release Lock */
1193   __HAL_UNLOCK(hdma);
1194 
1195   return status;
1196 }
1197 
1198 /**
1199   * @brief  Unregister callback according to specified ID.
1200   * @param  hdma       : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1201   *                      specified DMA Channel.
1202   * @param  CallbackID : User Callback identifier which could be a value of HAL_DMA_CallbackIDTypeDef enum.
1203   * @retval HAL status.
1204   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * const hdma,HAL_DMA_CallbackIDTypeDef CallbackID)1205 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *const hdma,
1206                                              HAL_DMA_CallbackIDTypeDef CallbackID)
1207 {
1208   HAL_StatusTypeDef status = HAL_OK;
1209 
1210   /* Check the DMA peripheral handle parameter */
1211   if (hdma == NULL)
1212   {
1213     return HAL_ERROR;
1214   }
1215 
1216   /* Process locked */
1217   __HAL_LOCK(hdma);
1218 
1219   /* Check DMA channel state */
1220   if (hdma->State == HAL_DMA_STATE_READY)
1221   {
1222     /* Check callback ID */
1223     switch (CallbackID)
1224     {
1225       case HAL_DMA_XFER_CPLT_CB_ID:
1226       {
1227         /* UnRegister transfer complete callback */
1228         hdma->XferCpltCallback = NULL;
1229         break;
1230       }
1231 
1232       case HAL_DMA_XFER_HALFCPLT_CB_ID:
1233       {
1234         /* UnRegister half transfer callback */
1235         hdma->XferHalfCpltCallback = NULL;
1236         break;
1237       }
1238 
1239       case HAL_DMA_XFER_ERROR_CB_ID:
1240       {
1241         /* UnRegister transfer error callback */
1242         hdma->XferErrorCallback = NULL;
1243         break;
1244       }
1245 
1246       case HAL_DMA_XFER_ABORT_CB_ID:
1247       {
1248         /* UnRegister abort callback */
1249         hdma->XferAbortCallback = NULL;
1250         break;
1251       }
1252 
1253       case HAL_DMA_XFER_SUSPEND_CB_ID:
1254       {
1255         /* UnRegister suspend callback */
1256         hdma->XferSuspendCallback = NULL;
1257         break;
1258       }
1259 
1260       case HAL_DMA_XFER_ALL_CB_ID:
1261       {
1262         /* UnRegister all available callbacks */
1263         hdma->XferCpltCallback     = NULL;
1264         hdma->XferHalfCpltCallback = NULL;
1265         hdma->XferErrorCallback    = NULL;
1266         hdma->XferAbortCallback    = NULL;
1267         hdma->XferSuspendCallback  = NULL;
1268         break;
1269       }
1270 
1271       default:
1272       {
1273         /* Update error status */
1274         status = HAL_ERROR;
1275         break;
1276       }
1277     }
1278   }
1279   else
1280   {
1281     /* Update error status */
1282     status = HAL_ERROR;
1283   }
1284 
1285   /* Release Lock */
1286   __HAL_UNLOCK(hdma);
1287 
1288   return status;
1289 }
1290 /**
1291   * @}
1292   */
1293 
1294 /** @addtogroup DMA_Exported_Functions_Group3
1295   *
1296 @verbatim
1297   ======================================================================================================================
1298                               ############### State and Errors functions ###############
1299   ======================================================================================================================
1300     [..]
1301       This section provides functions allowing to :
1302       (+) Check the DMA state
1303       (+) Get error code
1304 
1305     [..]
1306       (+) The HAL_DMA_GetState() function allows to get the DMA channel state.
1307       (+) The HAL_DMA_DeInit() function allows to get the DMA channel error code.
1308 
1309 @endverbatim
1310   * @{
1311   */
1312 
1313 /**
1314   * @brief  Returns the DMA channel state.
1315   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1316   *                specified DMA Channel.
1317   * @retval DMA state.
1318   */
HAL_DMA_GetState(DMA_HandleTypeDef const * const hdma)1319 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef const *const hdma)
1320 {
1321   /* Return the DMA channel state */
1322   return hdma->State;
1323 }
1324 
1325 /**
1326   * @brief  Return the DMA channel error code.
1327   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1328   *                specified DMA Channel.
1329   * @retval DMA Error Code.
1330   */
HAL_DMA_GetError(DMA_HandleTypeDef const * const hdma)1331 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef const *const hdma)
1332 {
1333   /* Return the DMA channel error code */
1334   return hdma->ErrorCode;
1335 }
1336 /**
1337   * @}
1338   */
1339 
1340 /** @addtogroup DMA_Exported_Functions_Group4
1341   *
1342 @verbatim
1343   ======================================================================================================================
1344                            ############### DMA Attributes functions ###############
1345   ======================================================================================================================
1346     [..]
1347       This section provides functions allowing to :
1348       (+) Configure DMA channel secure and privilege attributes.
1349       (+) Get DMA channel secure and privilege attributes.
1350       (+) Lock DMA channel secure and privilege attributes configuration.
1351       (+) Check whether DMA channel secure and privilege attributes configuration is locked or not.
1352 
1353     [..]
1354       (+) The HAL_DMA_ConfigChannelAttributes() function allows to configure DMA channel security and privilege
1355           attributes.
1356       (+) The HAL_DMA_GetConfigChannelAttributes() function allows to get DMA channel security and privilege attributes
1357           configuration.
1358       (+) The HAL_DMA_LockChannelAttributes() function allows to lock the DMA channel security and privilege attributes.
1359       (+) The HAL_DMA_GetLockChannelAttributes() function allows to get the DMA channel security and privilege
1360           attributes lock status.
1361 
1362 @endverbatim
1363   * @{
1364   */
1365 
1366 /**
1367   * @brief  Configure the DMA channel security and privilege attribute(s).
1368   * @note   These attributes cannot be modified when the corresponding lock state is enabled.
1369   * @param  hdma              : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for
1370   *                             the specified DMA Channel.
1371   * @param  ChannelAttributes : Specifies the DMA channel secure/privilege attributes.
1372   *                             This parameter can be a one or a combination of @ref DMA_Channel_Attributes.
1373   * @retval HAL Status.
1374   */
HAL_DMA_ConfigChannelAttributes(DMA_HandleTypeDef * const hdma,uint32_t ChannelAttributes)1375 HAL_StatusTypeDef HAL_DMA_ConfigChannelAttributes(DMA_HandleTypeDef *const hdma, uint32_t ChannelAttributes)
1376 {
1377   DMA_TypeDef *p_dma_instance;
1378   uint32_t channel_idx;
1379 
1380   /* Check the DMA peripheral handle parameter */
1381   if (hdma == NULL)
1382   {
1383     return HAL_ERROR;
1384   }
1385 
1386   /* Check the parameters */
1387   assert_param(IS_DMA_ATTRIBUTES(ChannelAttributes));
1388 
1389   /* Get DMA instance */
1390   p_dma_instance = GET_DMA_INSTANCE(hdma);
1391 
1392   /* Get channel index */
1393   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1394 
1395   /* Check DMA channel privilege attribute management */
1396   if ((ChannelAttributes & DMA_CHANNEL_ATTR_PRIV_MASK) == DMA_CHANNEL_ATTR_PRIV_MASK)
1397   {
1398     /* Configure DMA channel privilege attribute */
1399     if ((ChannelAttributes & DMA_CHANNEL_PRIV) == DMA_CHANNEL_PRIV)
1400     {
1401       p_dma_instance->PRIVCFGR |= channel_idx;
1402     }
1403     else
1404     {
1405       p_dma_instance->PRIVCFGR &= (~channel_idx);
1406     }
1407   }
1408 
1409 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1410   /* Check DMA channel security attribute management */
1411   if ((ChannelAttributes & DMA_CHANNEL_ATTR_SEC_MASK) == DMA_CHANNEL_ATTR_SEC_MASK)
1412   {
1413     /* Configure DMA channel security attribute */
1414     if ((ChannelAttributes & DMA_CHANNEL_SEC) == DMA_CHANNEL_SEC)
1415     {
1416       p_dma_instance->SECCFGR |= channel_idx;
1417     }
1418     else
1419     {
1420       p_dma_instance->SECCFGR &= (~channel_idx);
1421     }
1422   }
1423 
1424   /* Channel source security attribute management */
1425   if ((ChannelAttributes & DMA_CHANNEL_ATTR_SEC_SRC_MASK) == DMA_CHANNEL_ATTR_SEC_SRC_MASK)
1426   {
1427     /* Configure DMA channel source security attribute */
1428     if ((ChannelAttributes & DMA_CHANNEL_SRC_SEC) == DMA_CHANNEL_SRC_SEC)
1429     {
1430       hdma->Instance->CTR1 |= DMA_CTR1_SSEC;
1431     }
1432     else
1433     {
1434       hdma->Instance->CTR1 &= (~DMA_CTR1_SSEC);
1435     }
1436   }
1437 
1438   /* Channel destination security attribute management */
1439   if ((ChannelAttributes & DMA_CHANNEL_ATTR_SEC_DEST_MASK) == DMA_CHANNEL_ATTR_SEC_DEST_MASK)
1440   {
1441     /* Configure DMA channel destination security attribute */
1442     if ((ChannelAttributes & DMA_CHANNEL_DEST_SEC) == DMA_CHANNEL_DEST_SEC)
1443     {
1444       hdma->Instance->CTR1 |= DMA_CTR1_DSEC;
1445     }
1446     else
1447     {
1448       hdma->Instance->CTR1 &= (~DMA_CTR1_DSEC);
1449     }
1450   }
1451 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1452 
1453   return HAL_OK;
1454 }
1455 
1456 /**
1457   * @brief  Get the DMA channel security and privilege attributes.
1458   * @param  hdma               : Pointer to a DMA_HandleTypeDef structure that contains the configuration information
1459   *                              for the specified DMA Channel.
1460   * @param  pChannelAttributes : Pointer to the returned attributes.
1461   * @retval HAL Status.
1462   */
HAL_DMA_GetConfigChannelAttributes(DMA_HandleTypeDef const * const hdma,uint32_t * const pChannelAttributes)1463 HAL_StatusTypeDef HAL_DMA_GetConfigChannelAttributes(DMA_HandleTypeDef const *const hdma,
1464                                                      uint32_t *const pChannelAttributes)
1465 {
1466   DMA_TypeDef *p_dma_instance;
1467   uint32_t attributes;
1468   uint32_t channel_idx;
1469 
1470   /* Check the DMA peripheral handle and channel attributes parameters */
1471   if ((hdma == NULL) || (pChannelAttributes == NULL))
1472   {
1473     return HAL_ERROR;
1474   }
1475 
1476   /* Get DMA instance */
1477   p_dma_instance = GET_DMA_INSTANCE(hdma);
1478 
1479   /* Get channel index */
1480   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1481 
1482   /* Get DMA channel privilege attribute */
1483   attributes = ((p_dma_instance->PRIVCFGR & channel_idx) == 0U) ? DMA_CHANNEL_NPRIV : DMA_CHANNEL_PRIV;
1484 
1485 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1486   /* Get DMA channel security attribute */
1487   attributes |= ((p_dma_instance->SECCFGR & channel_idx) == 0U) ? DMA_CHANNEL_NSEC : DMA_CHANNEL_SEC;
1488 
1489   /* Get DMA channel source security attribute */
1490   attributes |= ((hdma->Instance->CTR1 & DMA_CTR1_SSEC) == 0U) ? DMA_CHANNEL_SRC_NSEC : DMA_CHANNEL_SRC_SEC;
1491 
1492   /* Get DMA channel destination security attribute */
1493   attributes |= ((hdma->Instance->CTR1 & DMA_CTR1_DSEC) == 0U) ? DMA_CHANNEL_DEST_NSEC : DMA_CHANNEL_DEST_SEC;
1494 
1495 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1496   /* return value */
1497   *pChannelAttributes = attributes;
1498 
1499   return HAL_OK;
1500 }
1501 
1502 #if defined (DMA_RCFGLOCKR_LOCK0)
1503 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1504 /**
1505   * @brief  Lock the DMA channel security and privilege attribute(s).
1506   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1507   *                specified DMA Channel.
1508   * @retval HAL Status.
1509   */
HAL_DMA_LockChannelAttributes(DMA_HandleTypeDef const * const hdma)1510 HAL_StatusTypeDef HAL_DMA_LockChannelAttributes(DMA_HandleTypeDef const *const hdma)
1511 {
1512   DMA_TypeDef *p_dma_instance;
1513   uint32_t channel_idx;
1514 
1515   /* Check the DMA peripheral handle parameter */
1516   if (hdma == NULL)
1517   {
1518     return HAL_ERROR;
1519   }
1520 
1521   /* Get DMA instance */
1522   p_dma_instance = GET_DMA_INSTANCE(hdma);
1523 
1524   /* Get channel index */
1525   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1526 
1527   /* Lock the DMA channel privilege and security attributes */
1528   p_dma_instance->RCFGLOCKR |= channel_idx;
1529 
1530   return HAL_OK;
1531 }
1532 #endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1533 
1534 /**
1535   * @brief  Get the security and privilege attribute lock state of a DMA channel.
1536   * @param  hdma       : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1537   *                      specified DMA Channel.
1538   * @param  pLockState : Pointer to lock state (returned value can be DMA_CHANNEL_ATTRIBUTE_UNLOCKED or
1539   *                      DMA_CHANNEL_ATTRIBUTE_LOCKED).
1540   * @retval HAL status.
1541   */
HAL_DMA_GetLockChannelAttributes(DMA_HandleTypeDef const * const hdma,uint32_t * const pLockState)1542 HAL_StatusTypeDef HAL_DMA_GetLockChannelAttributes(DMA_HandleTypeDef const *const hdma, uint32_t *const pLockState)
1543 {
1544   DMA_TypeDef *p_dma_instance;
1545   uint32_t channel_idx;
1546 
1547   /* Check the DMA peripheral handle and lock state parameters */
1548   if ((hdma == NULL) || (pLockState == NULL))
1549   {
1550     return HAL_ERROR;
1551   }
1552 
1553   /* Get DMA instance */
1554   p_dma_instance = GET_DMA_INSTANCE(hdma);
1555 
1556   /* Get channel index */
1557   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1558 
1559   /* Get channel lock attribute state */
1560   *pLockState = ((p_dma_instance->RCFGLOCKR & channel_idx) == 0U) ? DMA_CHANNEL_ATTRIBUTE_UNLOCKED : \
1561                 DMA_CHANNEL_ATTRIBUTE_LOCKED;
1562 
1563   return HAL_OK;
1564 }
1565 #endif /* defined (DMA_RCFGLOCKR_LOCK0) */
1566 /**
1567   * @}
1568   */
1569 
1570 /**
1571   * @}
1572   */
1573 
1574 
1575 /* Private functions -------------------------------------------------------------------------------------------------*/
1576 /** @defgroup DMA_Private_Functions DMA Private Functions
1577   * @brief    DMA Private Functions
1578   * @{
1579   */
1580 
1581 /**
1582   * @brief  Set the DMA channel normal transfer parameters.
1583   * @param  hdma        : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1584   *                       specified DMA Channel.
1585   * @param  SrcAddress  : The source data address.
1586   * @param  DstAddress  : The destination data address.
1587   * @param  SrcDataSize : The length of data to be transferred from source to destination in bytes.
1588   * @retval None.
1589   */
DMA_SetConfig(DMA_HandleTypeDef const * const hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SrcDataSize)1590 static void DMA_SetConfig(DMA_HandleTypeDef const *const hdma,
1591                           uint32_t SrcAddress,
1592                           uint32_t DstAddress,
1593                           uint32_t SrcDataSize)
1594 {
1595   /* Configure the DMA channel data size */
1596   MODIFY_REG(hdma->Instance->CBR1, DMA_CBR1_BNDT, (SrcDataSize & DMA_CBR1_BNDT));
1597 
1598   /* Clear all interrupt flags */
1599   __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
1600                        DMA_FLAG_TO);
1601 
1602   /* Configure DMA channel source address */
1603   hdma->Instance->CSAR = SrcAddress;
1604 
1605   /* Configure DMA channel destination address */
1606   hdma->Instance->CDAR = DstAddress;
1607 }
1608 
1609 /**
1610   * @brief  Initialize the DMA channel in normal mode according to the specified parameters in the DMA_InitTypeDef.
1611   * @param  hdma : pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1612   *                specified DMA Channel.
1613   * @retval None.
1614   */
DMA_Init(DMA_HandleTypeDef const * const hdma)1615 static void DMA_Init(DMA_HandleTypeDef const *const hdma)
1616 {
1617   uint32_t tmpreg;
1618 
1619   /* Prepare DMA Channel Control Register (CCR) value *****************************************************************/
1620   tmpreg = hdma->Init.Priority;
1621 
1622   /* Write DMA Channel Control Register (CCR) */
1623   MODIFY_REG(hdma->Instance->CCR, DMA_CCR_PRIO | DMA_CCR_LAP | DMA_CCR_LSM, tmpreg);
1624 
1625 
1626   /* Prepare DMA Channel Transfer Register (CTR1) value ***************************************************************/
1627   tmpreg = hdma->Init.DestInc | hdma->Init.DestDataWidth | hdma->Init.SrcInc | hdma->Init.SrcDataWidth;
1628 
1629   /* Add parameters specific to GPDMA */
1630   if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
1631   {
1632     tmpreg |= (hdma->Init.TransferAllocatedPort                                             |
1633                (((hdma->Init.DestBurstLength - 1U) << DMA_CTR1_DBL_1_Pos) & DMA_CTR1_DBL_1) |
1634                (((hdma->Init.SrcBurstLength - 1U) << DMA_CTR1_SBL_1_Pos) & DMA_CTR1_SBL_1));
1635   }
1636 
1637   /* Write DMA Channel Transfer Register 1 (CTR1) */
1638 #if defined (DMA_CTR1_SSEC)
1639   MODIFY_REG(hdma->Instance->CTR1, ~(DMA_CTR1_SSEC | DMA_CTR1_DSEC), tmpreg);
1640 #else
1641   WRITE_REG(hdma->Instance->CTR1, tmpreg);
1642 #endif /* defined (DMA_CTR1_SSEC) */
1643   /* Prepare DMA Channel Transfer Register 2 (CTR2) value *************************************************************/
1644   tmpreg = hdma->Init.BlkHWRequest | (hdma->Init.Request & DMA_CTR2_REQSEL) | hdma->Init.TransferEventMode;
1645 
1646   /* Memory to Peripheral Transfer */
1647   if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1648   {
1649     if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
1650     {
1651       tmpreg |= DMA_CTR2_DREQ;
1652     }
1653   }
1654   /* Memory to Memory Transfer */
1655   else if ((hdma->Init.Direction) == DMA_MEMORY_TO_MEMORY)
1656   {
1657     tmpreg |= DMA_CTR2_SWREQ;
1658   }
1659   else
1660   {
1661     /* Nothing to do */
1662   }
1663 
1664   /* Write DMA Channel Transfer Register 2 (CTR2) */
1665   MODIFY_REG(hdma->Instance->CTR2, (DMA_CTR2_TCEM  | DMA_CTR2_TRIGPOL | DMA_CTR2_TRIGSEL | DMA_CTR2_TRIGM |
1666                                     DMA_CTR2_BREQ  | DMA_CTR2_DREQ    | DMA_CTR2_SWREQ   | DMA_CTR2_REQSEL), tmpreg);
1667 
1668 
1669   /* Write DMA Channel Block Register 1 (CBR1) ************************************************************************/
1670   WRITE_REG(hdma->Instance->CBR1, 0U);
1671 
1672 
1673   /* If 2D Addressing is supported by current channel */
1674   if (IS_DMA_2D_ADDRESSING_INSTANCE(hdma->Instance) != 0U)
1675   {
1676     /* Write DMA Channel Transfer Register 3 (CTR3) *******************************************************************/
1677     WRITE_REG(hdma->Instance->CTR3, 0U);
1678 
1679 
1680     /* Write DMA Channel Block Register 2 (CBR2) **********************************************************************/
1681     WRITE_REG(hdma->Instance->CBR2, 0U);
1682   }
1683 
1684 
1685   /* Write DMA Channel linked-list address register (CLLR) ************************************************************/
1686   WRITE_REG(hdma->Instance->CLLR, 0U);
1687 }
1688 /**
1689   * @}
1690   */
1691 
1692 #endif /* HAL_DMA_MODULE_ENABLED */
1693 
1694 /**
1695   * @}
1696   */
1697 
1698 /**
1699   * @}
1700   */
1701