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   if(hdma->State != HAL_DMA_STATE_BUSY)
386   {
387     /* no transfer ongoing */
388     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
389 
390     /* Process Unlocked */
391     __HAL_UNLOCK(hdma);
392 
393     return HAL_ERROR;
394   }
395   else
396   {
397     /* Disable DMA IT */
398      hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_HT | DMA_IT_TE);
399 
400     /* Disable the channel */
401     hdma->Instance->CCR &= ~DMA_CCR_EN;
402 
403     /* Clear all flags */
404     hdma->DmaBaseAddress->IFCR = (DMA_FLAG_GL1 << hdma->ChannelIndex);
405   }
406   /* Change the DMA state*/
407   hdma->State = HAL_DMA_STATE_READY;
408 
409   /* Process Unlocked */
410   __HAL_UNLOCK(hdma);
411 
412   return HAL_OK;
413 }
414 
415 /**
416   * @brief  Abort the DMA Transfer in Interrupt mode.
417   * @param  hdma  : pointer to a DMA_HandleTypeDef structure that contains
418   *                 the configuration information for the specified DMA Stream.
419   * @retval HAL status
420   */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)421 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
422 {
423   HAL_StatusTypeDef status = HAL_OK;
424 
425   if(HAL_DMA_STATE_BUSY != hdma->State)
426   {
427     /* no transfer ongoing */
428     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
429 
430     status = HAL_ERROR;
431   }
432   else
433   {
434 
435     /* Disable DMA IT */
436     hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_HT | DMA_IT_TE);
437 
438     /* Disable the channel */
439     hdma->Instance->CCR &= ~DMA_CCR_EN;
440 
441     /* Clear all flags */
442     hdma->DmaBaseAddress->IFCR = DMA_FLAG_GL1 << hdma->ChannelIndex;
443 
444     /* Change the DMA state */
445     hdma->State = HAL_DMA_STATE_READY;
446 
447     /* Process Unlocked */
448     __HAL_UNLOCK(hdma);
449 
450     /* Call User Abort callback */
451     if(hdma->XferAbortCallback != NULL)
452     {
453       hdma->XferAbortCallback(hdma);
454     }
455   }
456   return status;
457 }
458 
459 /**
460   * @brief  Polling for transfer complete.
461   * @param  hdma    pointer to a DMA_HandleTypeDef structure that contains
462   *                  the configuration information for the specified DMA Channel.
463   * @param  CompleteLevel Specifies the DMA level complete.
464   * @param  Timeout       Timeout duration.
465   * @retval HAL status
466   */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,uint32_t CompleteLevel,uint32_t Timeout)467 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
468 {
469   uint32_t temp;
470   uint32_t tickstart = 0U;
471 
472   if(HAL_DMA_STATE_BUSY != hdma->State)
473   {
474     /* no transfer ongoing */
475     hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
476     __HAL_UNLOCK(hdma);
477     return HAL_ERROR;
478   }
479 
480   /* Polling mode not supported in circular mode */
481   if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC))
482   {
483     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
484     return HAL_ERROR;
485   }
486 
487   /* Get the level transfer complete flag */
488   if(HAL_DMA_FULL_TRANSFER == CompleteLevel)
489   {
490     /* Transfer Complete flag */
491     temp = DMA_FLAG_TC1 << hdma->ChannelIndex;
492   }
493   else
494   {
495     /* Half Transfer Complete flag */
496     temp = DMA_FLAG_HT1 << hdma->ChannelIndex;
497   }
498 
499   /* Get tick */
500   tickstart = HAL_GetTick();
501 
502   while(RESET == (hdma->DmaBaseAddress->ISR & temp))
503   {
504     if(RESET != (hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << hdma->ChannelIndex)))
505     {
506       /* When a DMA transfer error occurs */
507       /* A hardware clear of its EN bits is performed */
508       /* Clear all flags */
509       hdma->DmaBaseAddress->IFCR = DMA_FLAG_GL1 << hdma->ChannelIndex;
510 
511       /* Update error code */
512       hdma->ErrorCode = HAL_DMA_ERROR_TE;
513 
514       /* Change the DMA state */
515       hdma->State= HAL_DMA_STATE_READY;
516 
517       /* Process Unlocked */
518       __HAL_UNLOCK(hdma);
519 
520       return HAL_ERROR;
521     }
522     /* Check for the Timeout */
523     if(Timeout != HAL_MAX_DELAY)
524     {
525       if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
526       {
527         /* Update error code */
528         hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
529 
530         /* Change the DMA state */
531         hdma->State = HAL_DMA_STATE_READY;
532 
533         /* Process Unlocked */
534         __HAL_UNLOCK(hdma);
535 
536         return HAL_ERROR;
537       }
538     }
539   }
540 
541   if(HAL_DMA_FULL_TRANSFER == CompleteLevel)
542   {
543     /* Clear the transfer complete flag */
544     hdma->DmaBaseAddress->IFCR = DMA_FLAG_TC1 << hdma->ChannelIndex;
545 
546     /* The selected Channelx EN bit is cleared (DMA is disabled and
547     all transfers are complete) */
548     hdma->State = HAL_DMA_STATE_READY;
549   }
550   else
551   {
552     /* Clear the half transfer complete flag */
553     hdma->DmaBaseAddress->IFCR = DMA_FLAG_HT1 << hdma->ChannelIndex;
554   }
555 
556   /* Process unlocked */
557   __HAL_UNLOCK(hdma);
558 
559   return HAL_OK;
560 }
561 
562 /**
563   * @brief  Handle DMA interrupt request.
564   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
565   *               the configuration information for the specified DMA Channel.
566   * @retval None
567   */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)568 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
569 {
570 	uint32_t flag_it = hdma->DmaBaseAddress->ISR;
571   uint32_t source_it = hdma->Instance->CCR;
572 
573   /* Half Transfer Complete Interrupt management ******************************/
574   if ((RESET != (flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_HT)))
575   {
576   	/* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
577   	if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
578   	{
579   		/* Disable the half transfer interrupt */
580   		hdma->Instance->CCR &= ~DMA_IT_HT;
581   	}
582 
583   	/* Clear the half transfer complete flag */
584   	hdma->DmaBaseAddress->IFCR = DMA_FLAG_HT1 << hdma->ChannelIndex;
585 
586   	/* DMA peripheral state is not updated in Half Transfer */
587   	/* State is updated only in Transfer Complete case */
588 
589   	if(hdma->XferHalfCpltCallback != NULL)
590   	{
591   		/* Half transfer callback */
592   		hdma->XferHalfCpltCallback(hdma);
593   	}
594   }
595 
596   /* Transfer Complete Interrupt management ***********************************/
597   else if ((RESET != (flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TC)))
598   {
599   	if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
600   	{
601   		/* Disable the transfer complete  & transfer error interrupts */
602   		/* if the DMA mode is not CIRCULAR */
603   		hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_TE);
604 
605   		/* Change the DMA state */
606   		hdma->State = HAL_DMA_STATE_READY;
607   	}
608 
609   	/* Clear the transfer complete flag */
610   	hdma->DmaBaseAddress->IFCR = DMA_FLAG_TC1 << hdma->ChannelIndex;
611 
612   	/* Process Unlocked */
613   	__HAL_UNLOCK(hdma);
614 
615   	if(hdma->XferCpltCallback != NULL)
616   	{
617   		/* Transfer complete callback */
618   		hdma->XferCpltCallback(hdma);
619   	}
620   }
621 
622   /* Transfer Error Interrupt management ***************************************/
623   else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE)))
624   {
625   	/* When a DMA transfer error occurs */
626     /* A hardware clear of its EN bits is performed */
627     /* Then, disable all DMA interrupts */
628     hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_HT | DMA_IT_TE);
629 
630     /* Clear all flags */
631     hdma->DmaBaseAddress->IFCR = DMA_FLAG_GL1 << hdma->ChannelIndex;
632 
633     /* Update error code */
634     hdma->ErrorCode = HAL_DMA_ERROR_TE;
635 
636     /* Change the DMA state */
637     hdma->State = HAL_DMA_STATE_READY;
638 
639     /* Process Unlocked */
640     __HAL_UNLOCK(hdma);
641 
642     if(hdma->XferErrorCallback != NULL)
643     {
644     	/* Transfer error callback */
645     	hdma->XferErrorCallback(hdma);
646     }
647   }
648 }
649 
650 /**
651   * @brief  Register callbacks
652   * @param  hdma                 pointer to a DMA_HandleTypeDef structure that contains
653   *                               the configuration information for the specified DMA Stream.
654   * @param  CallbackID           User Callback identifier
655   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
656   * @param  pCallback            pointer to private callback function which has pointer to
657   *                               a DMA_HandleTypeDef structure as parameter.
658   * @retval HAL status
659   */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))660 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma))
661 {
662   HAL_StatusTypeDef status = HAL_OK;
663 
664   /* Process locked */
665   __HAL_LOCK(hdma);
666 
667   if(HAL_DMA_STATE_READY == hdma->State)
668   {
669     switch (CallbackID)
670     {
671      case  HAL_DMA_XFER_CPLT_CB_ID:
672            hdma->XferCpltCallback = pCallback;
673            break;
674 
675      case  HAL_DMA_XFER_HALFCPLT_CB_ID:
676            hdma->XferHalfCpltCallback = pCallback;
677            break;
678 
679      case  HAL_DMA_XFER_ERROR_CB_ID:
680            hdma->XferErrorCallback = pCallback;
681            break;
682 
683      case  HAL_DMA_XFER_ABORT_CB_ID:
684            hdma->XferAbortCallback = pCallback;
685            break;
686 
687      default:
688            status = HAL_ERROR;
689            break;
690     }
691   }
692   else
693   {
694     status = HAL_ERROR;
695   }
696 
697   /* Release Lock */
698   __HAL_UNLOCK(hdma);
699 
700   return status;
701 }
702 
703 /**
704   * @brief  UnRegister callbacks
705   * @param  hdma                 pointer to a DMA_HandleTypeDef structure that contains
706   *                               the configuration information for the specified DMA Stream.
707   * @param  CallbackID           User Callback identifier
708   *                               a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
709   * @retval HAL status
710   */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)711 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
712 {
713   HAL_StatusTypeDef status = HAL_OK;
714 
715     /* Process locked */
716   __HAL_LOCK(hdma);
717 
718   if(HAL_DMA_STATE_READY == hdma->State)
719   {
720     switch (CallbackID)
721     {
722      case  HAL_DMA_XFER_CPLT_CB_ID:
723            hdma->XferCpltCallback = NULL;
724            break;
725 
726      case  HAL_DMA_XFER_HALFCPLT_CB_ID:
727            hdma->XferHalfCpltCallback = NULL;
728            break;
729 
730      case  HAL_DMA_XFER_ERROR_CB_ID:
731            hdma->XferErrorCallback = NULL;
732            break;
733 
734      case  HAL_DMA_XFER_ABORT_CB_ID:
735            hdma->XferAbortCallback = NULL;
736            break;
737 
738     case   HAL_DMA_XFER_ALL_CB_ID:
739            hdma->XferCpltCallback = NULL;
740            hdma->XferHalfCpltCallback = NULL;
741            hdma->XferErrorCallback = NULL;
742            hdma->XferAbortCallback = NULL;
743            break;
744 
745     default:
746            status = HAL_ERROR;
747            break;
748     }
749   }
750   else
751   {
752     status = HAL_ERROR;
753   }
754 
755   /* Release Lock */
756   __HAL_UNLOCK(hdma);
757 
758   return status;
759 }
760 
761 /**
762   * @}
763   */
764 
765 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State functions
766  *  @brief    Peripheral State functions
767  *
768 @verbatim
769  ===============================================================================
770                     ##### State and Errors functions #####
771  ===============================================================================
772     [..]
773     This subsection provides functions allowing to
774       (+) Check the DMA state
775       (+) Get error code
776 
777 @endverbatim
778   * @{
779   */
780 
781 /**
782   * @brief  Returns the DMA state.
783   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
784   *               the configuration information for the specified DMA Channel.
785   * @retval HAL state
786   */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)787 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
788 {
789   return hdma->State;
790 }
791 
792 /**
793   * @brief  Return the DMA error code
794   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
795   *              the configuration information for the specified DMA Channel.
796   * @retval DMA Error Code
797   */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)798 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
799 {
800   return hdma->ErrorCode;
801 }
802 
803 /**
804   * @}
805   */
806 
807 /**
808   * @}
809   */
810 
811 /** @addtogroup DMA_Private_Functions
812   * @{
813   */
814 
815 /**
816   * @brief  Set the DMA Transfer parameters.
817   * @param  hdma       pointer to a DMA_HandleTypeDef structure that contains
818   *                     the configuration information for the specified DMA Channel.
819   * @param  SrcAddress The source memory Buffer address
820   * @param  DstAddress The destination memory Buffer address
821   * @param  DataLength The length of data to be transferred from source to destination
822   * @retval HAL status
823   */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)824 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
825 {
826 	/* Clear all flags */
827   hdma->DmaBaseAddress->IFCR  = (DMA_FLAG_GL1 << hdma->ChannelIndex);
828 
829   /* Configure DMA Channel data length */
830   hdma->Instance->CNDTR = DataLength;
831 
832   /* Peripheral to Memory */
833   if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
834   {
835     /* Configure DMA Channel destination address */
836     hdma->Instance->CPAR = DstAddress;
837 
838     /* Configure DMA Channel source address */
839     hdma->Instance->CMAR = SrcAddress;
840   }
841   /* Memory to Peripheral */
842   else
843   {
844     /* Configure DMA Channel source address */
845     hdma->Instance->CPAR = SrcAddress;
846 
847     /* Configure DMA Channel destination address */
848     hdma->Instance->CMAR = DstAddress;
849   }
850 }
851 
852 /**
853   * @brief  Set the DMA base address and channel index depending on DMA instance
854   * @param  hdma       pointer to a DMA_HandleTypeDef structure that contains
855   *                     the configuration information for the specified DMA Stream.
856   * @retval None
857   */
DMA_CalcBaseAndBitshift(DMA_HandleTypeDef * hdma)858 static void DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
859 {
860 #if defined (DMA2)
861   /* calculation of the channel index */
862   if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
863   {
864     /* DMA1 */
865     hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
866     hdma->DmaBaseAddress = DMA1;
867   }
868   else
869   {
870     /* DMA2 */
871     hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
872     hdma->DmaBaseAddress = DMA2;
873   }
874 #else
875   /* calculation of the channel index */
876   /* DMA1 */
877   hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
878   hdma->DmaBaseAddress = DMA1;
879 #endif
880 }
881 
882 /**
883   * @}
884   */
885 
886 /**
887   * @}
888   */
889 #endif /* HAL_DMA_MODULE_ENABLED */
890 
891 /**
892   * @}
893   */
894 
895   /**
896   * @}
897   */
898 
899