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