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