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>© 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