1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_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) 2022 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 Channel
28        (except for internal SRAM / FLASH memories: no initialization is
29        necessary). Please refer to the Reference manual for connection between peripherals
30        and DMA requests.
31 
32    (#) For a given Channel, program the required configuration through the following parameters:
33        Channel request, Transfer Direction, Source and Destination data formats,
34        Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
35        using HAL_DMA_Init() function.
36 
37        Prior to HAL_DMA_Init the CLK shall be enabled for both DMA & DMAMUX
38        thanks to:
39        DMA1   :       __HAL_RCC_DMA1_CLK_ENABLE();
40 
41    (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
42        detection.
43 
44    (#) Use HAL_DMA_Abort() function to abort the current transfer
45 
46      -@-   In Memory-to-Memory transfer mode, Circular mode is not allowed.
47      *** Polling mode IO operation ***
48      =================================
49     [..]
50           (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
51               address and destination address and the Length of data to be transferred
52           (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
53               case a fixed Timeout can be configured by User depending from his application.
54 
55      *** Interrupt mode IO operation ***
56      ===================================
57     [..]
58           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
59           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
60           (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
61               Source address and destination address and the Length of data to be transferred.
62               In this case the DMA interrupt is configured
63           (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
64           (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
65               add his own function by customization of function pointer XferCpltCallback and
66               XferErrorCallback (i.e. a member of DMA handle structure).
67 
68      *** DMA HAL driver macros list ***
69      =============================================
70       [..]
71        Below the list of most used macros in DMA HAL driver.
72 
73        (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
74        (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
75        (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
76        (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
77        (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
78        (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
79        (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not.
80 
81      [..]
82       (@) You can refer to the DMA HAL driver header file for more useful macros
83 
84   @endverbatim
85   ******************************************************************************
86   */
87 
88 /* Includes ------------------------------------------------------------------*/
89 #include "stm32c0xx_hal.h"
90 
91 /** @addtogroup STM32C0xx_HAL_Driver
92   * @{
93   */
94 
95 /** @defgroup DMA DMA
96   * @brief DMA HAL module driver
97   * @{
98   */
99 
100 #ifdef HAL_DMA_MODULE_ENABLED
101 
102 /* Private typedef -----------------------------------------------------------*/
103 /* Private define ------------------------------------------------------------*/
104 /* Private macro -------------------------------------------------------------*/
105 /* Private variables ---------------------------------------------------------*/
106 /* Private function prototypes -----------------------------------------------*/
107 
108 /** @defgroup DMA_Private_Functions DMA Private Functions
109   * @{
110   */
111 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
112 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
113 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
114 
115 /**
116   * @}
117   */
118 
119 /* Exported functions ---------------------------------------------------------*/
120 
121 /** @defgroup DMA_Exported_Functions DMA Exported Functions
122   * @{
123   */
124 
125 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
126   *  @brief   Initialization and de-initialization functions
127   *
128 @verbatim
129  ===============================================================================
130              ##### Initialization and de-initialization functions  #####
131  ===============================================================================
132     [..]
133     This section provides functions allowing to initialize the DMA Channel source
134     and destination addresses, incrementation and data sizes, transfer direction,
135     circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
136     [..]
137     The HAL_DMA_Init() function follows the DMA configuration procedures as described in
138     reference manual.
139 
140 @endverbatim
141   * @{
142   */
143 
144 /**
145   * @brief  Initialize the DMA according to the specified
146   *         parameters in the DMA_InitTypeDef and initialize the associated handle.
147   * @param  hdma  Pointer to a DMA_HandleTypeDef structure that contains
148   *               the configuration information for the specified DMA Channel.
149   * @retval HAL status
150   */
HAL_DMA_Init(DMA_HandleTypeDef * hdma)151 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
152 {
153   /* Check the DMA handle allocation */
154   if (hdma == NULL)
155   {
156     return HAL_ERROR;
157   }
158 
159   /* Check the parameters */
160   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
161   assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
162   assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
163   assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
164   assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
165   assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
166   assert_param(IS_DMA_MODE(hdma->Init.Mode));
167   assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
168 
169   /* calculation of the channel index */
170   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - \
171                                                                                 (uint32_t)DMA1_Channel1)) << 2U;
172   /* Change DMA peripheral state */
173   hdma->State = HAL_DMA_STATE_BUSY;
174 
175   /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
176   CLEAR_BIT(hdma->Instance->CCR, (DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  | \
177                                   DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   | \
178                                   DMA_CCR_DIR   | DMA_CCR_MEM2MEM));
179 
180   /* Set the DMA Channel configuration */
181   SET_BIT(hdma->Instance->CCR, (hdma->Init.Direction           |                               \
182                                 hdma->Init.PeriphInc           | hdma->Init.MemInc           | \
183                                 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | \
184                                 hdma->Init.Mode                | hdma->Init.Priority));
185 
186   /* Initialize parameters for DMAMUX channel :
187      DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
188   */
189   DMA_CalcDMAMUXChannelBaseAndMask(hdma);
190 
191   if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
192   {
193     /* if memory to memory force the request to 0*/
194     hdma->Init.Request = DMA_REQUEST_MEM2MEM;
195   }
196 
197   /* Set peripheral request  to DMAMUX channel */
198   hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
199 
200   /* Clear the DMAMUX synchro overrun flag */
201   hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
202 
203   if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
204   {
205     /* Initialize parameters for DMAMUX request generator :
206        DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
207     */
208     DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
209 
210     /* Reset the DMAMUX request generator register*/
211     hdma->DMAmuxRequestGen->RGCR = 0U;
212 
213     /* Clear the DMAMUX request generator overrun flag */
214     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
215   }
216   else
217   {
218     hdma->DMAmuxRequestGen = 0U;
219     hdma->DMAmuxRequestGenStatus = 0U;
220     hdma->DMAmuxRequestGenStatusMask = 0U;
221   }
222 
223   /* Initialize the error code */
224   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
225 
226   /* Initialize the DMA state*/
227   hdma->State  = HAL_DMA_STATE_READY;
228 
229   /* Release Lock */
230   __HAL_UNLOCK(hdma);
231 
232   return HAL_OK;
233 }
234 
235 /**
236   * @brief  DeInitialize the DMA peripheral.
237   * @param  hdma  pointer to a DMA_HandleTypeDef structure that contains
238   *               the configuration information for the specified DMA Channel.
239   * @retval HAL status
240   */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)241 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
242 {
243   /* Check the DMA handle allocation */
244   if (NULL == hdma)
245   {
246     return HAL_ERROR;
247   }
248 
249   /* Check the parameters */
250   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
251 
252   /* Disable the selected DMA Channelx */
253   __HAL_DMA_DISABLE(hdma);
254 
255   /* calculation of the channel index */
256   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - \
257                                                                                 (uint32_t)DMA1_Channel1)) << 2U;
258 
259   /* Reset DMA Channel control register */
260   hdma->Instance->CCR  = 0U;
261 
262   /* Clear all flags */
263   __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
264 
265   /* Initialize parameters for DMAMUX channel :
266      DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
267 
268   DMA_CalcDMAMUXChannelBaseAndMask(hdma);
269 
270   /* Reset the DMAMUX channel that corresponds to the DMA channel */
271   hdma->DMAmuxChannel->CCR = 0U;
272 
273   /* Clear the DMAMUX synchro overrun flag */
274   hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
275 
276   /* Reset Request generator parameters if any */
277   if (((hdma->Init.Request >  0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
278   {
279     /* Initialize parameters for DMAMUX request generator :
280        DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
281     */
282     DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
283 
284     /* Reset the DMAMUX request generator register*/
285     hdma->DMAmuxRequestGen->RGCR = 0U;
286 
287     /* Clear the DMAMUX request generator overrun flag */
288     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
289   }
290 
291   /* Clean callbacks */
292   hdma->XferCpltCallback = NULL;
293   hdma->XferHalfCpltCallback = NULL;
294   hdma->XferErrorCallback = NULL;
295   hdma->XferAbortCallback = NULL;
296 
297   hdma->DMAmuxRequestGen = 0U;
298   hdma->DMAmuxRequestGenStatus = 0U;
299   hdma->DMAmuxRequestGenStatusMask = 0U;
300 
301   /* Initialize the error code */
302   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
303 
304   /* Initialize the DMA state */
305   hdma->State = HAL_DMA_STATE_RESET;
306 
307   /* Release Lock */
308   __HAL_UNLOCK(hdma);
309 
310   return HAL_OK;
311 }
312 
313 /**
314   * @}
315   */
316 
317 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
318   *  @brief   Input and Output operation functions
319   *
320 @verbatim
321  ===============================================================================
322                       #####  IO operation functions  #####
323  ===============================================================================
324     [..]  This section provides functions allowing to:
325       (+) Configure the source, destination address and data length and Start DMA transfer
326       (+) Configure the source, destination address and data length and
327           Start DMA transfer with interrupt
328       (+) Abort DMA transfer
329       (+) Poll for transfer complete
330       (+) Handle DMA interrupt request
331 
332 @endverbatim
333   * @{
334   */
335 
336 /**
337   * @brief  Start the DMA Transfer.
338   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
339   *               the configuration information for the specified DMA Channel.
340   * @param SrcAddress The source memory Buffer address
341   * @param DstAddress The destination memory Buffer address
342   * @param DataLength The length of data to be transferred from source to destination
343   * @retval HAL status
344   */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)345 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
346 {
347   HAL_StatusTypeDef status = HAL_OK;
348 
349   /* Check the parameters */
350   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
351 
352   /* Process locked */
353   __HAL_LOCK(hdma);
354 
355   if (HAL_DMA_STATE_READY == hdma->State)
356   {
357     /* Change DMA peripheral state */
358     hdma->State = HAL_DMA_STATE_BUSY;
359     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
360 
361     /* Disable the peripheral */
362     __HAL_DMA_DISABLE(hdma);
363 
364     /* Configure the source, destination address and the data length & clear flags*/
365     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
366 
367     /* Enable the Peripheral */
368     __HAL_DMA_ENABLE(hdma);
369   }
370   else
371   {
372     /* Process Unlocked */
373     __HAL_UNLOCK(hdma);
374     status = HAL_BUSY;
375   }
376 
377   /* Process locked */
378   __HAL_UNLOCK(hdma);
379 
380   return status;
381 }
382 
383 /**
384   * @brief  Start the DMA Transfer with interrupt enabled.
385   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
386   *               the configuration information for the specified DMA Channel.
387   * @param SrcAddress The source memory Buffer address
388   * @param DstAddress The destination memory Buffer address
389   * @param DataLength The length of data to be transferred from source to destination
390   * @retval HAL status
391   */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)392 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress,
393                                    uint32_t DataLength)
394 {
395   HAL_StatusTypeDef status = HAL_OK;
396 
397   /* Check the parameters */
398   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
399 
400   /* Process locked */
401   __HAL_LOCK(hdma);
402 
403   if (HAL_DMA_STATE_READY == hdma->State)
404   {
405     /* Change DMA peripheral state */
406     hdma->State = HAL_DMA_STATE_BUSY;
407     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
408 
409     /* Disable the peripheral */
410     __HAL_DMA_DISABLE(hdma);
411 
412     /* Configure the source, destination address and the data length & clear flags*/
413     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
414 
415     /* Enable the transfer complete interrupt */
416     /* Enable the transfer Error interrupt */
417     if (NULL != hdma->XferHalfCpltCallback)
418     {
419       /* Enable the Half transfer complete interrupt as well */
420       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
421     }
422     else
423     {
424       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
425       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
426     }
427 
428     /* Check if DMAMUX Synchronization is enabled*/
429     if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
430     {
431       /* Enable DMAMUX sync overrun IT*/
432       hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
433     }
434 
435     if (hdma->DMAmuxRequestGen != 0U)
436     {
437       /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
438       /* enable the request gen overrun IT*/
439       hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
440     }
441 
442     /* Enable the Peripheral */
443     __HAL_DMA_ENABLE(hdma);
444   }
445   else
446   {
447     /* Process Unlocked */
448     __HAL_UNLOCK(hdma);
449 
450     /* Remain BUSY */
451     status = HAL_BUSY;
452   }
453 
454   /* Process unlocked */
455   __HAL_UNLOCK(hdma);
456 
457   return status;
458 }
459 
460 /**
461   * @brief  Abort the DMA Transfer.
462   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
463   *               the configuration information for the specified DMA Channel.
464     * @retval HAL status
465   */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)466 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
467 {
468   /* Check the DMA peripheral handle */
469   if (NULL == hdma)
470   {
471     return HAL_ERROR;
472   }
473 
474   /* Check the DMA peripheral state */
475   if (hdma->State != HAL_DMA_STATE_BUSY)
476   {
477     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
478 
479     /* Process Unlocked */
480     __HAL_UNLOCK(hdma);
481 
482     return HAL_ERROR;
483   }
484   else
485   {
486     /* Disable DMA IT */
487     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
488 
489     /* disable the DMAMUX sync overrun IT*/
490     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
491 
492     /* Disable the channel */
493     __HAL_DMA_DISABLE(hdma);
494 
495     /* Clear all flags */
496     __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex  & 0x1cU)));
497 
498     /* Clear the DMAMUX synchro overrun flag */
499     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
500 
501     if (hdma->DMAmuxRequestGen != 0U)
502     {
503       /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
504       /* disable the request gen overrun IT*/
505       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
506 
507       /* Clear the DMAMUX request generator overrun flag */
508       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
509     }
510 
511     /* Change the DMA state */
512     hdma->State = HAL_DMA_STATE_READY;
513 
514     /* Process Unlocked */
515     __HAL_UNLOCK(hdma);
516   }
517 
518   return HAL_OK;
519 }
520 
521 /**
522   * @brief  Aborts the DMA Transfer in Interrupt mode.
523   * @param  hdma    pointer to a DMA_HandleTypeDef structure that contains
524   *                 the configuration information for the specified DMA Stream.
525   * @retval HAL status
526   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)527 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
528 {
529   HAL_StatusTypeDef status = HAL_OK;
530 
531   /* Process Unlocked/locked */
532   __HAL_UNLOCK(hdma);
533   __HAL_LOCK(hdma);
534 
535   if (HAL_DMA_STATE_BUSY != hdma->State)
536   {
537     /* no transfer ongoing */
538     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
539 
540     status = HAL_ERROR;
541   }
542   else
543   {
544     /* Disable DMA IT */
545     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
546 
547     /* Disable the channel */
548     __HAL_DMA_DISABLE(hdma);
549 
550     /* disable the DMAMUX sync overrun IT*/
551     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
552 
553     /* Clear all flags */
554     __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
555 
556     /* Clear the DMAMUX synchro overrun flag */
557     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
558 
559     if (hdma->DMAmuxRequestGen != 0U)
560     {
561       /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
562       /* disable the request gen overrun IT*/
563       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
564 
565       /* Clear the DMAMUX request generator overrun flag */
566       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
567     }
568 
569     /* Change the DMA state */
570     hdma->State = HAL_DMA_STATE_READY;
571 
572     /* Process Unlocked */
573     __HAL_UNLOCK(hdma);
574 
575     /* Call User Abort callback */
576     if (hdma->XferAbortCallback != NULL)
577     {
578       hdma->XferAbortCallback(hdma);
579     }
580   }
581   return status;
582 }
583 
584 /**
585   * @brief  Polling for transfer complete.
586   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
587   *                  the configuration information for the specified DMA Channel.
588   * @param CompleteLevel Specifies the DMA level complete.
589   * @param Timeout Timeout duration.
590   * @retval HAL status
591   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)592 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel,
593                                           uint32_t Timeout)
594 {
595   uint32_t temp;
596   uint32_t tickstart;
597 
598   /* Process unlocked */
599   __HAL_UNLOCK(hdma);
600 
601   if (HAL_DMA_STATE_BUSY != hdma->State)
602   {
603     /* no transfer ongoing */
604     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
605     __HAL_UNLOCK(hdma);
606     return HAL_ERROR;
607   }
608 
609   /* Polling mode not supported in circular mode */
610   if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
611   {
612     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
613     return HAL_ERROR;
614   }
615 
616   /* Get the level transfer complete flag */
617   if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
618   {
619     /* Transfer Complete flag */
620     temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
621   }
622   else
623   {
624     /* Half Transfer Complete flag */
625     temp = DMA_FLAG_HT1 << (hdma->ChannelIndex  & 0x1cU);
626   }
627 
628   /* Get tick */
629   tickstart = HAL_GetTick();
630 
631   while (0U == __HAL_DMA_GET_FLAG(hdma, temp))
632   {
633     if (0U != __HAL_DMA_GET_FLAG(hdma, (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))))
634     {
635       /* When a DMA transfer error occurs */
636       /* A hardware clear of its EN bits is performed */
637       /* Clear all flags */
638       __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1cU)));
639 
640       /* Update error code */
641       hdma->ErrorCode = HAL_DMA_ERROR_TE;
642 
643       /* Change the DMA state */
644       hdma->State = HAL_DMA_STATE_READY;
645 
646       /* Process Unlocked */
647       __HAL_UNLOCK(hdma);
648 
649       return HAL_ERROR;
650     }
651     /* Check for the Timeout */
652     if (Timeout != HAL_MAX_DELAY)
653     {
654       if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
655       {
656         /* Update error code */
657         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
658 
659         /* Change the DMA state */
660         hdma->State = HAL_DMA_STATE_READY;
661 
662         /* Process Unlocked */
663         __HAL_UNLOCK(hdma);
664 
665         return HAL_ERROR;
666       }
667     }
668   }
669 
670   /*Check for DMAMUX Request generator (if used) overrun status */
671   if (hdma->DMAmuxRequestGen != 0U)
672   {
673     /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
674     if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
675     {
676       /* Disable the request gen overrun interrupt */
677       hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
678 
679       /* Clear the DMAMUX request generator overrun flag */
680       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
681 
682       /* Update error code */
683       hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
684     }
685   }
686 
687   /* Check for DMAMUX Synchronization overrun */
688   if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
689   {
690     /* Clear the DMAMUX synchro overrun flag */
691     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
692 
693     /* Update error code */
694     hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
695   }
696 
697   if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
698   {
699     /* Clear the transfer complete flag */
700     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)));
701 
702     /* The selected Channelx EN bit is cleared (DMA is disabled and
703     all transfers are complete) */
704     hdma->State = HAL_DMA_STATE_READY;
705   }
706   else
707   {
708     /* Clear the half transfer complete flag */
709     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU)));
710   }
711 
712   /* Process unlocked */
713   __HAL_UNLOCK(hdma);
714 
715   return HAL_OK;
716 }
717 
718 /**
719   * @brief  Handle DMA interrupt request.
720   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
721   *               the configuration information for the specified DMA Channel.
722   * @retval None
723   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)724 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
725 {
726   uint32_t flag_it = DMA1->ISR;
727   uint32_t source_it = hdma->Instance->CCR;
728 
729   /* Half Transfer Complete Interrupt management ******************************/
730   if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
731   {
732     /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
733     if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
734     {
735       /* Disable the half transfer interrupt */
736       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
737     }
738     /* Clear the half transfer complete flag */
739     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU)));
740 
741     /* DMA peripheral state is not updated in Half Transfer */
742     /* but in Transfer Complete case */
743 
744     if (hdma->XferHalfCpltCallback != NULL)
745     {
746       /* Half transfer callback */
747       hdma->XferHalfCpltCallback(hdma);
748     }
749   }
750 
751   /* Transfer Complete Interrupt management ***********************************/
752   else if ((0U != (flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)))) && (0U != (source_it & DMA_IT_TC)))
753   {
754     if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
755     {
756       /* Disable the transfer complete and error interrupt */
757       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
758 
759       /* Change the DMA state */
760       hdma->State = HAL_DMA_STATE_READY;
761     }
762     /* Clear the transfer complete flag */
763     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU)));
764 
765     /* Process Unlocked */
766     __HAL_UNLOCK(hdma);
767 
768     if (hdma->XferCpltCallback != NULL)
769     {
770       /* Transfer complete callback */
771       hdma->XferCpltCallback(hdma);
772     }
773   }
774 
775   /* Transfer Error Interrupt management **************************************/
776   else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
777   {
778     /* When a DMA transfer error occurs */
779     /* A hardware clear of its EN bits is performed */
780     /* Disable ALL DMA IT */
781     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
782 
783     /* Clear all flags */
784     __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
785 
786     /* Update error code */
787     hdma->ErrorCode = HAL_DMA_ERROR_TE;
788 
789     /* Change the DMA state */
790     hdma->State = HAL_DMA_STATE_READY;
791 
792     /* Process Unlocked */
793     __HAL_UNLOCK(hdma);
794 
795     if (hdma->XferErrorCallback != NULL)
796     {
797       /* Transfer error callback */
798       hdma->XferErrorCallback(hdma);
799     }
800   }
801   else
802   {
803     /* Nothing To Do */
804   }
805   return;
806 }
807 
808 /**
809   * @brief  Register callbacks
810   * @param  hdma                  pointer to a DMA_HandleTypeDef structure that contains
811   *                               the configuration information for the specified DMA Stream.
812   * @param  CallbackID            User Callback identifier
813   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
814   * @param  pCallback             pointer to private callback function which has pointer to
815   *                               a DMA_HandleTypeDef structure as parameter.
816   * @retval HAL status
817   */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))818 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID,
819                                            void (* pCallback)(DMA_HandleTypeDef *_hdma))
820 {
821   HAL_StatusTypeDef status = HAL_OK;
822 
823   /* Process locked */
824   __HAL_LOCK(hdma);
825 
826   if (HAL_DMA_STATE_READY == hdma->State)
827   {
828     switch (CallbackID)
829     {
830       case  HAL_DMA_XFER_CPLT_CB_ID:
831         hdma->XferCpltCallback = pCallback;
832         break;
833 
834       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
835         hdma->XferHalfCpltCallback = pCallback;
836         break;
837 
838       case  HAL_DMA_XFER_ERROR_CB_ID:
839         hdma->XferErrorCallback = pCallback;
840         break;
841 
842       case  HAL_DMA_XFER_ABORT_CB_ID:
843         hdma->XferAbortCallback = pCallback;
844         break;
845 
846       default:
847         status = HAL_ERROR;
848         break;
849     }
850   }
851   else
852   {
853     status = HAL_ERROR;
854   }
855 
856   /* Release Lock */
857   __HAL_UNLOCK(hdma);
858 
859   return status;
860 }
861 
862 /**
863   * @brief  UnRegister callbacks
864   * @param  hdma                  pointer to a DMA_HandleTypeDef structure that contains
865   *                               the configuration information for the specified DMA Stream.
866   * @param  CallbackID            User Callback identifier
867   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
868   * @retval HAL status
869   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)870 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
871 {
872   HAL_StatusTypeDef status = HAL_OK;
873 
874   /* Process locked */
875   __HAL_LOCK(hdma);
876 
877   if (HAL_DMA_STATE_READY == hdma->State)
878   {
879     switch (CallbackID)
880     {
881       case  HAL_DMA_XFER_CPLT_CB_ID:
882         hdma->XferCpltCallback = NULL;
883         break;
884 
885       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
886         hdma->XferHalfCpltCallback = NULL;
887         break;
888 
889       case  HAL_DMA_XFER_ERROR_CB_ID:
890         hdma->XferErrorCallback = NULL;
891         break;
892 
893       case  HAL_DMA_XFER_ABORT_CB_ID:
894         hdma->XferAbortCallback = NULL;
895         break;
896 
897       case   HAL_DMA_XFER_ALL_CB_ID:
898         hdma->XferCpltCallback = NULL;
899         hdma->XferHalfCpltCallback = NULL;
900         hdma->XferErrorCallback = NULL;
901         hdma->XferAbortCallback = NULL;
902         break;
903 
904       default:
905         status = HAL_ERROR;
906         break;
907     }
908   }
909   else
910   {
911     status = HAL_ERROR;
912   }
913 
914   /* Release Lock */
915   __HAL_UNLOCK(hdma);
916 
917   return status;
918 }
919 
920 /**
921   * @}
922   */
923 
924 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
925   *  @brief    Peripheral State and Errors functions
926   *
927 @verbatim
928  ===============================================================================
929             ##### Peripheral State and Errors functions #####
930  ===============================================================================
931     [..]
932     This subsection provides functions allowing to
933       (+) Check the DMA state
934       (+) Get error code
935 
936 @endverbatim
937   * @{
938   */
939 
940 /**
941   * @brief  Return the DMA handle state.
942   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
943   *               the configuration information for the specified DMA Channel.
944   * @retval HAL state
945   */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)946 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
947 {
948   /* Return DMA handle state */
949   return hdma->State;
950 }
951 
952 /**
953   * @brief  Return the DMA error code.
954   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
955   *              the configuration information for the specified DMA Channel.
956   * @retval DMA Error Code
957   */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)958 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
959 {
960   return hdma->ErrorCode;
961 }
962 
963 /**
964   * @}
965   */
966 
967 /**
968   * @}
969   */
970 
971 /** @addtogroup DMA_Private_Functions
972   * @{
973   */
974 
975 /**
976   * @brief  Sets the DMA Transfer parameter.
977   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
978   *                     the configuration information for the specified DMA Channel.
979   * @param SrcAddress The source memory Buffer address
980   * @param DstAddress The destination memory Buffer address
981   * @param DataLength The length of data to be transferred from source to destination
982   * @retval HAL status
983   */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)984 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
985 {
986   /* Clear the DMAMUX synchro overrun flag */
987   hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
988 
989   if (hdma->DMAmuxRequestGen != 0U)
990   {
991     /* Clear the DMAMUX request generator overrun flag */
992     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
993   }
994 
995   /* Clear all flags */
996   __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1cU)));
997 
998   /* Configure DMA Channel data length */
999   hdma->Instance->CNDTR = DataLength;
1000 
1001   /* Peripheral to Memory */
1002   if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1003   {
1004     /* Configure DMA Channel destination address */
1005     hdma->Instance->CPAR = DstAddress;
1006 
1007     /* Configure DMA Channel source address */
1008     hdma->Instance->CMAR = SrcAddress;
1009   }
1010   /* Memory to Peripheral */
1011   else
1012   {
1013     /* Configure DMA Channel source address */
1014     hdma->Instance->CPAR = SrcAddress;
1015 
1016     /* Configure DMA Channel destination address */
1017     hdma->Instance->CMAR = DstAddress;
1018   }
1019 }
1020 
1021 /**
1022   * @brief  Updates the DMA handle with the DMAMUX  channel and status mask depending on stream number
1023   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
1024   *                     the configuration information for the specified DMA Stream.
1025   * @retval None
1026   */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1027 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1028 {
1029   uint32_t channel_number;
1030 
1031   channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
1032   hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)(uint32_t)((uint32_t)DMAMUX1_Channel0 + \
1033                                                              ((hdma->ChannelIndex >> 2U) * \
1034                                                               ((uint32_t)DMAMUX1_Channel1 - \
1035                                                                (uint32_t)DMAMUX1_Channel0)));
1036   hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1037   hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1cU);
1038 }
1039 
1040 /**
1041   * @brief  Updates the DMA handle with the DMAMUX  request generator params
1042   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
1043   *                     the configuration information for the specified DMA Stream.
1044   * @retval None
1045   */
1046 
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1047 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1048 {
1049   uint32_t request =  hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1050 
1051   /* DMA Channels are connected to DMAMUX1 request generator blocks*/
1052   hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + \
1053                                                                     ((request - 1U) * 4U)));
1054 
1055   hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1056 
1057   /* here "Request" is either DMA_REQUEST_GENERATOR0 to 4, i.e. <= 4*/
1058   hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
1059 }
1060 
1061 /**
1062   * @}
1063   */
1064 
1065 /**
1066   * @}
1067   */
1068 
1069 #endif /* HAL_DMA_MODULE_ENABLED */
1070 /**
1071   * @}
1072   */
1073 
1074 /**
1075   * @}
1076   */
1077