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