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