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