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