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