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