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