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