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