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