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