1 /**
2   ******************************************************************************
3   * @file    stm32mp1xx_hal_dma.c
4   * @author  MCD Application Team
5   * @brief   DMA HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Direct Memory Access (DMA) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral State and errors functions
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2019 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   @verbatim
23   ==============================================================================
24                         ##### How to use this driver #####
25   ==============================================================================
26   [..]
27    (#) Enable and configure the peripheral to be connected to the DMA Stream
28        (except for internal SRAM/FLASH memories: no initialization is
29        necessary) please refer to Reference manual for connection between peripherals
30        and DMA requests .
31 
32    (#) For a given Stream, program the required configuration through the following parameters:
33        Transfer Direction, Source and Destination data formats,
34        Circular, Normal or peripheral flow control mode, Stream Priority level,
35        Source and Destination Increment mode, FIFO mode and its Threshold (if needed),
36        Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function.
37 
38      *** Polling mode IO operation ***
39      =================================
40     [..]
41           (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
42               address and destination address and the Length of data to be transferred
43           (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
44               case a fixed Timeout can be configured by User depending from his application.
45 
46      *** Interrupt mode IO operation ***
47      ===================================
48     [..]
49           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
50           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
51           (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
52               Source address and destination address and the Length of data to be transferred. In this
53               case the DMA interrupt is configured
54           (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
55           (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
56               add his own function by customization of function pointer XferCpltCallback and
57               XferErrorCallback (i.e a member of DMA handle structure).
58     [..]
59      (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
60          detection.
61 
62      (#) Use HAL_DMA_Abort() function to abort the current transfer
63 
64      -@-   In Memory-to-Memory transfer mode, Circular mode is not allowed.
65 
66      -@-   The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
67            possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
68            Half-Word data size for the peripheral to access its data register and set Word data size
69            for the Memory to gain in access time. Each two half words will be packed and written in
70            a single access to a Word in the Memory).
71 
72      -@-   When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
73            and Destination. In this case the Peripheral Data Size will be applied to both Source
74            and Destination.
75 
76      *** DMA HAL driver macros list ***
77      =============================================
78      [..]
79        Below the list of most used macros in DMA HAL driver.
80 
81       (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream.
82       (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream.
83       (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level.
84       (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts.
85       (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts.
86       (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream interrupt has occurred or not.
87 
88      [..]
89       (@) You can refer to the DMA HAL driver header file for more useful macros.
90 
91   @endverbatim
92   ******************************************************************************
93   */
94 
95 /* Includes ------------------------------------------------------------------*/
96 #include "stm32mp1xx_hal.h"
97 
98 /** @addtogroup STM32MP1xx_HAL_Driver
99   * @{
100   */
101 
102 /** @defgroup DMA DMA
103   * @brief DMA HAL module driver
104   * @{
105   */
106 
107 #ifdef HAL_DMA_MODULE_ENABLED
108 
109 /* Private types -------------------------------------------------------------*/
110 typedef struct
111 {
112   __IO uint32_t ISR;   /*!< DMA interrupt status register */
113   __IO uint32_t Reserved0;
114   __IO uint32_t IFCR;  /*!< DMA interrupt flag clear register */
115 } DMA_Base_Registers;
116 
117 /* Private variables ---------------------------------------------------------*/
118 /* Private constants ---------------------------------------------------------*/
119 /** @addtogroup DMA_Private_Constants
120  * @{
121  */
122 #define HAL_TIMEOUT_DMA_ABORT    (5U)  /* 5 ms */
123 
124 
125 /**
126   * @}
127   */
128 /* Private macros ------------------------------------------------------------*/
129 /* Private functions ---------------------------------------------------------*/
130 /** @addtogroup DMA_Private_Functions
131   * @{
132   */
133 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
134 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
135 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma);
136 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
137 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
138 
139 /**
140   * @}
141   */
142 
143 /* Exported functions ---------------------------------------------------------*/
144 /** @addtogroup DMA_Exported_Functions
145   * @{
146   */
147 
148 /** @addtogroup DMA_Exported_Functions_Group1
149   *
150 @verbatim
151  ===============================================================================
152              ##### Initialization and de-initialization functions  #####
153  ===============================================================================
154     [..]
155     This section provides functions allowing to initialize the DMA Stream source
156     and destination incrementation and data sizes, transfer direction,
157     circular/normal mode selection, memory-to-memory mode selection and Stream priority value.
158     [..]
159     The HAL_DMA_Init() function follows the DMA configuration procedures as described in
160     reference manual.
161     The HAL_DMA_DeInit function allows to deinitialize the DMA stream.
162 
163 @endverbatim
164   * @{
165   */
166 
167 /**
168   * @brief  Initialize the DMA according to the specified
169   *         parameters in the DMA_InitTypeDef and create the associated handle.
170   * @param  hdma: Pointer to a DMA_HandleTypeDef structure that contains
171   *               the configuration information for the specified DMA Stream.
172   * @retval HAL status
173   */
HAL_DMA_Init(DMA_HandleTypeDef * hdma)174 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
175 {
176   uint32_t registerValue;
177   uint32_t tickstart = HAL_GetTick();
178   DMA_Base_Registers *regs_dma;
179 
180   /* Check the DMA peripheral handle */
181   if (hdma == NULL)
182   {
183     return HAL_ERROR;
184   }
185 
186   /* Check the parameters */
187   assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));
188   assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
189   assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
190   assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
191   assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
192   assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
193   assert_param(IS_DMA_MODE(hdma->Init.Mode));
194   assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
195 
196   if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
197   {
198 
199     assert_param(IS_DMA_REQUEST(hdma->Init.Request));
200     assert_param(IS_DMA_FIFO_MODE_STATE(hdma->Init.FIFOMode));
201     /* Check the memory burst, peripheral burst and FIFO threshold parameters only
202        when FIFO mode is enabled */
203     if (hdma->Init.FIFOMode != DMA_FIFOMODE_DISABLE)
204     {
205       assert_param(IS_DMA_FIFO_THRESHOLD(hdma->Init.FIFOThreshold));
206       assert_param(IS_DMA_MEMORY_BURST(hdma->Init.MemBurst));
207       assert_param(IS_DMA_PERIPHERAL_BURST(hdma->Init.PeriphBurst));
208     }
209 
210 
211 
212     /* Change DMA peripheral state */
213     hdma->State = HAL_DMA_STATE_BUSY;
214 
215     /* Allocate lock resource */
216     __HAL_UNLOCK(hdma);
217 
218     /* Disable the peripheral */
219     __HAL_DMA_DISABLE(hdma);
220 
221     /* Check if the DMA Stream is effectively disabled */
222     while ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
223     {
224       /* Check for the Timeout */
225       if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
226       {
227         /* Update error code */
228         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
229 
230         /* Change the DMA state */
231         hdma->State = HAL_DMA_STATE_ERROR;
232 
233         return HAL_ERROR;
234       }
235     }
236 
237     /* Get the CR register value */
238     registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->CR;
239 
240     /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
241     registerValue &= ((uint32_t)~(DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
242                                   DMA_SxCR_PL    | DMA_SxCR_MSIZE  | DMA_SxCR_PSIZE  | \
243                                   DMA_SxCR_MINC  | DMA_SxCR_PINC   | DMA_SxCR_CIRC   | \
244                                   DMA_SxCR_DIR   | DMA_SxCR_CT     | DMA_SxCR_DBM));
245 
246     /* Prepare the DMA Stream configuration */
247     registerValue |=  hdma->Init.Direction           |
248                       hdma->Init.PeriphInc           | hdma->Init.MemInc           |
249                       hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
250                       hdma->Init.Mode                | hdma->Init.Priority;
251 
252     /* the Memory burst and peripheral burst are not used when the FIFO is disabled */
253     if (hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
254     {
255       /* Get memory burst and peripheral burst */
256       registerValue |=  hdma->Init.MemBurst | hdma->Init.PeriphBurst;
257     }
258 
259     /* Write to DMA Stream CR register */
260     ((DMA_Stream_TypeDef *)hdma->Instance)->CR = registerValue;
261 
262     /* Get the FCR register value */
263     registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->FCR;
264 
265     /* Clear Direct mode and FIFO threshold bits */
266     registerValue &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
267 
268     /* Prepare the DMA Stream FIFO configuration */
269     registerValue |= hdma->Init.FIFOMode;
270 
271     /* the FIFO threshold is not used when the FIFO mode is disabled */
272     if (hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
273     {
274       /* Get the FIFO threshold */
275       registerValue |= hdma->Init.FIFOThreshold;
276 
277       /* Check compatibility between FIFO threshold level and size of the memory burst */
278       /* for INCR4, INCR8, INCR16 */
279       if (hdma->Init.MemBurst != DMA_MBURST_SINGLE)
280       {
281         if (DMA_CheckFifoParam(hdma) != HAL_OK)
282         {
283           /* Update error code */
284           hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
285 
286           /* Change the DMA state */
287           hdma->State = HAL_DMA_STATE_READY;
288 
289           return HAL_ERROR;
290         }
291       }
292     }
293 
294     /* Write to DMA Stream FCR */
295     ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = registerValue;
296 
297     /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
298        DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
299     regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
300 
301     /* Clear all interrupt flags */
302      regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
303   }
304   else
305   {
306     hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
307     hdma->State     = HAL_DMA_STATE_ERROR;
308 
309     return HAL_ERROR;
310   }
311 
312   /* Initialize parameters for DMAMUX channel :
313      DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
314   */
315   DMA_CalcDMAMUXChannelBaseAndMask(hdma);
316 
317   if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
318   {
319     /* if memory to memory force the request to 0*/
320     hdma->Init.Request = DMA_REQUEST_MEM2MEM;
321   }
322 
323 
324   /* Set peripheral request  to DMAMUX channel */
325   hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
326 
327   /* Clear the DMAMUX synchro overrun flag */
328   hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
329 
330   /* Initialize parameters for DMAMUX request generator :
331      if the DMA request is DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR7
332   */
333 
334   if ((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
335   {
336     /* Initialize parameters for DMAMUX request generator :
337     DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
338     DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
339 
340     /* Reset the DMAMUX request generator register*/
341     hdma->DMAmuxRequestGen->RGCR = 0U;
342 
343     /* Clear the DMAMUX request generator overrun flag */
344     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
345   }
346   else
347   {
348     hdma->DMAmuxRequestGen = 0U;
349     hdma->DMAmuxRequestGenStatus = 0U;
350     hdma->DMAmuxRequestGenStatusMask = 0U;
351   }
352 
353   /* Initialize the error code */
354   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
355 
356   /* Initialize the DMA state */
357   hdma->State = HAL_DMA_STATE_READY;
358 
359   return HAL_OK;
360 }
361 
362 /**
363   * @brief  DeInitializes the DMA peripheral
364   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
365   *               the configuration information for the specified DMA Stream.
366   * @retval HAL status
367   */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)368 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
369 {
370   DMA_Base_Registers *regs_dma;
371 
372   /* Check the DMA peripheral handle */
373   if (hdma == NULL)
374   {
375     return HAL_ERROR;
376   }
377 
378   /* Disable the selected DMA Streamx */
379   __HAL_DMA_DISABLE(hdma);
380 
381 
382   /* Reset DMA Streamx control register */
383   ((DMA_Stream_TypeDef *)hdma->Instance)->CR   = 0U;
384 
385   /* Reset DMA Streamx number of data to transfer register */
386   ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = 0U;
387 
388   /* Reset DMA Streamx peripheral address register */
389   ((DMA_Stream_TypeDef *)hdma->Instance)->PAR  = 0U;
390 
391   /* Reset DMA Streamx memory 0 address register */
392   ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = 0U;
393 
394   /* Reset DMA Streamx memory 1 address register */
395   ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = 0U;
396 
397   /* Reset DMA Streamx FIFO control register */
398   ((DMA_Stream_TypeDef *)hdma->Instance)->FCR  = (uint32_t)0x00000021U;
399 
400   /* Get DMA steam Base Address */
401     regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
402 
403   /* Clear all interrupt flags at correct offset within the register */
404   regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
405   /* Initialize parameters for DMAMUX channel :
406      DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
407   DMA_CalcDMAMUXChannelBaseAndMask(hdma);
408 
409   if(hdma->DMAmuxChannel != 0U)
410   {
411     /* Resett he DMAMUX channel that corresponds to the DMA stream */
412     hdma->DMAmuxChannel->CCR = 0U;
413 
414     /* Clear the DMAMUX synchro overrun flag */
415     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
416   }
417 
418   if ((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
419   {
420     /* Initialize parameters for DMAMUX request generator :
421     DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
422     DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
423 
424     /* Reset the DMAMUX request generator register*/
425     hdma->DMAmuxRequestGen->RGCR = 0U;
426 
427     /* Clear the DMAMUX request generator overrun flag */
428     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
429   }
430 
431   hdma->DMAmuxRequestGen = 0U;
432   hdma->DMAmuxRequestGenStatus = 0U;
433   hdma->DMAmuxRequestGenStatusMask = 0U;
434 
435   /* Clean callbacks */
436   hdma->XferCpltCallback = NULL;
437   hdma->XferHalfCpltCallback = NULL;
438   hdma->XferM1CpltCallback = NULL;
439   hdma->XferM1HalfCpltCallback = NULL;
440   hdma->XferErrorCallback = NULL;
441   hdma->XferAbortCallback = NULL;
442 
443   /* Initialize the error code */
444   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
445 
446   /* Initialize the DMA state */
447   hdma->State = HAL_DMA_STATE_RESET;
448 
449   /* Release Lock */
450   __HAL_UNLOCK(hdma);
451 
452   return HAL_OK;
453 }
454 
455 /**
456   * @}
457   */
458 
459 /** @addtogroup DMA_Exported_Functions_Group2
460   *
461 @verbatim
462  ===============================================================================
463                       #####  IO operation functions  #####
464  ===============================================================================
465     [..]  This section provides functions allowing to:
466       (+) Configure the source, destination address and data length and Start DMA transfer
467       (+) Configure the source, destination address and data length and
468           Start DMA transfer with interrupt
469       (+) Register and Unregister DMA callbacks
470       (+) Abort DMA transfer
471       (+) Poll for transfer complete
472       (+) Handle DMA interrupt request
473 
474 @endverbatim
475   * @{
476   */
477 
478 /**
479   * @brief  Starts the DMA Transfer.
480   * @param  hdma      : pointer to a DMA_HandleTypeDef structure that contains
481   *                     the configuration information for the specified DMA Stream.
482   * @param  SrcAddress: The source memory Buffer address
483   * @param  DstAddress: The destination memory Buffer address
484   * @param  DataLength: The length of data to be transferred from source to destination
485   * @retval HAL status
486   */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)487 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
488 {
489   HAL_StatusTypeDef status = HAL_OK;
490 
491   /* Check the parameters */
492   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
493 
494   /* Check the DMA peripheral handle */
495   if (hdma == NULL)
496   {
497     return HAL_ERROR;
498   }
499 
500   /* Process locked */
501   __HAL_LOCK(hdma);
502 
503   if (HAL_DMA_STATE_READY == hdma->State)
504   {
505     /* Change DMA peripheral state */
506     hdma->State = HAL_DMA_STATE_BUSY;
507 
508     /* Initialize the error code */
509     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
510 
511     /* Disable the peripheral */
512     __HAL_DMA_DISABLE(hdma);
513 
514     /* Configure the source, destination address and the data length */
515     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
516 
517     /* Enable the Peripheral */
518     __HAL_DMA_ENABLE(hdma);
519   }
520   else
521   {
522     /* Set the error code to busy */
523     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
524 
525     /* Process unlocked */
526     __HAL_UNLOCK(hdma);
527 
528     /* Return error status */
529     status = HAL_ERROR;
530   }
531   return status;
532 }
533 
534 /**
535   * @brief  Start the DMA Transfer with interrupt enabled.
536   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
537   *                     the configuration information for the specified DMA Stream.
538   * @param  SrcAddress: The source memory Buffer address
539   * @param  DstAddress: The destination memory Buffer address
540   * @param  DataLength: The length of data to be transferred from source to destination
541   * @retval HAL status
542   */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)543 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
544 {
545   HAL_StatusTypeDef status = HAL_OK;
546 
547   /* Check the parameters */
548   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
549 
550   /* Check the DMA peripheral handle */
551   if (hdma == NULL)
552   {
553     return HAL_ERROR;
554   }
555 
556   /* Process locked */
557   __HAL_LOCK(hdma);
558 
559   if (HAL_DMA_STATE_READY == hdma->State)
560   {
561     /* Change DMA peripheral state */
562     hdma->State = HAL_DMA_STATE_BUSY;
563 
564     /* Initialize the error code */
565     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
566 
567     /* Disable the peripheral */
568     __HAL_DMA_DISABLE(hdma);
569 
570     /* Configure the source, destination address and the data length */
571     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
572 
573     /* Enable Common interrupts*/
574     MODIFY_REG(((DMA_Stream_TypeDef *)hdma->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
575     if (hdma->XferHalfCpltCallback != NULL)
576     {
577       /*Enable Half Transfer IT if corresponding Callback is set*/
578       ((DMA_Stream_TypeDef *)hdma->Instance)->CR  |= DMA_IT_HT;
579     }
580 
581     /* Check if DMAMUX Synchronization is enabled*/
582     if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
583     {
584       /* Enable DMAMUX sync overrun IT*/
585       hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
586     }
587 
588     if(hdma->DMAmuxRequestGen != 0U)
589     {
590       /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
591       /* enable the request gen overrun IT*/
592       hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
593 
594     }
595 
596     /* Enable the Peripheral */
597     __HAL_DMA_ENABLE(hdma);
598   }
599   else
600   {
601     /* Set the error code to busy */
602     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
603 
604     /* Process unlocked */
605     __HAL_UNLOCK(hdma);
606 
607     /* Return error status */
608     status = HAL_ERROR;
609   }
610 
611   return status;
612 }
613 
614 /**
615   * @brief  Aborts the DMA Transfer.
616   * @param  hdma  : pointer to a DMA_HandleTypeDef structure that contains
617   *                 the configuration information for the specified DMA Stream.
618   *
619   * @note  After disabling a DMA Stream, a check for wait until the DMA Stream is
620   *        effectively disabled is added. If a Stream is disabled
621   *        while a data transfer is ongoing, the current data will be transferred
622   *        and the Stream will be effectively disabled only after the transfer of
623   *        this single data is finished.
624   * @retval HAL status
625   */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)626 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
627 {
628   /* calculate DMA base and stream number */
629   DMA_Base_Registers *regs_dma;
630   const __IO uint32_t *enableRegister;
631 
632   uint32_t tickstart = HAL_GetTick();
633 
634   /* Check the DMA peripheral handle */
635   if (hdma == NULL)
636   {
637     return HAL_ERROR;
638   }
639 
640   /* Check the DMA peripheral state */
641   if (hdma->State != HAL_DMA_STATE_BUSY)
642   {
643     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
644 
645     /* Process Unlocked */
646     __HAL_UNLOCK(hdma);
647 
648     return HAL_ERROR;
649   }
650   else
651   {
652     /* Disable DMA All Interrupts  */
653     ((DMA_Stream_TypeDef *)hdma->Instance)->CR  &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT);
654     ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
655 
656     enableRegister = (__IO uint32_t *)(&(((DMA_Stream_TypeDef *)hdma->Instance)->CR));
657 
658     /* disable the DMAMUX sync overrun IT*/
659     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
660 
661     /* Disable the stream */
662     __HAL_DMA_DISABLE(hdma);
663 
664     /* Check if the DMA Stream is effectively disabled */
665     while (((*enableRegister) & DMA_SxCR_EN) != 0U)
666     {
667       /* Check for the Timeout */
668       if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
669       {
670         /* Update error code */
671         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
672 
673         /* Change the DMA state */
674         hdma->State = HAL_DMA_STATE_ERROR;
675 
676         /* Process Unlocked */
677         __HAL_UNLOCK(hdma);
678 
679         return HAL_ERROR;
680       }
681     }
682     regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
683     regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
684 
685     /* Clear the DMAMUX synchro overrun flag */
686     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
687 
688     if(hdma->DMAmuxRequestGen != 0U)
689     {
690       /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
691       /* disable the request gen overrun IT*/
692       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
693 
694       /* Clear the DMAMUX request generator overrun flag */
695       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
696     }
697 
698     /* Change the DMA state*/
699     hdma->State = HAL_DMA_STATE_READY;
700     /* Process Unlocked */
701     __HAL_UNLOCK(hdma);
702   }
703   return HAL_OK;
704 }
705 
706 /**
707   * @brief  Aborts the DMA Transfer in Interrupt mode.
708   * @param  hdma  : pointer to a DMA_HandleTypeDef structure that contains
709   *                 the configuration information for the specified DMA Stream.
710   * @retval HAL status
711   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)712 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
713 {
714   /* Check the DMA peripheral handle */
715   if (hdma == NULL)
716   {
717     return HAL_ERROR;
718   }
719 
720   if (hdma->State != HAL_DMA_STATE_BUSY)
721   {
722     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
723     return HAL_ERROR;
724   }
725   else
726   {
727     /* Set Abort State  */
728     hdma->State = HAL_DMA_STATE_ABORT;
729 
730     /* Disable the stream */
731     __HAL_DMA_DISABLE(hdma);
732   }
733 
734   return HAL_OK;
735 }
736 
737 /**
738   * @brief  Polling for transfer complete.
739   * @param  hdma:          pointer to a DMA_HandleTypeDef structure that contains
740   *                        the configuration information for the specified DMA Stream.
741   * @param  CompleteLevel: Specifies the DMA level complete.
742   * @note   The polling mode is kept in this version for legacy. it is recommended to use the IT model instead.
743   *         This model could be used for debug purpose.
744   * @note   The HAL_DMA_PollForTransfer API cannot be used in circular and double buffering mode (automatic circular mode).
745   * @param  Timeout:       Timeout duration.
746   * @retval HAL status
747   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)748 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
749 {
750   HAL_StatusTypeDef status = HAL_OK;
751   uint32_t cpltlevel_mask;
752   uint32_t tickstart = HAL_GetTick();
753 
754   /* IT status register */
755   const __IO uint32_t *isr_reg;
756   /* IT clear flag register */
757   __IO uint32_t *ifcr_reg;
758 
759   /* Check the DMA peripheral handle */
760   if (hdma == NULL)
761   {
762     return HAL_ERROR;
763   }
764 
765   if (HAL_DMA_STATE_BUSY != hdma->State)
766   {
767     /* No transfer ongoing */
768     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
769     __HAL_UNLOCK(hdma);
770 
771     return HAL_ERROR;
772   }
773   /* Polling mode not supported in circular mode and double buffering mode */
774   if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) != 0U)
775   {
776     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
777     return HAL_ERROR;
778   }
779 
780   /* Get the level transfer complete flag */
781   if (CompleteLevel == HAL_DMA_FULL_TRANSFER)
782   {
783     /* Transfer Complete flag */
784       cpltlevel_mask = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
785   }
786   else
787   {
788     /* Half Transfer Complete flag */
789       cpltlevel_mask = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
790   }
791 
792   isr_reg  = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->ISR);
793   ifcr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR);
794 
795   while(((*isr_reg) & cpltlevel_mask) == 0U)
796   {
797     if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
798     {
799       if(((*isr_reg) & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
800       {
801         /* Update error code */
802         hdma->ErrorCode |= HAL_DMA_ERROR_FE;
803 
804         /* Clear the FIFO error flag */
805         (*ifcr_reg) = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
806       }
807 
808       if(((*isr_reg) & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
809       {
810         /* Update error code */
811         hdma->ErrorCode |= HAL_DMA_ERROR_DME;
812 
813         /* Clear the Direct Mode error flag */
814         (*ifcr_reg) = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
815       }
816 
817       if(((*isr_reg) & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
818       {
819         /* Update error code */
820         hdma->ErrorCode |= HAL_DMA_ERROR_TE;
821 
822         /* Clear the transfer error flag */
823         (*ifcr_reg) = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
824 
825         /* Change the DMA state */
826         hdma->State = HAL_DMA_STATE_READY;
827 
828         /* Process Unlocked */
829         __HAL_UNLOCK(hdma);
830 
831         return HAL_ERROR;
832       }
833     }
834 
835     }
836 
837     /* Check for the Timeout (Not applicable in circular mode)*/
838     if (Timeout != HAL_MAX_DELAY)
839     {
840       if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
841       {
842         /* Update error code */
843         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
844 
845         /* if timeout then abort the current transfer */
846         /* No need to check return value: as in this case we will return HAL_ERROR with HAL_DMA_ERROR_TIMEOUT error code  */
847         (void) HAL_DMA_Abort(hdma);
848           /*
849             Note that the Abort function will
850               - Clear the transfer error flags
851               - Unlock
852               - Set the State
853           */
854 
855 
856         return HAL_ERROR;
857       }
858     }
859 
860     /*Check for DMAMUX Request generator (if used) overrun status */
861     if(hdma->DMAmuxRequestGen != 0U)
862     {
863       /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
864       if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
865       {
866         /* Clear the DMAMUX request generator overrun flag */
867         hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
868 
869         /* Update error code */
870         hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
871       }
872     }
873 
874     /* Check for DMAMUX Synchronization overrun */
875     if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
876     {
877       /* Clear the DMAMUX synchro overrun flag */
878       hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
879 
880       /* Update error code */
881       hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
882     }
883 
884 
885 
886   /* Get the level transfer complete flag */
887   if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
888     {
889     /* Clear the half transfer and transfer complete flags */
890     if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
891     {
892       (*ifcr_reg) = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << (hdma->StreamIndex & 0x1FU);
893     }
894     hdma->State = HAL_DMA_STATE_READY;
895     /* Process Unlocked */
896     __HAL_UNLOCK(hdma);
897   }
898   else /*CompleteLevel = HAL_DMA_HALF_TRANSFER*/
899   {
900     /* Clear the half transfer and transfer complete flags */
901     if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
902     {
903     (*ifcr_reg) = (DMA_FLAG_HTIF0_4) << (hdma->StreamIndex & 0x1FU);
904     }
905   }
906 
907   return status;
908 }
909 
910 /**
911   * @brief  Handles DMA interrupt request.
912   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
913   *               the configuration information for the specified DMA Stream.
914   * @retval None
915   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)916 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
917 {
918   uint32_t tmpisr_dma;
919   __IO uint32_t count = 0U;
920   uint32_t timeout = SystemCoreClock / 9600U;
921 
922   /* calculate DMA base and stream number */
923   DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
924 
925   tmpisr_dma = regs_dma->ISR;
926 
927   if(IS_DMA_INSTANCE(hdma) != 0U)  /* DMA1 or DMA2 instance */
928   {
929     /* Transfer Error Interrupt management ***************************************/
930     if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
931     {
932       if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U)
933       {
934         /* Disable the transfer error interrupt */
935         ((DMA_Stream_TypeDef *)hdma->Instance)->CR  &= ~(DMA_IT_TE);
936 
937         /* Clear the transfer error flag */
938         regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
939 
940         /* Update error code */
941         hdma->ErrorCode |= HAL_DMA_ERROR_TE;
942       }
943     }
944     /* FIFO Error Interrupt management ******************************************/
945     if ((tmpisr_dma & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
946     {
947       if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != 0U)
948       {
949         /* Clear the FIFO error flag */
950         regs_dma->IFCR = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
951 
952         /* Update error code */
953         hdma->ErrorCode |= HAL_DMA_ERROR_FE;
954       }
955     }
956     /* Direct Mode Error Interrupt management ***********************************/
957     if ((tmpisr_dma & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
958     {
959       if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != 0U)
960       {
961         /* Clear the direct mode error flag */
962         regs_dma->IFCR = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
963 
964         /* Update error code */
965         hdma->ErrorCode |= HAL_DMA_ERROR_DME;
966       }
967     }
968     /* Half Transfer Complete Interrupt management ******************************/
969     if ((tmpisr_dma & (DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
970     {
971       if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U)
972       {
973         /* Clear the half transfer complete flag */
974         regs_dma->IFCR = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
975 
976         /* Multi_Buffering mode enabled */
977         if (((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
978         {
979           /* Current memory buffer used is Memory 0 */
980           if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
981           {
982             if (hdma->XferHalfCpltCallback != NULL)
983             {
984               /* Half transfer callback */
985               hdma->XferHalfCpltCallback(hdma);
986             }
987           }
988           /* Current memory buffer used is Memory 1 */
989           else
990           {
991             if (hdma->XferM1HalfCpltCallback != NULL)
992             {
993               /* Half transfer callback */
994               hdma->XferM1HalfCpltCallback(hdma);
995             }
996           }
997         }
998         else
999         {
1000           /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
1001           if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
1002           {
1003             /* Disable the half transfer interrupt */
1004             ((DMA_Stream_TypeDef *)hdma->Instance)->CR  &= ~(DMA_IT_HT);
1005           }
1006 
1007           if (hdma->XferHalfCpltCallback != NULL)
1008           {
1009             /* Half transfer callback */
1010             hdma->XferHalfCpltCallback(hdma);
1011           }
1012         }
1013       }
1014     }
1015     /* Transfer Complete Interrupt management ***********************************/
1016     if ((tmpisr_dma & (DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
1017     {
1018       if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U)
1019       {
1020         /* Clear the transfer complete flag */
1021         regs_dma->IFCR = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
1022 
1023         if (HAL_DMA_STATE_ABORT == hdma->State)
1024         {
1025           /* Disable all the transfer interrupts */
1026           ((DMA_Stream_TypeDef *)hdma->Instance)->CR  &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME);
1027           ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
1028 
1029           if ((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
1030           {
1031             ((DMA_Stream_TypeDef *)hdma->Instance)->CR  &= ~(DMA_IT_HT);
1032           }
1033 
1034           /* Clear all interrupt flags at correct offset within the register */
1035           regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
1036 
1037           /* Change the DMA state */
1038           hdma->State = HAL_DMA_STATE_READY;
1039 
1040           /* Process Unlocked */
1041           __HAL_UNLOCK(hdma);
1042 
1043           if (hdma->XferAbortCallback != NULL)
1044           {
1045             hdma->XferAbortCallback(hdma);
1046           }
1047           return;
1048         }
1049 
1050         if (((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
1051         {
1052           /* Current memory buffer used is Memory 0 */
1053           if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
1054           {
1055             if (hdma->XferM1CpltCallback != NULL)
1056             {
1057               /* Transfer complete Callback for memory1 */
1058               hdma->XferM1CpltCallback(hdma);
1059             }
1060           }
1061           /* Current memory buffer used is Memory 1 */
1062           else
1063           {
1064             if (hdma->XferCpltCallback != NULL)
1065             {
1066               /* Transfer complete Callback for memory0 */
1067               hdma->XferCpltCallback(hdma);
1068             }
1069           }
1070         }
1071         /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
1072         else
1073         {
1074           if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
1075           {
1076             /* Disable the transfer complete interrupt */
1077             ((DMA_Stream_TypeDef *)hdma->Instance)->CR  &= ~(DMA_IT_TC);
1078 
1079             /* Change the DMA state */
1080             hdma->State = HAL_DMA_STATE_READY;
1081             /* Process Unlocked */
1082             __HAL_UNLOCK(hdma);
1083           }
1084 
1085           if (hdma->XferCpltCallback != NULL)
1086           {
1087             /* Transfer complete callback */
1088             hdma->XferCpltCallback(hdma);
1089           }
1090         }
1091       }
1092     }
1093 
1094     /* manage error case */
1095     if (hdma->ErrorCode != HAL_DMA_ERROR_NONE)
1096     {
1097       if ((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U)
1098       {
1099         hdma->State = HAL_DMA_STATE_ABORT;
1100 
1101         /* Disable the stream */
1102         __HAL_DMA_DISABLE(hdma);
1103 
1104         do
1105         {
1106           if (++count > timeout)
1107           {
1108             break;
1109           }
1110         }
1111         while ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);
1112 
1113         if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
1114         {
1115           /* Change the DMA state to error if DMA disable fails */
1116           hdma->State = HAL_DMA_STATE_ERROR;
1117         }
1118         else
1119         {
1120           /* Change the DMA state to Ready if DMA disable success */
1121           hdma->State = HAL_DMA_STATE_READY;
1122         }
1123         /* Process Unlocked */
1124         __HAL_UNLOCK(hdma);
1125       }
1126 
1127       if (hdma->XferErrorCallback != NULL)
1128       {
1129         /* Transfer error callback */
1130         hdma->XferErrorCallback(hdma);
1131       }
1132     }
1133   }
1134   else
1135   {
1136     /* Nothing To Do */
1137   }
1138 }
1139 
1140 /**
1141   * @brief  Register callbacks
1142   * @param  hdma:                 pointer to a DMA_HandleTypeDef structure that contains
1143   *                               the configuration information for the specified DMA Stream.
1144   * @param  CallbackID:           User Callback identifier
1145   *                               a DMA_HandleTypeDef structure as parameter.
1146   * @param  pCallback:            pointer to private callback function which has pointer to
1147   *                               a DMA_HandleTypeDef structure as parameter.
1148   * @retval HAL status
1149   */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))1150 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
1151 {
1152 
1153   HAL_StatusTypeDef status = HAL_OK;
1154 
1155   /* Check the DMA peripheral handle */
1156   if (hdma == NULL)
1157   {
1158     return HAL_ERROR;
1159   }
1160 
1161   /* Process locked */
1162   __HAL_LOCK(hdma);
1163 
1164   if (HAL_DMA_STATE_READY == hdma->State)
1165   {
1166     switch (CallbackID)
1167     {
1168       case  HAL_DMA_XFER_CPLT_CB_ID:
1169         hdma->XferCpltCallback = pCallback;
1170         break;
1171 
1172       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
1173         hdma->XferHalfCpltCallback = pCallback;
1174         break;
1175 
1176       case  HAL_DMA_XFER_M1CPLT_CB_ID:
1177         hdma->XferM1CpltCallback = pCallback;
1178         break;
1179 
1180       case  HAL_DMA_XFER_M1HALFCPLT_CB_ID:
1181         hdma->XferM1HalfCpltCallback = pCallback;
1182         break;
1183 
1184       case  HAL_DMA_XFER_ERROR_CB_ID:
1185         hdma->XferErrorCallback = pCallback;
1186         break;
1187 
1188       case  HAL_DMA_XFER_ABORT_CB_ID:
1189         hdma->XferAbortCallback = pCallback;
1190         break;
1191 
1192       default:
1193       status =  HAL_ERROR;
1194         break;
1195     }
1196   }
1197   else
1198   {
1199     /* Return error status */
1200     status =  HAL_ERROR;
1201   }
1202 
1203   /* Release Lock */
1204   __HAL_UNLOCK(hdma);
1205 
1206   return status;
1207 }
1208 
1209 /**
1210   * @brief  UnRegister callbacks
1211   * @param  hdma:                 pointer to a DMA_HandleTypeDef structure that contains
1212   *                               the configuration information for the specified DMA Stream.
1213   * @param  CallbackID:           User Callback identifier
1214   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
1215   * @retval HAL status
1216   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)1217 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
1218 {
1219   HAL_StatusTypeDef status = HAL_OK;
1220 
1221   /* Check the DMA peripheral handle */
1222   if (hdma == NULL)
1223   {
1224     return HAL_ERROR;
1225   }
1226 
1227   /* Process locked */
1228   __HAL_LOCK(hdma);
1229 
1230   if (HAL_DMA_STATE_READY == hdma->State)
1231   {
1232     switch (CallbackID)
1233     {
1234       case  HAL_DMA_XFER_CPLT_CB_ID:
1235         hdma->XferCpltCallback = NULL;
1236         break;
1237 
1238       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
1239         hdma->XferHalfCpltCallback = NULL;
1240         break;
1241 
1242       case  HAL_DMA_XFER_M1CPLT_CB_ID:
1243         hdma->XferM1CpltCallback = NULL;
1244         break;
1245 
1246       case  HAL_DMA_XFER_M1HALFCPLT_CB_ID:
1247         hdma->XferM1HalfCpltCallback = NULL;
1248         break;
1249 
1250       case  HAL_DMA_XFER_ERROR_CB_ID:
1251         hdma->XferErrorCallback = NULL;
1252         break;
1253 
1254       case  HAL_DMA_XFER_ABORT_CB_ID:
1255         hdma->XferAbortCallback = NULL;
1256         break;
1257 
1258       case   HAL_DMA_XFER_ALL_CB_ID:
1259         hdma->XferCpltCallback = NULL;
1260         hdma->XferHalfCpltCallback = NULL;
1261         hdma->XferM1CpltCallback = NULL;
1262         hdma->XferM1HalfCpltCallback = NULL;
1263         hdma->XferErrorCallback = NULL;
1264         hdma->XferAbortCallback = NULL;
1265         break;
1266 
1267       default:
1268         status = HAL_ERROR;
1269         break;
1270     }
1271   }
1272   else
1273   {
1274     status = HAL_ERROR;
1275   }
1276 
1277   /* Release Lock */
1278   __HAL_UNLOCK(hdma);
1279 
1280   return status;
1281 }
1282 
1283 /**
1284   * @}
1285   */
1286 
1287 /** @addtogroup DMA_Exported_Functions_Group3
1288   *
1289 @verbatim
1290  ===============================================================================
1291                     ##### State and Errors functions #####
1292  ===============================================================================
1293     [..]
1294     This subsection provides functions allowing to
1295       (+) Check the DMA state
1296       (+) Get error code
1297 
1298 @endverbatim
1299   * @{
1300   */
1301 
1302 /**
1303   * @brief  Returns the DMA state.
1304   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
1305   *               the configuration information for the specified DMA Stream.
1306   * @retval HAL state
1307   */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)1308 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
1309 {
1310   return hdma->State;
1311 }
1312 
1313 /**
1314   * @brief  Return the DMA error code
1315   * @param  hdma : pointer to a DMA_HandleTypeDef structure that contains
1316   *              the configuration information for the specified DMA Stream.
1317   * @retval DMA Error Code
1318   */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)1319 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
1320 {
1321   return hdma->ErrorCode;
1322 }
1323 
1324 /**
1325   * @}
1326   */
1327 
1328 /**
1329   * @}
1330   */
1331 
1332 /** @addtogroup DMA_Private_Functions
1333   * @{
1334   */
1335 
1336 /**
1337   * @brief  Sets the DMA Transfer parameter.
1338   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
1339   *                     the configuration information for the specified DMA Stream.
1340   * @param  SrcAddress: The source memory Buffer address
1341   * @param  DstAddress: The destination memory Buffer address
1342   * @param  DataLength: The length of data to be transferred from source to destination
1343   * @retval None
1344   */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)1345 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
1346 {
1347   /* calculate DMA base and stream number */
1348   DMA_Base_Registers  *regs_dma  = (DMA_Base_Registers *)hdma->StreamBaseAddress;
1349 
1350   /* Clear the DMAMUX synchro overrun flag */
1351   hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
1352 
1353   if(hdma->DMAmuxRequestGen != 0U)
1354   {
1355     /* Clear the DMAMUX request generator overrun flag */
1356     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
1357   }
1358   /* Clear all interrupt flags at correct offset within the register */
1359     regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
1360 
1361   /* Clear DBM bit */
1362   ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
1363 
1364   /* Configure DMA Stream data length */
1365   ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = DataLength;
1366 
1367   /* Peripheral to Memory */
1368   if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1369   {
1370     /* Configure DMA Stream destination address */
1371     ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = DstAddress;
1372 
1373     /* Configure DMA Stream source address */
1374     ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = SrcAddress;
1375   }
1376   /* Memory to Peripheral */
1377   else
1378   {
1379     /* Configure DMA Stream source address */
1380     ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = SrcAddress;
1381 
1382     /* Configure DMA Stream destination address */
1383     ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = DstAddress;
1384   }
1385 }
1386 
1387 /**
1388   * @brief  Returns the DMA Stream base address depending on stream number
1389   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
1390   *                     the configuration information for the specified DMA Stream.
1391   * @retval Stream base address
1392   */
DMA_CalcBaseAndBitshift(DMA_HandleTypeDef * hdma)1393 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
1394 {
1395   uint32_t stream_number = (((uint32_t)((uint32_t *)hdma->Instance) & 0xFFU) - 16U) / 24U;
1396 
1397   /* lookup table for necessary bitshift of flags within status registers */
1398   static const uint8_t flagBitshiftOffset[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U};
1399   hdma->StreamIndex = flagBitshiftOffset[stream_number & 0x7U];
1400 
1401   if (stream_number > 3U)
1402   {
1403     /* return pointer to HISR and HIFCR */
1404     hdma->StreamBaseAddress = (((uint32_t)((uint32_t *)hdma->Instance) & (uint32_t)(~0x3FFU)) + 4U);
1405   }
1406   else
1407   {
1408     /* return pointer to LISR and LIFCR */
1409     hdma->StreamBaseAddress = ((uint32_t)((uint32_t *)hdma->Instance) & (uint32_t)(~0x3FFU));
1410   }
1411 
1412   return hdma->StreamBaseAddress;
1413 }
1414 
1415 /**
1416   * @brief  Check compatibility between FIFO threshold level and size of the memory burst
1417   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
1418   *                     the configuration information for the specified DMA Stream.
1419   * @retval HAL status
1420   */
DMA_CheckFifoParam(DMA_HandleTypeDef * hdma)1421 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma)
1422 {
1423   HAL_StatusTypeDef status = HAL_OK;
1424 
1425   /* Memory Data size equal to Byte */
1426   if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_BYTE)
1427   {
1428     switch (hdma->Init.FIFOThreshold)
1429     {
1430       case DMA_FIFO_THRESHOLD_1QUARTERFULL:
1431       case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
1432 
1433         if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
1434         {
1435           status = HAL_ERROR;
1436         }
1437         break;
1438 
1439       case DMA_FIFO_THRESHOLD_HALFFULL:
1440         if (hdma->Init.MemBurst == DMA_MBURST_INC16)
1441         {
1442           status = HAL_ERROR;
1443         }
1444         break;
1445 
1446       case DMA_FIFO_THRESHOLD_FULL:
1447         break;
1448 
1449       default:
1450         break;
1451     }
1452   }
1453 
1454   /* Memory Data size equal to Half-Word */
1455   else if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
1456   {
1457     switch (hdma->Init.FIFOThreshold)
1458     {
1459       case DMA_FIFO_THRESHOLD_1QUARTERFULL:
1460       case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
1461         status = HAL_ERROR;
1462         break;
1463 
1464       case DMA_FIFO_THRESHOLD_HALFFULL:
1465         if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
1466         {
1467           status = HAL_ERROR;
1468         }
1469         break;
1470 
1471       case DMA_FIFO_THRESHOLD_FULL:
1472         if (hdma->Init.MemBurst == DMA_MBURST_INC16)
1473         {
1474           status = HAL_ERROR;
1475         }
1476         break;
1477 
1478       default:
1479         break;
1480     }
1481   }
1482 
1483   /* Memory Data size equal to Word */
1484   else
1485   {
1486     switch (hdma->Init.FIFOThreshold)
1487     {
1488       case DMA_FIFO_THRESHOLD_1QUARTERFULL:
1489       case DMA_FIFO_THRESHOLD_HALFFULL:
1490       case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
1491         status = HAL_ERROR;
1492         break;
1493 
1494       case DMA_FIFO_THRESHOLD_FULL:
1495         if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
1496         {
1497           status = HAL_ERROR;
1498         }
1499         break;
1500 
1501       default:
1502         break;
1503     }
1504   }
1505 
1506   return status;
1507 }
1508 
1509 /**
1510   * @brief  Updates the DMA handle with the DMAMUX  channel and status mask depending on stream number
1511   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
1512   *                     the configuration information for the specified DMA Stream.
1513   * @retval HAL status
1514   */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1515 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1516 {
1517   uint32_t stream_number;
1518   uint32_t stream_baseaddress = (uint32_t)((uint32_t *)hdma->Instance);
1519   /*DMA1/DMA2 Streams are connected to DMAMUX1 channels*/
1520   stream_number = (((uint32_t)((uint32_t *)hdma->Instance) & 0xFFU) - 16U) / 24U;
1521 
1522   if ((stream_baseaddress <= ((uint32_t)DMA2_Stream7)) && \
1523       (stream_baseaddress >= ((uint32_t)DMA2_Stream0)))
1524   {
1525     stream_number += 8U;
1526   }
1527 
1528   hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_Channel0) + (stream_number * 4U)));
1529   hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1530   hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU);
1531 
1532 }
1533 
1534 /**
1535   * @brief  Updates the DMA handle with the DMAMUX  request generator params
1536   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
1537   *                     the configuration information for the specified DMA Stream.
1538   * @retval HAL status
1539   */
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1540 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1541 {
1542   uint32_t request =  hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1543 
1544   if ((request >= DMA_REQUEST_GENERATOR0) && (request <= DMA_REQUEST_GENERATOR7))
1545   {
1546     /*DMA1 and DMA2 Streams use DMAMUX1 request generator blocks*/
1547     hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
1548     hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1549     hdma->DMAmuxRequestGenStatusMask = 1UL << (request - 1U);
1550   }
1551 }
1552 
1553 /**
1554   * @}
1555   */
1556 
1557 #endif /* HAL_DMA_MODULE_ENABLED */
1558 /**
1559   * @}
1560   */
1561 
1562 /**
1563   * @}
1564   */
1565