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 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     [..]
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 DMA_Request_Selection
63 
64           (+) BlkHWRequest          : Specifies the Block hardware request mode for DMA channel
65               (++) can be a value of DMA_Block_Request
66 
67           (+) Direction             : Specifies the transfer direction for DMA channel
68               (++) can be a value of DMA_Transfer_Direction
69 
70           (+) SrcInc                : Specifies the source increment mode for the DMA channel
71               (++) can be a value of DMA_Source_Increment_Mode
72 
73           (+) DestInc               : Specifies the destination increment mode for the DMA channel
74               (++) can be a value of DMA_Destination_Increment_Mode
75 
76           (+) SrcDataWidth          : Specifies the source data width for the DMA channel
77               (++) can be a value of DMA_Source_Data_Width
78 
79           (+) DestDataWidth         : Specifies the destination data width for the DMA channel
80               (++) can be a value of DMA_Destination_Data_Width
81 
82           (+) Priority              : Specifies the priority for the DMA channel
83               (++) can be a value of 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 DMA_Transfer_Allocated_Port
93 
94           (+) TransferEventMode     : Specifies the transfer event mode for the DMA channel
95               (++) can be a value of DMA_Transfer_Event_Mode
96 
97           (+) Mode                  : Specifies the transfer mode for the DMA channel
98               (++) can be DMA_NORMAL
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 can be called once after each system boot.
159               If called again, HAL_DMA_ConfigChannelAttributes() API has no effect.
160               Unlock is done either by a system boot or a by an RCC reset.
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_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 
322   DMA_TypeDef *p_dma_instance;
323 
324   uint32_t tickstart = HAL_GetTick();
325 
326   /* Check the DMA peripheral handle parameter */
327   if (hdma == NULL)
328   {
329     return HAL_ERROR;
330   }
331 
332   /* Check the parameters */
333   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
334 
335   /* Get DMA instance */
336   p_dma_instance = GET_DMA_INSTANCE(hdma);
337 
338   /* Disable the selected DMA Channel */
339   __HAL_DMA_DISABLE(hdma);
340 
341   /* Check if the DMA channel is effectively disabled */
342   while ((hdma->Instance->CCR & DMA_CCR_EN) != 0U)
343   {
344     /* Check for the Timeout */
345     if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
346     {
347       /* Update the DMA channel error code */
348       hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
349 
350       /* Update the DMA channel state */
351       hdma->State = HAL_DMA_STATE_ERROR;
352 
353       return HAL_ERROR;
354     }
355   }
356 
357   /* Reset DMA Channel registers */
358   hdma->Instance->CLBAR = 0U;
359   hdma->Instance->CCR   = 0U;
360   hdma->Instance->CTR1  = 0U;
361   hdma->Instance->CTR2  = 0U;
362   hdma->Instance->CBR1  = 0U;
363   hdma->Instance->CSAR  = 0U;
364   hdma->Instance->CDAR  = 0U;
365   hdma->Instance->CLLR  = 0U;
366 
367   /* Reset 2D Addressing registers */
368   if (IS_DMA_2D_ADDRESSING_INSTANCE(hdma->Instance) != 0U)
369   {
370     hdma->Instance->CTR3 = 0U;
371     hdma->Instance->CBR2 = 0U;
372   }
373 
374   /* Clear privilege attribute */
375   CLEAR_BIT(p_dma_instance->PRIVCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
376 
377 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
378   /* Clear secure attribute */
379   CLEAR_BIT(p_dma_instance->SECCFGR, (1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU)));
380 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
381 
382   /* Clear all flags */
383   __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
384                               DMA_FLAG_TO));
385 
386   /* Clean all callbacks */
387   hdma->XferCpltCallback     = NULL;
388   hdma->XferHalfCpltCallback = NULL;
389   hdma->XferErrorCallback    = NULL;
390   hdma->XferAbortCallback    = NULL;
391   hdma->XferSuspendCallback  = NULL;
392 
393   /* Clean DMA queue */
394   hdma->LinkedListQueue = NULL;
395 
396   /* Clean DMA parent */
397   if (hdma->Parent != NULL)
398   {
399     hdma->Parent = NULL;
400   }
401 
402   /* Update DMA channel operation mode */
403   hdma->Mode = DMA_NORMAL;
404 
405   /* Update the DMA channel error code */
406   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
407 
408   /* Update the DMA channel state */
409   hdma->State = HAL_DMA_STATE_RESET;
410 
411   /* Release Lock */
412   __HAL_UNLOCK(hdma);
413 
414   return HAL_OK;
415 }
416 /**
417   * @}
418   */
419 
420 /** @addtogroup DMA_Exported_Functions_Group2
421   *
422 @verbatim
423   ======================================================================================================================
424                                 ##### IO operation functions #####
425   ======================================================================================================================
426     [..]
427       This section provides functions allowing to :
428       (+) Configure the source, destination address and data size and Start DMA transfer in normal mode
429       (+) Abort DMA transfer
430       (+) Poll for transfer complete
431       (+) Handle DMA interrupt request
432       (+) Register and Unregister DMA callbacks
433 
434     [..]
435       (+) The HAL_DMA_Start() function allows to start the DMA channel transfer in normal mode (Blocking mode).
436       (+) The HAL_DMA_Start_IT() function allows to start the DMA channel transfer in normal mode (Non-blocking mode).
437       (+) The HAL_DMA_Abort() function allows to abort any on-going transfer (Blocking mode).
438       (+) The HAL_DMA_Abort_IT() function allows to abort any on-going transfer (Non-blocking mode).
439       (+) The HAL_DMA_PollForTransfer() function allows to poll on half transfer and transfer complete (Blocking mode).
440           This API cannot be used for circular transfers.
441       (+) The HAL_DMA_IRQHandler() function allows to handle any DMA channel interrupt (Non-blocking mode).
442       (+) The HAL_DMA_RegisterCallback() and HAL_DMA_UnRegisterCallback() functions allow respectively to register and
443           unregister user customized callbacks.
444           User callbacks are called under HAL_DMA_IRQHandler().
445 
446 @endverbatim
447   * @{
448   */
449 
450 /**
451   * @brief  Start the DMA channel transfer in normal mode (Blocking mode).
452   * @param  hdma        : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for
453   *                       the specified DMA Channel.
454   * @param  SrcAddress  : The source data address.
455   * @param  DstAddress  : The destination data address.
456   * @param  SrcDataSize : The length of data to be transferred from source to destination in bytes.
457   * @retval HAL status.
458   */
HAL_DMA_Start(DMA_HandleTypeDef * const hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SrcDataSize)459 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *const hdma,
460                                 uint32_t SrcAddress,
461                                 uint32_t DstAddress,
462                                 uint32_t SrcDataSize)
463 {
464   /* Check the DMA peripheral handle parameter */
465   if (hdma == NULL)
466   {
467     return HAL_ERROR;
468   }
469 
470   /* Check the parameters */
471   assert_param(IS_DMA_BLOCK_SIZE(SrcDataSize));
472 
473   /* Process locked */
474   __HAL_LOCK(hdma);
475 
476   /* Check DMA channel state */
477   if (hdma->State == HAL_DMA_STATE_READY)
478   {
479     /* Update the DMA channel state */
480     hdma->State = HAL_DMA_STATE_BUSY;
481 
482     /* Update the DMA channel error code */
483     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
484 
485     /* Configure the source address, destination address, the data size and clear flags */
486     DMA_SetConfig(hdma, SrcAddress, DstAddress, SrcDataSize);
487 
488     /* Enable DMA channel */
489     __HAL_DMA_ENABLE(hdma);
490   }
491   else
492   {
493     /* Update the DMA channel error code */
494     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
495 
496     /* Process unlocked */
497     __HAL_UNLOCK(hdma);
498 
499     return HAL_ERROR;
500   }
501 
502   return HAL_OK;
503 }
504 
505 /**
506   * @brief  Starts the DMA channel transfer in normal mode with interrupts enabled (Non-blocking mode).
507   * @param  hdma         : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
508   *                        specified DMA Channel.
509   * @param  SrcAddress   : The source data address.
510   * @param  DstAddress   : The destination data address.
511   * @param  SrcDataSize  : The length of data to be transferred from source to destination in bytes.
512   * @retval HAL status.
513   */
HAL_DMA_Start_IT(DMA_HandleTypeDef * const hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SrcDataSize)514 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *const hdma,
515                                    uint32_t SrcAddress,
516                                    uint32_t DstAddress,
517                                    uint32_t SrcDataSize)
518 {
519   /* Check the DMA peripheral handle parameter */
520   if (hdma == NULL)
521   {
522     return HAL_ERROR;
523   }
524 
525   /* Check the parameters */
526   assert_param(IS_DMA_BLOCK_SIZE(SrcDataSize));
527 
528   /* Process locked */
529   __HAL_LOCK(hdma);
530 
531   /* Check DMA channel state */
532   if (hdma->State == HAL_DMA_STATE_READY)
533   {
534     /* Update the DMA channel state */
535     hdma->State = HAL_DMA_STATE_BUSY;
536 
537     /* Update the DMA channel error code */
538     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
539 
540     /* Configure the source address, destination address, the data size and clear flags */
541     DMA_SetConfig(hdma, SrcAddress, DstAddress, SrcDataSize);
542 
543     /* Enable common interrupts: Transfer Complete and Transfer Errors ITs */
544     __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_DTE | DMA_IT_ULE | DMA_IT_USE | DMA_IT_TO));
545 
546     /* Check half transfer complete callback */
547     if (hdma->XferHalfCpltCallback != NULL)
548     {
549       /* If Half Transfer complete callback is set, enable the corresponding IT */
550       __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
551     }
552 
553     /* Check Half suspend callback */
554     if (hdma->XferSuspendCallback != NULL)
555     {
556       /* If Transfer suspend callback is set, enable the corresponding IT */
557       __HAL_DMA_ENABLE_IT(hdma, DMA_IT_SUSP);
558     }
559 
560     /* Enable DMA channel */
561     __HAL_DMA_ENABLE(hdma);
562   }
563   else
564   {
565     /* Update the DMA channel error code */
566     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
567 
568     /* Process unlocked */
569     __HAL_UNLOCK(hdma);
570 
571     return HAL_ERROR;
572   }
573 
574   return HAL_OK;
575 }
576 
577 /**
578   * @brief  Abort any on-going DMA channel transfer (Blocking mode).
579   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
580   *                specified DMA Channel.
581   * @note   After suspending a DMA channel, a wait until the DMA channel is effectively stopped is added. If a channel
582   *         is suspended while a data transfer is on-going, the current data will be transferred and the channel will be
583   *         effectively suspended only after the transfer of any on-going data is finished.
584   * @retval HAL status.
585   */
HAL_DMA_Abort(DMA_HandleTypeDef * const hdma)586 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *const hdma)
587 {
588   /* Get tick number */
589   uint32_t tickstart =  HAL_GetTick();
590 
591   /* Check the DMA peripheral handle parameter */
592   if (hdma == NULL)
593   {
594     return HAL_ERROR;
595   }
596 
597   /* Check DMA channel state */
598   if (hdma->State != HAL_DMA_STATE_BUSY)
599   {
600     /* Update the DMA channel error code */
601     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
602 
603     /* Process Unlocked */
604     __HAL_UNLOCK(hdma);
605 
606     return HAL_ERROR;
607   }
608   else
609   {
610     /* Suspend the channel */
611     hdma->Instance->CCR |= DMA_CCR_SUSP;
612 
613     /* Update the DMA channel state */
614     hdma->State = HAL_DMA_STATE_SUSPEND;
615 
616     /* Check if the DMA Channel is suspended */
617     while ((hdma->Instance->CSR & DMA_CSR_SUSPF) == 0U)
618     {
619       /* Check for the Timeout */
620       if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
621       {
622         /* Update the DMA channel error code */
623         hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
624 
625         /* Update the DMA channel state */
626         hdma->State = HAL_DMA_STATE_ERROR;
627 
628         /* Check DMA channel transfer mode */
629         if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
630         {
631           /* Update the linked-list queue state */
632           hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
633         }
634 
635         /* Process Unlocked */
636         __HAL_UNLOCK(hdma);
637 
638         return HAL_ERROR;
639       }
640     }
641 
642     /* Reset the channel */
643     hdma->Instance->CCR |= DMA_CCR_RESET;
644 
645     /* Update the DMA channel state */
646     hdma->State = HAL_DMA_STATE_ABORT;
647 
648     /* Clear all status flags */
649     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
650                                 DMA_FLAG_TO));
651 
652     /* Update the DMA channel state */
653     hdma->State = HAL_DMA_STATE_READY;
654 
655     /* Check DMA channel transfer mode */
656     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
657     {
658       /* Update the linked-list queue state */
659       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
660 
661       /* Clear remaining data size to ensure loading linked-list from memory next start */
662       hdma->Instance->CBR1 = 0U;
663     }
664 
665     /* Process Unlocked */
666     __HAL_UNLOCK(hdma);
667   }
668 
669   return HAL_OK;
670 }
671 
672 /**
673   * @brief  Abort any on-going DMA channel transfer in interrupt mode (Non-blocking mode).
674   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
675   *                specified DMA Channel.
676   * @retval HAL status.
677   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * const hdma)678 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *const hdma)
679 {
680   /* Check the DMA peripheral handle parameter */
681   if (hdma == NULL)
682   {
683     return HAL_ERROR;
684   }
685 
686   /* Check DMA channel state */
687   if (hdma->State != HAL_DMA_STATE_BUSY)
688   {
689     /* Update the DMA channel error code */
690     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
691 
692     return HAL_ERROR;
693   }
694   else
695   {
696     /* Update the DMA channel state */
697     hdma->State = HAL_DMA_STATE_ABORT;
698 
699     /* Suspend the channel and activate suspend interrupt */
700     hdma->Instance->CCR |= (DMA_CCR_SUSP | DMA_CCR_SUSPIE);
701   }
702 
703   return HAL_OK;
704 }
705 
706 /**
707   * @brief  Polling for transfer status (Blocking mode).
708   * @param  hdma          : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
709   *                         specified DMA Channel.
710   * @param  CompleteLevel : Specifies the DMA level complete.
711   * @param  Timeout       : Timeout duration.
712   * @retval HAL status
713   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * const hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)714 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *const hdma,
715                                           HAL_DMA_LevelCompleteTypeDef CompleteLevel,
716                                           uint32_t Timeout)
717 {
718   /* Get tick number */
719   uint32_t tickstart = HAL_GetTick();
720   uint32_t level_flag;
721   uint32_t tmp_csr;
722 
723   /* Check the DMA peripheral handle parameter */
724   if (hdma == NULL)
725   {
726     return HAL_ERROR;
727   }
728 
729   /* Check the parameters */
730   assert_param(IS_DMA_LEVEL_COMPLETE(CompleteLevel));
731 
732   /* Check DMA channel state */
733   if (hdma->State != HAL_DMA_STATE_BUSY)
734   {
735     /* Update the DMA channel error code */
736     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
737 
738     /* Process Unlocked */
739     __HAL_UNLOCK(hdma);
740 
741     return HAL_ERROR;
742   }
743 
744   /* Polling mode is not supported in circular mode */
745   if ((hdma->Mode & DMA_LINKEDLIST_CIRCULAR) == DMA_LINKEDLIST_CIRCULAR)
746   {
747     /* Update the DMA channel error code */
748     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
749 
750     return HAL_ERROR;
751   }
752 
753   /* Get the level transfer complete flag */
754   level_flag = ((CompleteLevel == HAL_DMA_FULL_TRANSFER) ? DMA_FLAG_IDLE : DMA_FLAG_HT);
755 
756   /* Get DMA channel status */
757   tmp_csr = hdma->Instance->CSR;
758 
759   while ((tmp_csr & level_flag) == 0U)
760   {
761     /* Check for the timeout */
762     if (Timeout != HAL_MAX_DELAY)
763     {
764       if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
765       {
766         /* Update the DMA channel error code */
767         hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
768 
769         /*
770           If timeout, abort the current transfer.
771           Note that the Abort function will
772           - Clear all transfer flags.
773           - Unlock.
774           - Set the State.
775         */
776         (void)HAL_DMA_Abort(hdma);
777 
778         return HAL_ERROR;
779       }
780     }
781 
782     /* Get a newer CSR register value */
783     tmp_csr = hdma->Instance->CSR;
784   }
785 
786   /* Check trigger overrun flag */
787   if ((tmp_csr & DMA_FLAG_TO) != 0U)
788   {
789     /* Update the DMA channel error code */
790     hdma->ErrorCode |= HAL_DMA_ERROR_TO;
791 
792     /* Clear the error flag */
793     __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_TO);
794   }
795 
796   /* Check error flags */
797   if ((tmp_csr & (DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE)) != 0U)
798   {
799     /* Check the data transfer error flag */
800     if ((tmp_csr & DMA_FLAG_DTE) != 0U)
801     {
802       /* Update the DMA channel error code */
803       hdma->ErrorCode |= HAL_DMA_ERROR_DTE;
804 
805       /* Clear the error flag */
806       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_DTE);
807     }
808 
809     /* Check the update link error flag */
810     if ((tmp_csr & DMA_FLAG_ULE) != 0U)
811     {
812       /* Update the DMA channel error code */
813       hdma->ErrorCode |= HAL_DMA_ERROR_ULE;
814 
815       /* Clear the error flag */
816       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_ULE);
817     }
818 
819     /* Check the user setting error flag */
820     if ((tmp_csr & DMA_FLAG_USE) != 0U)
821     {
822       /* Update the DMA channel error code */
823       hdma->ErrorCode |= HAL_DMA_ERROR_USE;
824 
825       /* Clear the error flag */
826       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_USE);
827     }
828 
829     /* Reset the channel */
830     hdma->Instance->CCR |= DMA_CCR_RESET;
831 
832     /* Update the DMA channel state */
833     hdma->State = HAL_DMA_STATE_READY;
834 
835     /* Check DMA channel transfer mode */
836     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
837     {
838       /* Update the linked-list queue state */
839       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
840     }
841 
842     /* Process Unlocked */
843     __HAL_UNLOCK(hdma);
844 
845     return HAL_ERROR;
846   }
847 
848   /* Clear the transfer level flag */
849   if (CompleteLevel == HAL_DMA_HALF_TRANSFER)
850   {
851     /* Clear the Half Transfer flag */
852     __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_HT);
853   }
854   else if (CompleteLevel == HAL_DMA_FULL_TRANSFER)
855   {
856     /* Clear the transfer flags */
857     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT));
858 
859     /* Update the DMA channel state */
860     hdma->State = HAL_DMA_STATE_READY;
861 
862     /* Check DMA channel transfer mode */
863     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
864     {
865       /* Update the linked-list queue state */
866       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
867     }
868 
869     /* Process unlocked */
870     __HAL_UNLOCK(hdma);
871   }
872   else
873   {
874     return HAL_ERROR;
875   }
876 
877   return HAL_OK;
878 }
879 
880 /**
881   * @brief  Handle DMA interrupt request (Non-blocking mode).
882   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
883   *                specified DMA Channel.
884   * @retval None.
885   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * const hdma)886 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *const hdma)
887 {
888   const DMA_TypeDef *p_dma_instance = GET_DMA_INSTANCE(hdma);
889   uint32_t global_it_flag =  1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
890   uint32_t global_active_flag_ns = IS_DMA_GLOBAL_ACTIVE_FLAG_NS(p_dma_instance, global_it_flag);
891 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
892   uint32_t global_active_flag_s = IS_DMA_GLOBAL_ACTIVE_FLAG_S(p_dma_instance, global_it_flag);
893 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
894 
895   /* Global Interrupt Flag management *********************************************************************************/
896 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
897   if ((global_active_flag_s == 0U) && (global_active_flag_ns == 0U))
898 #else
899   if (global_active_flag_ns == 0U)
900 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
901   {
902     return; /* the global interrupt flag for the current channel is down , nothing to do */
903   }
904 
905   /* Data Transfer Error Interrupt management *************************************************************************/
906   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_DTE) != 0U))
907   {
908     /* Check if interrupt source is enabled */
909     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DTE) != 0U)
910     {
911       /* Clear the transfer error flag */
912       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_DTE);
913 
914       /* Update the DMA channel error code */
915       hdma->ErrorCode |= HAL_DMA_ERROR_DTE;
916     }
917   }
918 
919   /* Update Linked-list Error Interrupt management ********************************************************************/
920   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_ULE) != 0U))
921   {
922     /* Check if interrupt source is enabled */
923     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_ULE) != 0U)
924     {
925       /* Clear the update linked-list error flag */
926       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_ULE);
927 
928       /* Update the DMA channel error code */
929       hdma->ErrorCode |= HAL_DMA_ERROR_ULE;
930     }
931   }
932 
933   /* User Setting Error Interrupt management **************************************************************************/
934   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_USE) != 0U))
935   {
936     /* Check if interrupt source is enabled */
937     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_USE) != 0U)
938     {
939       /* Clear the user setting error flag */
940       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_USE);
941 
942       /* Update the DMA channel error code */
943       hdma->ErrorCode |= HAL_DMA_ERROR_USE;
944     }
945   }
946 
947   /* Trigger Overrun Interrupt management *****************************************************************************/
948   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_TO) != 0U))
949   {
950     /* Check if interrupt source is enabled */
951     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TO) != 0U)
952     {
953       /* Clear the trigger overrun flag */
954       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_TO);
955 
956       /* Update the DMA channel error code */
957       hdma->ErrorCode |= HAL_DMA_ERROR_TO;
958     }
959   }
960 
961   /* Half Transfer Complete Interrupt management **********************************************************************/
962   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_HT) != 0U))
963   {
964     /* Check if interrupt source is enabled */
965     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U)
966     {
967       /* Clear the half transfer flag */
968       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_HT);
969 
970       /* Check half transfer complete callback */
971       if (hdma->XferHalfCpltCallback != NULL)
972       {
973         /* Half transfer callback */
974         hdma->XferHalfCpltCallback(hdma);
975       }
976     }
977   }
978 
979   /* Suspend Transfer Interrupt management ****************************************************************************/
980   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_SUSP) != 0U))
981   {
982     /* Check if interrupt source is enabled */
983     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_SUSP) != 0U)
984     {
985       /* Clear the block transfer complete flag */
986       __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_SUSP);
987 
988       /* Check DMA channel state */
989       if (hdma->State == HAL_DMA_STATE_ABORT)
990       {
991         /* Disable the suspend transfer interrupt */
992         __HAL_DMA_DISABLE_IT(hdma, DMA_IT_SUSP);
993 
994         /* Reset the channel internal state and reset the FIFO */
995         hdma->Instance->CCR |= DMA_CCR_RESET;
996 
997         /* Update the DMA channel state */
998         hdma->State = HAL_DMA_STATE_READY;
999 
1000         /* Check DMA channel transfer mode */
1001         if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1002         {
1003           /* Update the linked-list queue state */
1004           hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
1005 
1006           /* Clear remaining data size to ensure loading linked-list from memory next start */
1007           hdma->Instance->CBR1 = 0U;
1008         }
1009 
1010         /* Process Unlocked */
1011         __HAL_UNLOCK(hdma);
1012 
1013         /* Check transfer abort callback */
1014         if (hdma->XferAbortCallback != NULL)
1015         {
1016           /* Transfer abort callback */
1017           hdma->XferAbortCallback(hdma);
1018         }
1019 
1020         return;
1021       }
1022       else
1023       {
1024         /* Update the DMA channel state */
1025         hdma->State = HAL_DMA_STATE_SUSPEND;
1026 
1027         /* Check transfer suspend callback */
1028         if (hdma->XferSuspendCallback != NULL)
1029         {
1030           /* Transfer suspend callback */
1031           hdma->XferSuspendCallback(hdma);
1032         }
1033       }
1034     }
1035   }
1036 
1037   /* Transfer Complete Interrupt management ***************************************************************************/
1038   if ((__HAL_DMA_GET_FLAG(hdma, DMA_FLAG_TC) != 0U))
1039   {
1040     /* Check if interrupt source is enabled */
1041     if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U)
1042     {
1043       /* Check DMA channel transfer mode */
1044       if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1045       {
1046         /* If linked-list transfer */
1047         if (hdma->Instance->CLLR == 0U)
1048         {
1049           if (hdma->Instance->CBR1 == 0U)
1050           {
1051             /* Update the DMA channel state */
1052             hdma->State = HAL_DMA_STATE_READY;
1053 
1054             /* Update the linked-list queue state */
1055             hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
1056           }
1057         }
1058       }
1059       else
1060       {
1061         /* If normal transfer */
1062         if (hdma->Instance->CBR1 == 0U)
1063         {
1064           /* Update the DMA channel state */
1065           hdma->State = HAL_DMA_STATE_READY;
1066         }
1067       }
1068 
1069       /* Clear TC and HT transfer flags */
1070       __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC | DMA_FLAG_HT));
1071 
1072       /* Process Unlocked */
1073       __HAL_UNLOCK(hdma);
1074 
1075       /* Check transfer complete callback */
1076       if (hdma->XferCpltCallback != NULL)
1077       {
1078         /* Channel Transfer Complete callback */
1079         hdma->XferCpltCallback(hdma);
1080       }
1081     }
1082   }
1083 
1084   /* Manage error case ************************************************************************************************/
1085   if (hdma->ErrorCode != HAL_DMA_ERROR_NONE)
1086   {
1087     /* Reset the channel internal state and reset the FIFO */
1088     hdma->Instance->CCR |= DMA_CCR_RESET;
1089 
1090     /* Update the DMA channel state */
1091     hdma->State = HAL_DMA_STATE_READY;
1092 
1093     /* Check DMA channel transfer mode */
1094     if ((hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1095     {
1096       /* Update the linked-list queue state */
1097       hdma->LinkedListQueue->State = HAL_DMA_QUEUE_STATE_READY;
1098     }
1099 
1100     /* Process Unlocked */
1101     __HAL_UNLOCK(hdma);
1102 
1103     /* Check transfer error callback */
1104     if (hdma->XferErrorCallback != NULL)
1105     {
1106       /* Transfer error callback */
1107       hdma->XferErrorCallback(hdma);
1108     }
1109   }
1110 }
1111 
1112 /**
1113   * @brief  Register callback according to specified ID.
1114   * @note   The HAL_DMA_RegisterCallback() may be called before HAL_DMA_Init() in HAL_DMA_STATE_RESET
1115   *         to register callbacks for HAL_DMA_MSPINIT_CB_ID and HAL_DMA_MSPDEINIT_CB_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   /* Check DMA channel state */
1135   if (hdma->State == HAL_DMA_STATE_READY)
1136   {
1137     /* Check callback ID */
1138     switch (CallbackID)
1139     {
1140       case HAL_DMA_XFER_CPLT_CB_ID:
1141       {
1142         /* Register transfer complete callback */
1143         hdma->XferCpltCallback = pCallback;
1144         break;
1145       }
1146 
1147       case HAL_DMA_XFER_HALFCPLT_CB_ID:
1148       {
1149         /* Register half transfer callback */
1150         hdma->XferHalfCpltCallback = pCallback;
1151         break;
1152       }
1153 
1154       case HAL_DMA_XFER_ERROR_CB_ID:
1155       {
1156         /* Register transfer error callback */
1157         hdma->XferErrorCallback = pCallback;
1158         break;
1159       }
1160 
1161       case HAL_DMA_XFER_ABORT_CB_ID:
1162       {
1163         /* Register abort callback */
1164         hdma->XferAbortCallback = pCallback;
1165         break;
1166       }
1167 
1168       case HAL_DMA_XFER_SUSPEND_CB_ID:
1169       {
1170         /* Register suspend callback */
1171         hdma->XferSuspendCallback = pCallback;
1172         break;
1173       }
1174 
1175       default:
1176       {
1177         /* Update error status */
1178         status = HAL_ERROR;
1179         break;
1180       }
1181     }
1182   }
1183   else
1184   {
1185     /* Update error status */
1186     status =  HAL_ERROR;
1187   }
1188 
1189   return status;
1190 }
1191 
1192 /**
1193   * @brief  Unregister callback according to specified ID.
1194   * @note   The HAL_DMA_UnRegisterCallback() may be called before HAL_DMA_Init() in HAL_DMA_STATE_RESET
1195   *         to un-register callbacks for HAL_DMA_MSPINIT_CB_ID and HAL_DMA_MSPDEINIT_CB_ID.
1196   * @param  hdma       : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1197   *                      specified DMA Channel.
1198   * @param  CallbackID : User Callback identifier which could be a value of HAL_DMA_CallbackIDTypeDef enum.
1199   * @retval HAL status.
1200   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * const hdma,HAL_DMA_CallbackIDTypeDef CallbackID)1201 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *const hdma,
1202                                              HAL_DMA_CallbackIDTypeDef CallbackID)
1203 {
1204   HAL_StatusTypeDef status = HAL_OK;
1205 
1206   /* Check the DMA peripheral handle parameter */
1207   if (hdma == NULL)
1208   {
1209     return HAL_ERROR;
1210   }
1211 
1212   /* Check DMA channel state */
1213   if (hdma->State == HAL_DMA_STATE_READY)
1214   {
1215     /* Check callback ID */
1216     switch (CallbackID)
1217     {
1218       case HAL_DMA_XFER_CPLT_CB_ID:
1219       {
1220         /* UnRegister transfer complete callback */
1221         hdma->XferCpltCallback = NULL;
1222         break;
1223       }
1224 
1225       case HAL_DMA_XFER_HALFCPLT_CB_ID:
1226       {
1227         /* UnRegister half transfer callback */
1228         hdma->XferHalfCpltCallback = NULL;
1229         break;
1230       }
1231 
1232       case HAL_DMA_XFER_ERROR_CB_ID:
1233       {
1234         /* UnRegister transfer error callback */
1235         hdma->XferErrorCallback = NULL;
1236         break;
1237       }
1238 
1239       case HAL_DMA_XFER_ABORT_CB_ID:
1240       {
1241         /* UnRegister abort callback */
1242         hdma->XferAbortCallback = NULL;
1243         break;
1244       }
1245 
1246       case HAL_DMA_XFER_SUSPEND_CB_ID:
1247       {
1248         /* UnRegister suspend callback */
1249         hdma->XferSuspendCallback = NULL;
1250         break;
1251       }
1252 
1253       case HAL_DMA_XFER_ALL_CB_ID:
1254       {
1255         /* UnRegister all available callbacks */
1256         hdma->XferCpltCallback     = NULL;
1257         hdma->XferHalfCpltCallback = NULL;
1258         hdma->XferErrorCallback    = NULL;
1259         hdma->XferAbortCallback    = NULL;
1260         hdma->XferSuspendCallback  = NULL;
1261         break;
1262       }
1263 
1264       default:
1265       {
1266         /* Update error status */
1267         status = HAL_ERROR;
1268         break;
1269       }
1270     }
1271   }
1272   else
1273   {
1274     /* Update error status */
1275     status = HAL_ERROR;
1276   }
1277 
1278   return status;
1279 }
1280 /**
1281   * @}
1282   */
1283 
1284 /** @addtogroup DMA_Exported_Functions_Group3
1285   *
1286 @verbatim
1287   ======================================================================================================================
1288                               ##### State and Errors functions #####
1289   ======================================================================================================================
1290     [..]
1291       This section provides functions allowing to :
1292       (+) Check the DMA state
1293       (+) Get error code
1294 
1295     [..]
1296       (+) The HAL_DMA_GetState() function allows to get the DMA channel state.
1297       (+) The HAL_DMA_DeInit() function allows to get the DMA channel error code.
1298 
1299 @endverbatim
1300   * @{
1301   */
1302 
1303 /**
1304   * @brief  Returns the DMA channel state.
1305   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1306   *                specified DMA Channel.
1307   * @retval DMA state.
1308   */
HAL_DMA_GetState(DMA_HandleTypeDef const * const hdma)1309 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef const *const hdma)
1310 {
1311   /* Return the DMA channel state */
1312   return hdma->State;
1313 }
1314 
1315 /**
1316   * @brief  Return the DMA channel error code.
1317   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1318   *                specified DMA Channel.
1319   * @retval DMA Error Code.
1320   */
HAL_DMA_GetError(DMA_HandleTypeDef const * const hdma)1321 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef const *const hdma)
1322 {
1323   /* Return the DMA channel error code */
1324   return hdma->ErrorCode;
1325 }
1326 /**
1327   * @}
1328   */
1329 
1330 /** @addtogroup DMA_Exported_Functions_Group4
1331   *
1332 @verbatim
1333   ======================================================================================================================
1334                            ##### DMA Attributes functions #####
1335   ======================================================================================================================
1336     [..]
1337       This section provides functions allowing to :
1338       (+) Configure DMA channel secure and privilege attributes.
1339       (+) Get DMA channel secure and privilege attributes.
1340       (+) Lock DMA channel secure and privilege attributes configuration.
1341       (+) Check whether DMA channel secure and privilege attributes configuration is locked or not.
1342 
1343     [..]
1344       (+) The HAL_DMA_ConfigChannelAttributes() function allows to configure DMA channel security and privilege
1345           attributes.
1346       (+) The HAL_DMA_GetConfigChannelAttributes() function allows to get DMA channel security and privilege attributes
1347           configuration.
1348       (+) The HAL_DMA_LockChannelAttributes() function allows to lock the DMA channel security and privilege attributes.
1349       (+) The HAL_DMA_GetLockChannelAttributes() function allows to get the DMA channel security and privilege
1350           attributes lock status.
1351 
1352 @endverbatim
1353   * @{
1354   */
1355 
1356 /**
1357   * @brief  Configure the DMA channel security and privilege attribute(s).
1358   * @note   These attributes cannot be modified when the corresponding lock state is enabled.
1359   * @param  hdma              : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for
1360   *                             the specified DMA Channel.
1361   * @param  ChannelAttributes : Specifies the DMA channel secure/privilege attributes.
1362   *                             This parameter can be a one or a combination of @ref DMA_Channel_Attributes.
1363   * @retval HAL Status.
1364   */
HAL_DMA_ConfigChannelAttributes(DMA_HandleTypeDef * const hdma,uint32_t ChannelAttributes)1365 HAL_StatusTypeDef HAL_DMA_ConfigChannelAttributes(DMA_HandleTypeDef *const hdma, uint32_t ChannelAttributes)
1366 {
1367   DMA_TypeDef *p_dma_instance;
1368   uint32_t channel_idx;
1369 
1370   /* Check the DMA peripheral handle parameter */
1371   if (hdma == NULL)
1372   {
1373     return HAL_ERROR;
1374   }
1375 
1376   /* Check the parameters */
1377   assert_param(IS_DMA_ATTRIBUTES(ChannelAttributes));
1378 
1379   /* Get DMA instance */
1380   p_dma_instance = GET_DMA_INSTANCE(hdma);
1381 
1382   /* Get channel index */
1383   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1384 
1385   /* Check DMA channel privilege attribute management */
1386   if ((ChannelAttributes & DMA_CHANNEL_ATTR_PRIV_MASK) == DMA_CHANNEL_ATTR_PRIV_MASK)
1387   {
1388     /* Configure DMA channel privilege attribute */
1389     if ((ChannelAttributes & DMA_CHANNEL_PRIV) == DMA_CHANNEL_PRIV)
1390     {
1391       p_dma_instance->PRIVCFGR |= channel_idx;
1392     }
1393     else
1394     {
1395       p_dma_instance->PRIVCFGR &= (~channel_idx);
1396     }
1397   }
1398 
1399 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1400   /* Check DMA channel security attribute management */
1401   if ((ChannelAttributes & DMA_CHANNEL_ATTR_SEC_MASK) == DMA_CHANNEL_ATTR_SEC_MASK)
1402   {
1403     /* Configure DMA channel security attribute */
1404     if ((ChannelAttributes & DMA_CHANNEL_SEC) == DMA_CHANNEL_SEC)
1405     {
1406       p_dma_instance->SECCFGR |= channel_idx;
1407     }
1408     else
1409     {
1410       p_dma_instance->SECCFGR &= (~channel_idx);
1411     }
1412   }
1413 
1414   /* Channel source security attribute management */
1415   if ((ChannelAttributes & DMA_CHANNEL_ATTR_SEC_SRC_MASK) == DMA_CHANNEL_ATTR_SEC_SRC_MASK)
1416   {
1417     /* Configure DMA channel source security attribute */
1418     if ((ChannelAttributes & DMA_CHANNEL_SRC_SEC) == DMA_CHANNEL_SRC_SEC)
1419     {
1420       hdma->Instance->CTR1 |= DMA_CTR1_SSEC;
1421     }
1422     else
1423     {
1424       hdma->Instance->CTR1 &= (~DMA_CTR1_SSEC);
1425     }
1426   }
1427 
1428   /* Channel destination security attribute management */
1429   if ((ChannelAttributes & DMA_CHANNEL_ATTR_SEC_DEST_MASK) == DMA_CHANNEL_ATTR_SEC_DEST_MASK)
1430   {
1431     /* Configure DMA channel destination security attribute */
1432     if ((ChannelAttributes & DMA_CHANNEL_DEST_SEC) == DMA_CHANNEL_DEST_SEC)
1433     {
1434       hdma->Instance->CTR1 |= DMA_CTR1_DSEC;
1435     }
1436     else
1437     {
1438       hdma->Instance->CTR1 &= (~DMA_CTR1_DSEC);
1439     }
1440   }
1441 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1442 
1443   return HAL_OK;
1444 }
1445 
1446 /**
1447   * @brief  Get the DMA channel security and privilege attributes.
1448   * @param  hdma               : Pointer to a DMA_HandleTypeDef structure that contains the configuration information
1449   *                              for the specified DMA Channel.
1450   * @param  pChannelAttributes : Pointer to the returned attributes.
1451   * @retval HAL Status.
1452   */
HAL_DMA_GetConfigChannelAttributes(DMA_HandleTypeDef const * const hdma,uint32_t * const pChannelAttributes)1453 HAL_StatusTypeDef HAL_DMA_GetConfigChannelAttributes(DMA_HandleTypeDef const *const hdma,
1454                                                      uint32_t *const pChannelAttributes)
1455 {
1456   const DMA_TypeDef *p_dma_instance;
1457   uint32_t attributes;
1458   uint32_t channel_idx;
1459 
1460   /* Check the DMA peripheral handle and channel attributes parameters */
1461   if ((hdma == NULL) || (pChannelAttributes == NULL))
1462   {
1463     return HAL_ERROR;
1464   }
1465 
1466   /* Get DMA instance */
1467   p_dma_instance = GET_DMA_INSTANCE(hdma);
1468 
1469   /* Get channel index */
1470   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1471 
1472   /* Get DMA channel privilege attribute */
1473   attributes = ((p_dma_instance->PRIVCFGR & channel_idx) == 0U) ? DMA_CHANNEL_NPRIV : DMA_CHANNEL_PRIV;
1474 
1475   /* Get DMA channel security attribute */
1476   attributes |= ((p_dma_instance->SECCFGR & channel_idx) == 0U) ? DMA_CHANNEL_NSEC : DMA_CHANNEL_SEC;
1477 
1478   /* Get DMA channel source security attribute */
1479   attributes |= ((hdma->Instance->CTR1 & DMA_CTR1_SSEC) == 0U) ? DMA_CHANNEL_SRC_NSEC : DMA_CHANNEL_SRC_SEC;
1480 
1481   /* Get DMA channel destination security attribute */
1482   attributes |= ((hdma->Instance->CTR1 & DMA_CTR1_DSEC) == 0U) ? DMA_CHANNEL_DEST_NSEC : DMA_CHANNEL_DEST_SEC;
1483 
1484   /* return value */
1485   *pChannelAttributes = attributes;
1486 
1487   return HAL_OK;
1488 }
1489 
1490 
1491 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
1492 /**
1493   * @brief  Lock the DMA channel security and privilege attribute(s).
1494   * @param  hdma : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1495   *                specified DMA Channel.
1496   * @retval HAL Status.
1497   */
HAL_DMA_LockChannelAttributes(DMA_HandleTypeDef const * const hdma)1498 HAL_StatusTypeDef HAL_DMA_LockChannelAttributes(DMA_HandleTypeDef const *const hdma)
1499 {
1500   DMA_TypeDef *p_dma_instance;
1501   uint32_t channel_idx;
1502 
1503   /* Check the DMA peripheral handle parameter */
1504   if (hdma == NULL)
1505   {
1506     return HAL_ERROR;
1507   }
1508 
1509   /* Get DMA instance */
1510   p_dma_instance = GET_DMA_INSTANCE(hdma);
1511 
1512   /* Get channel index */
1513   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1514 
1515   /* Lock the DMA channel privilege and security attributes */
1516   p_dma_instance->RCFGLOCKR |= channel_idx;
1517 
1518   return HAL_OK;
1519 }
1520 #endif /* (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
1521 
1522 /**
1523   * @brief  Get the security and privilege attribute lock state of a DMA channel.
1524   * @param  hdma       : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1525   *                      specified DMA Channel.
1526   * @param  pLockState : Pointer to lock state (returned value can be DMA_CHANNEL_ATTRIBUTE_UNLOCKED or
1527   *                      DMA_CHANNEL_ATTRIBUTE_LOCKED).
1528   * @retval HAL status.
1529   */
HAL_DMA_GetLockChannelAttributes(DMA_HandleTypeDef const * const hdma,uint32_t * const pLockState)1530 HAL_StatusTypeDef HAL_DMA_GetLockChannelAttributes(DMA_HandleTypeDef const *const hdma, uint32_t *const pLockState)
1531 {
1532   DMA_TypeDef *p_dma_instance;
1533   uint32_t channel_idx;
1534 
1535   /* Check the DMA peripheral handle and lock state parameters */
1536   if ((hdma == NULL) || (pLockState == NULL))
1537   {
1538     return HAL_ERROR;
1539   }
1540 
1541   /* Get DMA instance */
1542   p_dma_instance = GET_DMA_INSTANCE(hdma);
1543 
1544   /* Get channel index */
1545   channel_idx = 1UL << (GET_DMA_CHANNEL(hdma) & 0x1FU);
1546 
1547   /* Get channel lock attribute state */
1548   *pLockState = ((p_dma_instance->RCFGLOCKR & channel_idx) == 0U) ? DMA_CHANNEL_ATTRIBUTE_UNLOCKED : \
1549                 DMA_CHANNEL_ATTRIBUTE_LOCKED;
1550 
1551   return HAL_OK;
1552 }
1553 /**
1554   * @}
1555   */
1556 
1557 /**
1558   * @}
1559   */
1560 
1561 
1562 /* Private functions -------------------------------------------------------------------------------------------------*/
1563 /** @defgroup DMA_Private_Functions DMA Private Functions
1564   * @brief    DMA Private Functions
1565   * @{
1566   */
1567 
1568 /**
1569   * @brief  Set the DMA channel normal transfer parameters.
1570   * @param  hdma        : Pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1571   *                       specified DMA Channel.
1572   * @param  SrcAddress  : The source data address.
1573   * @param  DstAddress  : The destination data address.
1574   * @param  SrcDataSize : The length of data to be transferred from source to destination in bytes.
1575   * @retval None.
1576   */
DMA_SetConfig(DMA_HandleTypeDef const * const hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SrcDataSize)1577 static void DMA_SetConfig(DMA_HandleTypeDef const *const hdma,
1578                           uint32_t SrcAddress,
1579                           uint32_t DstAddress,
1580                           uint32_t SrcDataSize)
1581 {
1582   /* Configure the DMA channel data size */
1583   MODIFY_REG(hdma->Instance->CBR1, DMA_CBR1_BNDT, (SrcDataSize & DMA_CBR1_BNDT));
1584 
1585   /* Clear all interrupt flags */
1586   __HAL_DMA_CLEAR_FLAG(hdma, DMA_FLAG_TC | DMA_FLAG_HT | DMA_FLAG_DTE | DMA_FLAG_ULE | DMA_FLAG_USE | DMA_FLAG_SUSP |
1587                        DMA_FLAG_TO);
1588 
1589   /* Configure DMA channel source address */
1590   hdma->Instance->CSAR = SrcAddress;
1591 
1592   /* Configure DMA channel destination address */
1593   hdma->Instance->CDAR = DstAddress;
1594 }
1595 
1596 /**
1597   * @brief  Initialize the DMA channel in normal mode according to the specified parameters in the DMA_InitTypeDef.
1598   * @param  hdma : pointer to a DMA_HandleTypeDef structure that contains the configuration information for the
1599   *                specified DMA Channel.
1600   * @retval None.
1601   */
DMA_Init(DMA_HandleTypeDef const * const hdma)1602 static void DMA_Init(DMA_HandleTypeDef const *const hdma)
1603 {
1604   uint32_t tmpreg;
1605 
1606   /* Prepare DMA Channel Control Register (CCR) value *****************************************************************/
1607   tmpreg = hdma->Init.Priority;
1608 
1609   /* Write DMA Channel Control Register (CCR) */
1610   MODIFY_REG(hdma->Instance->CCR, DMA_CCR_PRIO | DMA_CCR_LAP | DMA_CCR_LSM, tmpreg);
1611 
1612   /* Prepare DMA Channel Transfer Register (CTR1) value ***************************************************************/
1613   tmpreg = hdma->Init.DestInc | hdma->Init.DestDataWidth | hdma->Init.SrcInc | hdma->Init.SrcDataWidth;
1614 
1615   /* Add parameters specific to GPDMA */
1616   if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
1617   {
1618     tmpreg |= (hdma->Init.TransferAllocatedPort                                             |
1619                (((hdma->Init.DestBurstLength - 1U) << DMA_CTR1_DBL_1_Pos) & DMA_CTR1_DBL_1) |
1620                (((hdma->Init.SrcBurstLength - 1U) << DMA_CTR1_SBL_1_Pos) & DMA_CTR1_SBL_1));
1621   }
1622 
1623   /* Write DMA Channel Transfer Register 1 (CTR1) */
1624   MODIFY_REG(hdma->Instance->CTR1, ~(DMA_CTR1_SSEC | DMA_CTR1_DSEC), tmpreg);
1625 
1626   /* Prepare DMA Channel Transfer Register 2 (CTR2) value *************************************************************/
1627   tmpreg = hdma->Init.BlkHWRequest | (hdma->Init.Request & DMA_CTR2_REQSEL) | hdma->Init.TransferEventMode;
1628 
1629   /* Memory to Peripheral Transfer */
1630   if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1631   {
1632     if (IS_GPDMA_INSTANCE(hdma->Instance) != 0U)
1633     {
1634       tmpreg |= DMA_CTR2_DREQ;
1635     }
1636   }
1637   /* Memory to Memory Transfer */
1638   else if ((hdma->Init.Direction) == DMA_MEMORY_TO_MEMORY)
1639   {
1640     tmpreg |= DMA_CTR2_SWREQ;
1641   }
1642   else
1643   {
1644     /* Nothing to do */
1645   }
1646 
1647   /* Write DMA Channel Transfer Register 2 (CTR2) */
1648   MODIFY_REG(hdma->Instance->CTR2, (DMA_CTR2_TCEM  | DMA_CTR2_TRIGPOL | DMA_CTR2_TRIGSEL | DMA_CTR2_TRIGM |
1649                                     DMA_CTR2_BREQ  | DMA_CTR2_DREQ    | DMA_CTR2_SWREQ   | DMA_CTR2_REQSEL), tmpreg);
1650 
1651 
1652   /* Write DMA Channel Block Register 1 (CBR1) ************************************************************************/
1653   WRITE_REG(hdma->Instance->CBR1, 0U);
1654 
1655   /* If 2D Addressing is supported by current channel */
1656   if (IS_DMA_2D_ADDRESSING_INSTANCE(hdma->Instance) != 0U)
1657   {
1658     /* Write DMA Channel Transfer Register 3 (CTR3) *******************************************************************/
1659     WRITE_REG(hdma->Instance->CTR3, 0U);
1660 
1661     /* Write DMA Channel Block Register 2 (CBR2) **********************************************************************/
1662     WRITE_REG(hdma->Instance->CBR2, 0U);
1663   }
1664 
1665   /* Write DMA Channel linked-list address register (CLLR) ************************************************************/
1666   WRITE_REG(hdma->Instance->CLLR, 0U);
1667 }
1668 /**
1669   * @}
1670   */
1671 
1672 #endif /* HAL_DMA_MODULE_ENABLED */
1673 
1674 /**
1675   * @}
1676   */
1677 
1678 /**
1679   * @}
1680   */
1681