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