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   @verbatim
12   ==============================================================================
13                         ##### How to use this driver #####
14   ==============================================================================
15   [..]
16    (#) Enable and configure the peripheral to be connected to the DMA Channel
17        (except for internal SRAM / FLASH memories: no initialization is
18        necessary). Please refer to the Reference manual for connection between peripherals
19        and DMA requests.
20 
21    (#) For a given Channel, program the required configuration through the following parameters:
22        Channel request, Transfer Direction, Source and Destination data formats,
23        Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
24        using HAL_DMA_Init() function.
25 
26        Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX
27        thanks to:
28       (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or  __HAL_RCC_DMA2_CLK_ENABLE() ;
29       (##) DMAMUX1:      __HAL_RCC_DMAMUX1_CLK_ENABLE();
30 
31    (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
32        detection.
33 
34    (#) Use HAL_DMA_Abort() function to abort the current transfer
35 
36      -@-   In Memory-to-Memory transfer mode, Circular mode is not allowed.
37 
38      *** Polling mode IO operation ***
39      =================================
40     [..]
41           (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
42               address and destination address and the Length of data to be transferred
43           (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
44               case a fixed Timeout can be configured by User depending from his application.
45 
46      *** Interrupt mode IO operation ***
47      ===================================
48     [..]
49           (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
50           (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
51           (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
52               Source address and destination address and the Length of data to be transferred.
53               In this case the DMA interrupt is configured
54           (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
55           (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
56               add his own function to register callbacks with HAL_DMA_RegisterCallback().
57 
58      *** DMA HAL driver macros list ***
59      =============================================
60       [..]
61        Below the list of macros in DMA HAL driver.
62 
63        (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
64        (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
65        (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
66        (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
67        (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
68        (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
69        (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not.
70 
71      [..]
72       (@) You can refer to the DMA HAL driver header file for more useful macros
73 
74   @endverbatim
75   ******************************************************************************
76   * @attention
77   *
78   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
79   * All rights reserved.</center></h2>
80   *
81   * This software component is licensed by ST under BSD 3-Clause license,
82   * the "License"; You may not use this file except in compliance with the
83   * License. You may obtain a copy of the License at:
84   *                        opensource.org/licenses/BSD-3-Clause
85   *
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
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
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, uint32_t DataLength)
433 {
434   HAL_StatusTypeDef status = HAL_OK;
435 
436   /* Check the parameters */
437   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
438 
439   /* Process locked */
440   __HAL_LOCK(hdma);
441 
442   if (HAL_DMA_STATE_READY == hdma->State)
443   {
444     /* Change DMA peripheral state */
445     hdma->State = HAL_DMA_STATE_BUSY;
446     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
447 
448     /* Disable the peripheral */
449     __HAL_DMA_DISABLE(hdma);
450 
451     /* Configure the source, destination address and the data length & clear flags*/
452     DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
453 
454     /* Enable the transfer complete interrupt */
455     /* Enable the transfer Error interrupt */
456     if (NULL != hdma->XferHalfCpltCallback)
457     {
458       /* Enable the Half transfer complete interrupt as well */
459       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
460     }
461     else
462     {
463       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
464       __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
465     }
466 
467     /* Check if DMAMUX Synchronization is enabled*/
468     if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
469     {
470       /* Enable DMAMUX sync overrun IT*/
471       hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
472     }
473 
474     if (hdma->DMAmuxRequestGen != 0U)
475     {
476       /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
477       /* enable the request gen overrun IT*/
478       hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
479     }
480 
481     /* Enable the Peripheral */
482     __HAL_DMA_ENABLE(hdma);
483   }
484   else
485   {
486     /* Process Unlocked */
487     __HAL_UNLOCK(hdma);
488 
489     /* Remain BUSY */
490     status = HAL_BUSY;
491   }
492   return status;
493 }
494 
495 /**
496   * @brief  Abort the DMA Transfer.
497   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
498   *               the configuration information for the specified DMA Channel.
499     * @retval HAL status
500   */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)501 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
502 {
503 
504   /* Check the DMA peripheral handle */
505   if (NULL == hdma)
506   {
507     return HAL_ERROR;
508   }
509 
510   /* Check the DMA peripheral state */
511   if(hdma->State != HAL_DMA_STATE_BUSY)
512   {
513     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
514 
515     /* Process Unlocked */
516     __HAL_UNLOCK(hdma);
517 
518     return HAL_ERROR;
519   }
520   else
521   {
522     /* Disable DMA IT */
523     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
524 
525     /* disable the DMAMUX sync overrun IT*/
526     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
527 
528     /* Disable the channel */
529     __HAL_DMA_DISABLE(hdma);
530 
531     /* Clear all flags */
532     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
533 
534     /* Clear the DMAMUX synchro overrun flag */
535     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
536 
537     if (hdma->DMAmuxRequestGen != 0U)
538     {
539       /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
540       /* disable the request gen overrun IT*/
541       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
542 
543       /* Clear the DMAMUX request generator overrun flag */
544       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
545     }
546 
547     /* Change the DMA state */
548     hdma->State = HAL_DMA_STATE_READY;
549 
550     /* Process Unlocked */
551     __HAL_UNLOCK(hdma);
552   }
553 
554   return HAL_OK;
555 }
556 
557 /**
558   * @brief  Aborts the DMA Transfer in Interrupt mode.
559   * @param  hdma  Pointer to a DMA_HandleTypeDef structure that contains
560   *                 the configuration information for the specified DMA Channel.
561   * @retval HAL status
562   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)563 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
564 {
565   HAL_StatusTypeDef status = HAL_OK;
566 
567   if (HAL_DMA_STATE_BUSY != hdma->State)
568   {
569     /* no transfer ongoing */
570     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
571 
572     status = HAL_ERROR;
573   }
574   else
575   {
576     /* Disable DMA IT */
577     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
578 
579     /* Disable the channel */
580     __HAL_DMA_DISABLE(hdma);
581 
582     /* disable the DMAMUX sync overrun IT*/
583     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
584 
585     /* Clear all flags */
586     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
587 
588     /* Clear the DMAMUX synchro overrun flag */
589     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
590 
591     if (hdma->DMAmuxRequestGen != 0U)
592     {
593       /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
594       /* disable the request gen overrun IT*/
595       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
596 
597       /* Clear the DMAMUX request generator overrun flag */
598       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
599     }
600 
601     /* Change the DMA state */
602     hdma->State = HAL_DMA_STATE_READY;
603 
604     /* Process Unlocked */
605     __HAL_UNLOCK(hdma);
606 
607     /* Call User Abort callback */
608     if (hdma->XferAbortCallback != NULL)
609     {
610       hdma->XferAbortCallback(hdma);
611     }
612   }
613   return status;
614 }
615 
616 /**
617   * @brief  Polling for transfer complete.
618   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
619   *                  the configuration information for the specified DMA Channel.
620   * @param CompleteLevel Specifies the DMA level complete.
621   * @param Timeout Timeout duration.
622   * @retval HAL status
623   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)624 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
625 {
626   uint32_t temp;
627   uint32_t tickstart;
628 
629   if (HAL_DMA_STATE_BUSY != hdma->State)
630   {
631     /* no transfer ongoing */
632     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
633     __HAL_UNLOCK(hdma);
634     return HAL_ERROR;
635   }
636 
637   /* Polling mode not supported in circular mode */
638   if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
639   {
640     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
641     return HAL_ERROR;
642   }
643 
644   /* Get the level transfer complete flag */
645   if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
646   {
647     /* Transfer Complete flag */
648     temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
649   }
650   else
651   {
652     /* Half Transfer Complete flag */
653     temp = DMA_FLAG_HT1 << (hdma->ChannelIndex  & 0x1cU);
654   }
655 
656   /* Get tick */
657   tickstart = HAL_GetTick();
658 
659   while((hdma->DmaBaseAddress->ISR & temp) == 0U)
660   {
661     if((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex& 0x1CU))) != 0U)
662     {
663       /* When a DMA transfer error occurs */
664       /* A hardware clear of its EN bits is performed */
665       /* Clear all flags */
666       hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
667 
668       /* Update error code */
669       hdma->ErrorCode = HAL_DMA_ERROR_TE;
670 
671       /* Change the DMA state */
672       hdma->State = HAL_DMA_STATE_READY;
673 
674       /* Process Unlocked */
675       __HAL_UNLOCK(hdma);
676 
677       return HAL_ERROR;
678     }
679     /* Check for the Timeout */
680     if (Timeout != HAL_MAX_DELAY)
681     {
682       if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
683       {
684         /* Update error code */
685         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
686 
687         /* Change the DMA state */
688         hdma->State = HAL_DMA_STATE_READY;
689 
690         /* Process Unlocked */
691         __HAL_UNLOCK(hdma);
692 
693         return HAL_ERROR;
694       }
695     }
696   }
697 
698   /*Check for DMAMUX Request generator (if used) overrun status */
699   if (hdma->DMAmuxRequestGen != 0U)
700   {
701     /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
702     if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
703     {
704       /* Disable the request gen overrun interrupt */
705       hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
706 
707       /* Clear the DMAMUX request generator overrun flag */
708       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
709 
710       /* Update error code */
711       hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
712     }
713   }
714 
715   /* Check for DMAMUX Synchronization overrun */
716   if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
717   {
718     /* Clear the DMAMUX synchro overrun flag */
719     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
720 
721     /* Update error code */
722     hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
723   }
724 
725   if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
726   {
727     /* Clear the transfer complete flag */
728     hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU));
729 
730     /* Process unlocked */
731     __HAL_UNLOCK(hdma);
732 
733     /* The selected Channelx EN bit is cleared (DMA is disabled and
734     all transfers are complete) */
735     hdma->State = HAL_DMA_STATE_READY;
736   }
737   else
738   {
739     /* Clear the half transfer complete flag */
740     hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU));
741   }
742 
743   return HAL_OK;
744 }
745 
746 /**
747   * @brief  Handle DMA interrupt request.
748   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
749   *               the configuration information for the specified DMA Channel.
750   * @retval None
751   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)752 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
753 {
754   uint32_t flag_it = hdma->DmaBaseAddress->ISR;
755   uint32_t source_it = hdma->Instance->CCR;
756 
757   /* Half Transfer Complete Interrupt management ******************************/
758   if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
759   {
760     /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
761     if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
762     {
763       /* Disable the half transfer interrupt */
764       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
765     }
766     /* Clear the half transfer complete flag */
767     hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU));
768 
769     /* DMA peripheral state is not updated in Half Transfer */
770     /* but in Transfer Complete case */
771 
772     if (hdma->XferHalfCpltCallback != NULL)
773     {
774       /* Half transfer callback */
775       hdma->XferHalfCpltCallback(hdma);
776     }
777   }
778 
779   /* Transfer Complete Interrupt management ***********************************/
780   else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
781   {
782     if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
783     {
784       /* Disable the transfer complete and error interrupt */
785       __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
786 
787       /* Change the DMA state */
788       hdma->State = HAL_DMA_STATE_READY;
789     }
790     /* Clear the transfer complete flag */
791     hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1cU));
792 
793     /* Process Unlocked */
794     __HAL_UNLOCK(hdma);
795 
796     if (hdma->XferCpltCallback != NULL)
797     {
798       /* Transfer complete callback */
799       hdma->XferCpltCallback(hdma);
800     }
801   }
802 
803   /* Transfer Error Interrupt management **************************************/
804   else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU)))!= 0U) && ((source_it & DMA_IT_TE) != 0U))
805   {
806     /* When a DMA transfer error occurs */
807     /* A hardware clear of its EN bits is performed */
808     /* Disable ALL DMA IT */
809     __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
810 
811     /* Clear all flags */
812     hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
813 
814     /* Update error code */
815     hdma->ErrorCode = HAL_DMA_ERROR_TE;
816 
817     /* Change the DMA state */
818     hdma->State = HAL_DMA_STATE_READY;
819 
820     /* Process Unlocked */
821     __HAL_UNLOCK(hdma);
822 
823     if (hdma->XferErrorCallback != NULL)
824     {
825       /* Transfer error callback */
826       hdma->XferErrorCallback(hdma);
827     }
828   }
829   else
830   {
831     /* Nothing To Do */
832   }
833   return;
834 }
835 
836 /**
837   * @brief  Register callbacks
838   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
839   *                               the configuration information for the specified DMA Channel.
840   * @param CallbackID User Callback identifer
841   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
842   * @param pCallback Pointer to private callbacsk function which has pointer to
843   *                               a DMA_HandleTypeDef structure as parameter.
844   * @retval HAL status
845   */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))846 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
847 {
848   HAL_StatusTypeDef status = HAL_OK;
849 
850   /* Process locked */
851   __HAL_LOCK(hdma);
852 
853   if (HAL_DMA_STATE_READY == hdma->State)
854   {
855     switch (CallbackID)
856     {
857       case  HAL_DMA_XFER_CPLT_CB_ID:
858         hdma->XferCpltCallback = pCallback;
859         break;
860 
861       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
862         hdma->XferHalfCpltCallback = pCallback;
863         break;
864 
865       case  HAL_DMA_XFER_ERROR_CB_ID:
866         hdma->XferErrorCallback = pCallback;
867         break;
868 
869       case  HAL_DMA_XFER_ABORT_CB_ID:
870         hdma->XferAbortCallback = pCallback;
871         break;
872 
873       default:
874         status = HAL_ERROR;
875         break;
876     }
877   }
878   else
879   {
880     status = HAL_ERROR;
881   }
882 
883   /* Release Lock */
884   __HAL_UNLOCK(hdma);
885 
886   return status;
887 }
888 
889 /**
890   * @brief  UnRegister callbacks
891   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
892   *                               the configuration information for the specified DMA Channel.
893   * @param CallbackID User Callback identifer
894   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
895   * @retval HAL status
896   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)897 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
898 {
899   HAL_StatusTypeDef status = HAL_OK;
900 
901   /* Process locked */
902   __HAL_LOCK(hdma);
903 
904   if (HAL_DMA_STATE_READY == hdma->State)
905   {
906     switch (CallbackID)
907     {
908       case  HAL_DMA_XFER_CPLT_CB_ID:
909         hdma->XferCpltCallback = NULL;
910         break;
911 
912       case  HAL_DMA_XFER_HALFCPLT_CB_ID:
913         hdma->XferHalfCpltCallback = NULL;
914         break;
915 
916       case  HAL_DMA_XFER_ERROR_CB_ID:
917         hdma->XferErrorCallback = NULL;
918         break;
919 
920       case  HAL_DMA_XFER_ABORT_CB_ID:
921         hdma->XferAbortCallback = NULL;
922         break;
923 
924       case   HAL_DMA_XFER_ALL_CB_ID:
925         hdma->XferCpltCallback = NULL;
926         hdma->XferHalfCpltCallback = NULL;
927         hdma->XferErrorCallback = NULL;
928         hdma->XferAbortCallback = NULL;
929         break;
930 
931       default:
932         status = HAL_ERROR;
933         break;
934     }
935   }
936   else
937   {
938     status = HAL_ERROR;
939   }
940 
941   /* Release Lock */
942   __HAL_UNLOCK(hdma);
943 
944   return status;
945 }
946 
947 /**
948   * @}
949   */
950 
951 
952 
953 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
954  *  @brief    Peripheral State and Errors functions
955  *
956 @verbatim
957  ===============================================================================
958             ##### Peripheral State and Errors functions #####
959  ===============================================================================
960     [..]
961     This subsection provides functions allowing to
962       (+) Check the DMA state
963       (+) Get error code
964 
965 @endverbatim
966   * @{
967   */
968 
969 /**
970   * @brief  Return the DMA handle state.
971   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
972   *               the configuration information for the specified DMA Channel.
973   * @retval HAL state
974   */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)975 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
976 {
977   /* Return DMA handle state */
978   return hdma->State;
979 }
980 
981 /**
982   * @brief  Return the DMA error code.
983   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
984   *              the configuration information for the specified DMA Channel.
985   * @retval DMA Error Code
986   */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)987 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
988 {
989   return hdma->ErrorCode;
990 }
991 
992 /**
993   * @}
994   */
995 
996 /**
997   * @}
998   */
999 
1000 /** @addtogroup DMA_Private_Functions
1001   * @{
1002   */
1003 
1004 /**
1005   * @brief  Sets the DMA Transfer parameter.
1006   * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1007   *                     the configuration information for the specified DMA Channel.
1008   * @param SrcAddress The source memory Buffer address
1009   * @param DstAddress The destination memory Buffer address
1010   * @param DataLength The length of data to be transferred from source to destination
1011   * @retval HAL status
1012   */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)1013 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
1014 {
1015   /* Clear the DMAMUX synchro overrun flag */
1016   hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
1017 
1018   if (hdma->DMAmuxRequestGen != 0U)
1019   {
1020     /* Clear the DMAMUX request generator overrun flag */
1021     hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
1022   }
1023 
1024   /* Clear all flags */
1025   hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
1026 
1027   /* Configure DMA Channel data length */
1028   hdma->Instance->CNDTR = DataLength;
1029 
1030   /* Memory to Peripheral */
1031   if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1032   {
1033     /* Configure DMA Channel destination address */
1034     hdma->Instance->CPAR = DstAddress;
1035 
1036     /* Configure DMA Channel source address */
1037     hdma->Instance->CMAR = SrcAddress;
1038   }
1039   /* Peripheral to Memory */
1040   else
1041   {
1042     /* Configure DMA Channel source address */
1043     hdma->Instance->CPAR = SrcAddress;
1044 
1045     /* Configure DMA Channel destination address */
1046     hdma->Instance->CMAR = DstAddress;
1047   }
1048 }
1049 
1050 /**
1051   * @brief  Updates the DMA handle with the DMAMUX  channel and status mask depending on channel number
1052   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
1053   *                     the configuration information for the specified DMA Channel.
1054   * @retval None
1055   */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1056 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1057 {
1058   uint32_t channel_number;
1059 
1060   /* check if instance is not outside the DMA channel range */
1061 #if defined(DMA2)
1062   if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1)
1063   {
1064     /* DMA1 */
1065     hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
1066   }
1067   else
1068   {
1069     /* DMA2 */
1070     hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U));
1071   }
1072 #else
1073   /* DMA1 */
1074   hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
1075 #endif
1076   channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
1077   hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1078 
1079   /* Initialize the field DMAmuxChannelStatusMask with the corresponding index of the DMAMUX channel selected for the current ChannelIndex */
1080   hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1FU);
1081 }
1082 
1083 /**
1084   * @brief  Updates the DMA handle with the DMAMUX  request generator params
1085   * @param  hdma Pointer to a DMA_HandleTypeDef structure that contains
1086   *                     the configuration information for the specified DMA Channel.
1087   * @retval None
1088   */
1089 
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1090 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1091 {
1092   uint32_t request =  hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1093 
1094   /* DMA Channels are connected to DMAMUX1 request generator blocks*/
1095   hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
1096 
1097   hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1098 
1099   /* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/
1100   hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
1101 }
1102 
1103 /**
1104   * @}
1105   */
1106 
1107 /**
1108   * @}
1109   */
1110 
1111 #endif /* HAL_DMA_MODULE_ENABLED */
1112 /**
1113   * @}
1114   */
1115 
1116 /**
1117   * @}
1118   */
1119 
1120 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1121