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