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