1 /**
2   ******************************************************************************
3   * @file    stm32wb0x_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) 2024 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 
48      *** Polling mode IO operation ***
49      =================================
50     [..]
51           (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
52               address and destination address and the Length of data to be transferred
53           (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
54               case a fixed Timeout can be configured by User depending from his application.
55 
56      *** Interrupt mode IO operation ***
57      ===================================
58     [..]
59           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
60           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
61           (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
62               Source address and destination address and the Length of data to be transferred.
63               In this case the DMA interrupt is configured
64           (+) Use HAL_DMA_IRQHandler() called under DMA_Handler() Interrupt subroutine
65           (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
66               add his own function by customization of function pointer XferCpltCallback and
67               XferErrorCallback (i.e. a member of DMA handle structure).
68 
69      *** DMA HAL driver macros list ***
70      =============================================
71       [..]
72        Below the list of most used macros in DMA HAL driver.
73 
74        (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
75        (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
76        (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
77        (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
78        (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
79        (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
80        (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not.
81 
82      [..]
83       (@) You can refer to the DMA HAL driver header file for more useful macros
84 
85   @endverbatim
86   ******************************************************************************
87 */
88 /* Includes ------------------------------------------------------------------*/
89 #include "stm32wb0x_hal.h"
90 
91 /** @addtogroup STM32WB0x_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 /** @defgroup DMA_Private_Functions DMA Private Functions
108   * @{
109   */
110 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
111 
112 /**
113   * @}
114   */
115 
116 /* Exported functions ---------------------------------------------------------*/
117 
118 /** @defgroup DMA_Exported_Functions DMA Exported Functions
119   * @{
120   */
121 
122 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
123  *  @brief   Initialization and de-initialization functions
124  *
125 @verbatim
126  ===============================================================================
127              ##### Initialization and de-initialization functions  #####
128  ===============================================================================
129     [..]
130     This section provides functions allowing to initialize the DMA Channel source
131     and destination addresses, incrementation and data sizes, transfer direction,
132     circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
133     [..]
134     The HAL_DMA_Init() function follows the DMA configuration procedures as described in
135     reference manual.
136 
137 @endverbatim
138   * @{
139   */
140 
141 /**
142   * @brief  Initialize the DMA according to the specified
143   *         parameters in the DMA_InitTypeDef and initialize the associated handle.
144   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
145   *             the configuration information for the specified DMA Channel.
146   * @retval HAL status
147   */
HAL_DMA_Init(DMA_HandleTypeDef * hdma)148 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
149 {
150   uint32_t tmp;
151 
152   /* Check the DMA handle allocation */
153   if (hdma == NULL)
154   {
155     return HAL_ERROR;
156   }
157 
158   /* Check the parameters */
159   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
160   assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
161   assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
162   assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
163   assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
164   assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
165   assert_param(IS_DMA_MODE(hdma->Init.Mode));
166   assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
167 
168   assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));
169 
170   /* DMA1 Channel Index */
171   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
172   hdma->DmaBaseAddress = DMA1;
173 
174   /* Change DMA peripheral state */
175   hdma->State = HAL_DMA_STATE_BUSY;
176 
177   /* Get the CR register value */
178   tmp = hdma->Instance->CCR;
179 
180   /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
181   tmp &= ((uint32_t)~(DMA_CCR_PL    | DMA_CCR_MSIZE  | DMA_CCR_PSIZE  |
182                       DMA_CCR_MINC  | DMA_CCR_PINC   | DMA_CCR_CIRC   |
183                       DMA_CCR_DIR   | DMA_CCR_MEM2MEM));
184 
185   /* Prepare the DMA Channel configuration */
186   tmp |=  hdma->Init.Direction        |
187           hdma->Init.PeriphInc           | hdma->Init.MemInc           |
188           hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
189           hdma->Init.Mode                | hdma->Init.Priority;
190 
191   /* Write to DMA Channel CR register */
192   hdma->Instance->CCR = tmp;
193 
194   /* Initialize DMAmuxChannel */
195   hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
196 
197   if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
198   {
199     /* if memory to memory force the request to 0*/
200     hdma->Init.Request = DMA_REQUEST_MEM2MEM;
201   }
202 
203   /* Set peripheral request  to DMAMUX channel */
204   hdma->DMAmuxChannel->CxCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
205 
206   /* Initialize the error code */
207   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
208 
209   /* Initialize the DMA state*/
210   hdma->State  = HAL_DMA_STATE_READY;
211 
212   /* Allocate lock resource and initialize it */
213   hdma->Lock = HAL_UNLOCKED;
214 
215   return HAL_OK;
216 }
217 
218 /**
219   * @brief  DeInitialize the DMA peripheral.
220   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
221   *               the configuration information for the specified DMA Channel.
222   * @retval HAL status
223   */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)224 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
225 {
226   /* Check the DMA handle allocation */
227   if (NULL == hdma)
228   {
229     return HAL_ERROR;
230   }
231 
232   /* Check the parameters */
233   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
234 
235   /* Disable the selected DMA Channelx */
236   __HAL_DMA_DISABLE(hdma);
237 
238   /* DMA1 Channel Index */
239   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
240   hdma->DmaBaseAddress = DMA1;
241 
242   /* Reset DMA Channel control register */
243   hdma->Instance->CCR  = 0U;
244 
245   /* Clear all flags */
246   hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x3cU));
247 
248   /* Initialize DMAmuxChannel */
249   hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
250 
251   /* Reset the DMAMUX channel that corresponds to the DMA channel */
252   hdma->DMAmuxChannel->CxCR = 0U;
253 
254   /* Clean callbacks */
255   hdma->XferCpltCallback = NULL;
256   hdma->XferHalfCpltCallback = NULL;
257   hdma->XferErrorCallback = NULL;
258   hdma->XferAbortCallback = NULL;
259 
260   /* Initialize the error code */
261   hdma->ErrorCode = HAL_DMA_ERROR_NONE;
262 
263   /* Initialize the DMA state */
264   hdma->State = HAL_DMA_STATE_RESET;
265 
266   /* Release Lock */
267   __HAL_UNLOCK(hdma);
268 
269   return HAL_OK;
270 }
271 
272 /**
273   * @}
274   */
275 
276 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
277  *  @brief   Input and Output operation functions
278  *
279 @verbatim
280  ===============================================================================
281                       #####  IO operation functions  #####
282  ===============================================================================
283     [..]  This section provides functions allowing to:
284       (+) Configure the source, destination address and data length and Start DMA transfer
285       (+) Configure the source, destination address and data length and
286           Start DMA transfer with interrupt
287       (+) Abort DMA transfer
288       (+) Poll for transfer complete
289       (+) Handle DMA interrupt request
290 
291 @endverbatim
292   * @{
293   */
294 
295 /**
296   * @brief  Start the DMA Transfer.
297   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
298   *             the configuration information for the specified DMA Channel.
299   * @param SrcAddress The source memory Buffer address
300   * @param DstAddress The destination memory Buffer address
301   * @param DataLength The length of data to be transferred from source to destination
302   * @retval HAL status
303   */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)304 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
305 {
306   HAL_StatusTypeDef status = HAL_OK;
307 
308   /* Check the parameters */
309   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
310 
311   /* Process locked */
312   __HAL_LOCK(hdma);
313 
314   if (HAL_DMA_STATE_READY == hdma->State)
315   {
316     /* Change DMA peripheral state */
317     hdma->State = HAL_DMA_STATE_BUSY;
318     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
319 
320     /* Disable the peripheral */
321     __HAL_DMA_DISABLE(hdma);
322 
323     /* Configure the source, destination address and the data length & clear flags*/
324     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
325 
326     /* Enable the Peripheral */
327     __HAL_DMA_ENABLE(hdma);
328   }
329   else
330   {
331     /* Process Unlocked */
332     __HAL_UNLOCK(hdma);
333     status = HAL_BUSY;
334   }
335   return status;
336 }
337 
338 /**
339   * @brief  Start the DMA Transfer with interrupt enabled.
340   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
341   *             the configuration information for the specified DMA Channel.
342   * @param SrcAddress The source memory Buffer address
343   * @param DstAddress The destination memory Buffer address
344   * @param DataLength The length of data to be transferred from source to destination
345   * @retval HAL status
346   */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)347 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
348 {
349   HAL_StatusTypeDef status = HAL_OK;
350 
351   /* Check the parameters */
352   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
353 
354   /* Process locked */
355   __HAL_LOCK(hdma);
356 
357   if (HAL_DMA_STATE_READY == hdma->State)
358   {
359     /* Change DMA peripheral state */
360     hdma->State = HAL_DMA_STATE_BUSY;
361     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
362 
363     /* Disable the peripheral */
364     __HAL_DMA_DISABLE(hdma);
365 
366     /* Configure the source, destination address and the data length & clear flags*/
367     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
368 
369     /* Enable the transfer complete interrupt */
370     /* Enable the transfer Error interrupt */
371     if (NULL != hdma->XferHalfCpltCallback)
372     {
373       /* Enable the Half transfer complete interrupt as well */
374       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
375     }
376     else
377     {
378       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
379       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
380     }
381 
382     /* Enable the Peripheral */
383     __HAL_DMA_ENABLE(hdma);
384   }
385   else
386   {
387     /* Process Unlocked */
388     __HAL_UNLOCK(hdma);
389 
390     /* Remain BUSY */
391     status = HAL_BUSY;
392   }
393   return status;
394 }
395 
396 /**
397   * @brief  Abort the DMA Transfer.
398   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
399   *             the configuration information for the specified DMA Channel.
400     * @retval HAL status
401   */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)402 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
403 {
404 
405   /* Check the DMA peripheral handle */
406   if (NULL == hdma)
407   {
408     return HAL_ERROR;
409   }
410 
411   /* Check the DMA peripheral state */
412   if(hdma->State != HAL_DMA_STATE_BUSY)
413   {
414     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
415 
416     /* Process Unlocked */
417     __HAL_UNLOCK(hdma);
418 
419     return HAL_ERROR;
420   }
421   else
422   {
423     /* Disable DMA IT */
424     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
425 
426     /* Disable the channel */
427     __HAL_DMA_DISABLE(hdma);
428 
429     /* Clear all flags */
430     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x3cU));
431 
432     /* Change the DMA state */
433     hdma->State = HAL_DMA_STATE_READY;
434 
435     /* Process Unlocked */
436     __HAL_UNLOCK(hdma);
437   }
438 
439   return HAL_OK;
440 }
441 
442 /**
443   * @brief  Aborts the DMA Transfer in Interrupt mode.
444   * @param  hdma  Pointer to a DMA_HandleTypeDef structure that contains
445   *               the configuration information for the specified DMA Channel.
446   * @retval HAL status
447   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)448 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
449 {
450   HAL_StatusTypeDef status = HAL_OK;
451 
452   if (HAL_DMA_STATE_BUSY != hdma->State)
453   {
454     /* no transfer ongoing */
455     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
456 
457     status = HAL_ERROR;
458   }
459   else
460   {
461     /* Disable DMA IT */
462     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
463 
464     /* Disable the channel */
465     __HAL_DMA_DISABLE(hdma);
466 
467     /* Clear all flags */
468     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x3cU));
469 
470     /* Change the DMA state */
471     hdma->State = HAL_DMA_STATE_READY;
472 
473     /* Process Unlocked */
474     __HAL_UNLOCK(hdma);
475 
476     /* Call User Abort callback */
477     if (hdma->XferAbortCallback != NULL)
478     {
479       hdma->XferAbortCallback(hdma);
480     }
481   }
482   return status;
483 }
484 
485 /**
486   * @brief  Polling for transfer complete.
487   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
488   *             the configuration information for the specified DMA Channel.
489   * @param CompleteLevel Specifies the DMA level complete.
490   * @param Timeout Timeout duration.
491   * @retval HAL status
492   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)493 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
494 {
495   uint32_t temp;
496   uint32_t tickstart;
497 
498   if (HAL_DMA_STATE_BUSY != hdma->State)
499   {
500     /* no transfer ongoing */
501     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
502     __HAL_UNLOCK(hdma);
503     return HAL_ERROR;
504   }
505 
506   /* Polling mode not supported in circular mode */
507   if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
508   {
509     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
510     return HAL_ERROR;
511   }
512 
513   /* Get the level transfer complete flag */
514   if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
515   {
516     /* Transfer Complete flag */
517     temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x3cU);
518   }
519   else
520   {
521     /* Half Transfer Complete flag */
522     temp = DMA_FLAG_HT1 << (hdma->ChannelIndex  & 0x3cU);
523   }
524 
525   /* Get tick */
526   tickstart = HAL_GetTick();
527 
528   while ((hdma->DmaBaseAddress->ISR & temp) == 0U)
529   {
530     if (((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x3cU)))) != 0U)
531     {
532       /* When a DMA transfer error occurs */
533       /* A hardware clear of its EN bits is performed */
534       /* Clear all flags */
535       hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x3cU));
536 
537       /* Update error code */
538       hdma->ErrorCode = HAL_DMA_ERROR_TE;
539 
540       /* Change the DMA state */
541       hdma->State = HAL_DMA_STATE_READY;
542 
543       /* Process Unlocked */
544       __HAL_UNLOCK(hdma);
545 
546       return HAL_ERROR;
547     }
548     /* Check for the Timeout */
549     if (Timeout != HAL_MAX_DELAY)
550     {
551       if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
552       {
553         /* Update error code */
554         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
555 
556         /* Change the DMA state */
557         hdma->State = HAL_DMA_STATE_READY;
558 
559         /* Process Unlocked */
560         __HAL_UNLOCK(hdma);
561 
562         return HAL_ERROR;
563       }
564     }
565   }
566 
567   if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
568   {
569     /* Clear the transfer complete flag */
570     hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x3cU));
571 
572     /* The selected Channelx EN bit is cleared (DMA is disabled and
573     all transfers are complete) */
574     hdma->State = HAL_DMA_STATE_READY;
575   }
576   else
577   {
578     /* Clear the half transfer complete flag */
579     hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x3cU));
580   }
581 
582   /* Process unlocked */
583   __HAL_UNLOCK(hdma);
584 
585   return HAL_OK;
586 }
587 
588 /**
589   * @brief  Handle DMA interrupt request.
590   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
591   *             the configuration information for the specified DMA Channel.
592   * @retval None
593   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)594 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
595 {
596   uint32_t flag_it = hdma->DmaBaseAddress->ISR;
597   uint32_t source_it = hdma->Instance->CCR;
598 
599   /* Half Transfer Complete Interrupt management ******************************/
600   if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x3cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
601   {
602     /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
603     if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
604     {
605       /* Disable the half transfer interrupt */
606       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
607     }
608     /* Clear the half transfer complete flag */
609     hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x3cU));
610 
611     /* DMA peripheral state is not updated in Half Transfer */
612     /* but in Transfer Complete case */
613 
614     if (hdma->XferHalfCpltCallback != NULL)
615     {
616       /* Half transfer callback */
617       hdma->XferHalfCpltCallback(hdma);
618     }
619   }
620 
621   /* Transfer Complete Interrupt management ***********************************/
622   else if ((0U != (flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x3cU)))) && (0U != (source_it & DMA_IT_TC)))
623   {
624     if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
625     {
626       /* Disable the transfer complete and error interrupt */
627       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
628 
629       /* Change the DMA state */
630       hdma->State = HAL_DMA_STATE_READY;
631     }
632     /* Clear the transfer complete flag */
633     hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x3cU));
634 
635     /* Process Unlocked */
636     __HAL_UNLOCK(hdma);
637 
638     if (hdma->XferCpltCallback != NULL)
639     {
640       /* Transfer complete callback */
641       hdma->XferCpltCallback(hdma);
642     }
643   }
644 
645   /* Transfer Error Interrupt management **************************************/
646   else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x3cU)))!= 0U) && ((source_it & DMA_IT_TE) != 0U))
647   {
648     /* When a DMA transfer error occurs */
649     /* A hardware clear of its EN bits is performed */
650     /* Disable ALL DMA IT */
651     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
652 
653     /* Clear all flags */
654     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x3cU));
655 
656     /* Update error code */
657     hdma->ErrorCode = HAL_DMA_ERROR_TE;
658 
659     /* Change the DMA state */
660     hdma->State = HAL_DMA_STATE_READY;
661 
662     /* Process Unlocked */
663     __HAL_UNLOCK(hdma);
664 
665     if (hdma->XferErrorCallback != NULL)
666     {
667       /* Transfer error callback */
668       hdma->XferErrorCallback(hdma);
669     }
670   }
671   else
672   {
673     /* Nothing To Do */
674   }
675   return;
676 }
677 
678 /**
679   * @brief  Register callbacks
680   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
681   *             the configuration information for the specified DMA Channel.
682   * @param CallbackID User Callback identifier
683   *                   a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
684   * @param pCallback Pointer to private callback function which has pointer to
685   *                  a DMA_HandleTypeDef structure as parameter.
686   * @retval HAL status
687   */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))688 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
689 {
690   HAL_StatusTypeDef status = HAL_OK;
691 
692   /* Process locked */
693   __HAL_LOCK(hdma);
694 
695   if (HAL_DMA_STATE_READY == hdma->State)
696   {
697     switch (CallbackID)
698     {
699       case  HAL_DMA_XFER_CPLT_CB_ID:
700         hdma->XferCpltCallback = pCallback;
701         break;
702 
703       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
704         hdma->XferHalfCpltCallback = pCallback;
705         break;
706 
707       case  HAL_DMA_XFER_ERROR_CB_ID:
708         hdma->XferErrorCallback = pCallback;
709         break;
710 
711       case  HAL_DMA_XFER_ABORT_CB_ID:
712         hdma->XferAbortCallback = pCallback;
713         break;
714 
715       default:
716         status = HAL_ERROR;
717         break;
718     }
719   }
720   else
721   {
722     status = HAL_ERROR;
723   }
724 
725   /* Release Lock */
726   __HAL_UNLOCK(hdma);
727 
728   return status;
729 }
730 
731 /**
732   * @brief  UnRegister callbacks
733   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
734   *             the configuration information for the specified DMA Channel.
735   * @param CallbackID User Callback identifier
736   *                   a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
737   * @retval HAL status
738   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)739 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
740 {
741   HAL_StatusTypeDef status = HAL_OK;
742 
743   /* Process locked */
744   __HAL_LOCK(hdma);
745 
746   if (HAL_DMA_STATE_READY == hdma->State)
747   {
748     switch (CallbackID)
749     {
750       case  HAL_DMA_XFER_CPLT_CB_ID:
751         hdma->XferCpltCallback = NULL;
752         break;
753 
754       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
755         hdma->XferHalfCpltCallback = NULL;
756         break;
757 
758       case  HAL_DMA_XFER_ERROR_CB_ID:
759         hdma->XferErrorCallback = NULL;
760         break;
761 
762       case  HAL_DMA_XFER_ABORT_CB_ID:
763         hdma->XferAbortCallback = NULL;
764         break;
765 
766       case  HAL_DMA_XFER_ALL_CB_ID:
767         hdma->XferCpltCallback = NULL;
768         hdma->XferHalfCpltCallback = NULL;
769         hdma->XferErrorCallback = NULL;
770         hdma->XferAbortCallback = NULL;
771         break;
772 
773       default:
774         status = HAL_ERROR;
775         break;
776     }
777   }
778   else
779   {
780     status = HAL_ERROR;
781   }
782 
783   /* Release Lock */
784   __HAL_UNLOCK(hdma);
785 
786   return status;
787 }
788 
789 /**
790   * @}
791   */
792 
793 
794 
795 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
796  *  @brief    Peripheral State and Errors functions
797  *
798 @verbatim
799  ===============================================================================
800             ##### Peripheral State and Errors functions #####
801  ===============================================================================
802     [..]
803     This subsection provides functions allowing to
804       (+) Check the DMA state
805       (+) Get error code
806 
807 @endverbatim
808   * @{
809   */
810 
811 /**
812   * @brief  Return the DMA handle state.
813   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
814   *             the configuration information for the specified DMA Channel.
815   * @retval HAL state
816   */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)817 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
818 {
819   /* Return DMA handle state */
820   return hdma->State;
821 }
822 
823 /**
824   * @brief  Return the DMA error code.
825   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
826   *              the configuration information for the specified DMA Channel.
827   * @retval DMA Error Code
828   */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)829 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
830 {
831   return hdma->ErrorCode;
832 }
833 
834 /**
835   * @}
836   */
837 
838 /**
839   * @}
840   */
841 
842 /** @addtogroup DMA_Private_Functions
843   * @{
844   */
845 
846 /**
847   * @brief  Sets the DMA Transfer parameter.
848   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
849   *             the configuration information for the specified DMA Channel.
850   * @param SrcAddress The source memory Buffer address
851   * @param DstAddress The destination memory Buffer address
852   * @param DataLength The length of data to be transferred from source to destination
853   * @retval HAL status
854   */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)855 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
856 {
857   /* Clear all flags */
858   hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x3cU));
859 
860   /* Configure DMA Channel data length */
861   hdma->Instance->CNDTR = DataLength;
862 
863   /* Peripheral to Memory */
864   if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
865   {
866     /* Configure DMA Channel destination address */
867     hdma->Instance->CPAR = DstAddress;
868 
869     /* Configure DMA Channel source address */
870     hdma->Instance->CMAR = SrcAddress;
871   }
872   /* Memory to Peripheral */
873   else
874   {
875     /* Configure DMA Channel source address */
876     hdma->Instance->CPAR = SrcAddress;
877 
878     /* Configure DMA Channel destination address */
879     hdma->Instance->CMAR = DstAddress;
880   }
881 }
882 
883 /**
884   * @}
885   */
886 
887 /**
888   * @}
889   */
890 
891 #endif /* HAL_DMA_MODULE_ENABLED */
892 /**
893   * @}
894   */
895 
896 /**
897   * @}
898   */
899