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