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