1 /**
2 ******************************************************************************
3 * @file stm32wbxx_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) 2019 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 peripheral clock shall be enabled for both DMA & DMAMUX
38 thanks to:
39 (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ;
40 (##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE();
41
42 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
43 detection.
44
45 (#) Use HAL_DMA_Abort() function to abort the current transfer
46
47 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
48
49 *** Polling mode IO operation ***
50 =================================
51 [..]
52 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
53 address and destination address and the Length of data to be transferred
54 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
55 case a fixed Timeout can be configured by User depending from his application.
56
57 *** Interrupt mode IO operation ***
58 ===================================
59 [..]
60 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
61 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
62 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
63 Source address and destination address and the Length of data to be transferred.
64 In this case the DMA interrupt is configured
65 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
66 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
67 add his own function to register callbacks with HAL_DMA_RegisterCallback().
68
69 *** DMA HAL driver macros list ***
70 =============================================
71 [..]
72 Below the list of 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 is enabled 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
89 /* Includes ------------------------------------------------------------------*/
90 #include "stm32wbxx_hal.h"
91
92 /** @addtogroup STM32WBxx_HAL_Driver
93 * @{
94 */
95
96 /** @defgroup DMA DMA
97 * @brief DMA HAL module driver
98 * @{
99 */
100
101 #ifdef HAL_DMA_MODULE_ENABLED
102
103 /* Private typedef -----------------------------------------------------------*/
104 /* Private define ------------------------------------------------------------*/
105 /* Private macro -------------------------------------------------------------*/
106 /* Private variables ---------------------------------------------------------*/
107 /* Private function prototypes -----------------------------------------------*/
108 /** @defgroup DMA_Private_Functions DMA Private Functions
109 * @{
110 */
111 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
112 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
113 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
114
115 /**
116 * @}
117 */
118
119 /* Exported functions ---------------------------------------------------------*/
120
121 /** @defgroup DMA_Exported_Functions DMA Exported Functions
122 * @{
123 */
124
125 /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
126 * @brief Initialization and de-initialization functions
127 *
128 @verbatim
129 ===============================================================================
130 ##### Initialization and de-initialization functions #####
131 ===============================================================================
132 [..]
133 This section provides functions allowing to initialize the DMA Channel source
134 and destination addresses, incrementation and data sizes, transfer direction,
135 circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
136 [..]
137 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
138 reference manual.
139
140 @endverbatim
141 * @{
142 */
143
144 /**
145 * @brief Initialize the DMA according to the specified
146 * parameters in the DMA_InitTypeDef and initialize the associated handle.
147 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
148 * the configuration information for the specified DMA Channel.
149 * @retval HAL status
150 */
HAL_DMA_Init(DMA_HandleTypeDef * hdma)151 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
152 {
153 uint32_t tmp;
154
155 /* Check the DMA handle allocation */
156 if (hdma == NULL)
157 {
158 return HAL_ERROR;
159 }
160
161 /* Check the parameters */
162 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
163 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
164 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
165 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
166 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
167 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
168 assert_param(IS_DMA_MODE(hdma->Init.Mode));
169 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
170
171 assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));
172
173 #if defined(DMA2)
174 /* Compute the channel index */
175 if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
176 {
177 /* DMA1 */
178 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
179 hdma->DmaBaseAddress = DMA1;
180 }
181 else
182 {
183 /* DMA2 */
184 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
185 hdma->DmaBaseAddress = DMA2;
186 }
187 #else
188 /* DMA1 */
189 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
190 hdma->DmaBaseAddress = DMA1;
191 #endif /* DMA2 */
192
193 /* Change DMA peripheral state */
194 hdma->State = HAL_DMA_STATE_BUSY;
195
196 /* Get the CR register value */
197 tmp = hdma->Instance->CCR;
198
199 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
200 tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE |
201 DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC |
202 DMA_CCR_DIR | DMA_CCR_MEM2MEM));
203
204 /* Prepare the DMA Channel configuration */
205 tmp |= hdma->Init.Direction |
206 hdma->Init.PeriphInc | hdma->Init.MemInc |
207 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
208 hdma->Init.Mode | hdma->Init.Priority;
209
210 /* Write to DMA Channel CR register */
211 hdma->Instance->CCR = tmp;
212
213 /* Initialize parameters for DMAMUX channel :
214 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
215 */
216 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
217
218 if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
219 {
220 /* if memory to memory force the request to 0*/
221 hdma->Init.Request = DMA_REQUEST_MEM2MEM;
222 }
223
224 /* Set peripheral request to DMAMUX channel */
225 hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
226
227 /* Clear the DMAMUX synchro overrun flag */
228 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
229
230 if (((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
231 {
232 /* Initialize parameters for DMAMUX request generator :
233 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
234 */
235 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
236
237 /* Reset the DMAMUX request generator register*/
238 hdma->DMAmuxRequestGen->RGCR = 0U;
239
240 /* Clear the DMAMUX request generator overrun flag */
241 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
242 }
243 else
244 {
245 hdma->DMAmuxRequestGen = 0U;
246 hdma->DMAmuxRequestGenStatus = 0U;
247 hdma->DMAmuxRequestGenStatusMask = 0U;
248 }
249
250 /* Initialize the error code */
251 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
252
253 /* Initialize the DMA state*/
254 hdma->State = HAL_DMA_STATE_READY;
255
256 /* Allocate lock resource and initialize it */
257 hdma->Lock = HAL_UNLOCKED;
258
259 return HAL_OK;
260 }
261
262 /**
263 * @brief DeInitialize the DMA peripheral.
264 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
265 * the configuration information for the specified DMA Channel.
266 * @retval HAL status
267 */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)268 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
269 {
270
271 /* Check the DMA handle allocation */
272 if (NULL == hdma)
273 {
274 return HAL_ERROR;
275 }
276
277 /* Check the parameters */
278 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
279
280 /* Disable the selected DMA Channelx */
281 __HAL_DMA_DISABLE(hdma);
282
283 #if defined(DMA2)
284 /* Compute the channel index */
285 if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
286 {
287 /* DMA1 */
288 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
289 hdma->DmaBaseAddress = DMA1;
290 }
291 else
292 {
293 /* DMA2 */
294 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
295 hdma->DmaBaseAddress = DMA2;
296 }
297 #else
298 /* DMA1 */
299 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
300 hdma->DmaBaseAddress = DMA1;
301 #endif /* DMA2 */
302
303 /* Reset DMA Channel control register */
304 hdma->Instance->CCR = 0U;
305
306 /* Clear all flags */
307 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
308
309 /* Initialize parameters for DMAMUX channel :
310 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
311
312 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
313
314 /* Reset the DMAMUX channel that corresponds to the DMA channel */
315 hdma->DMAmuxChannel->CCR = 0U;
316
317 /* Clear the DMAMUX synchro overrun flag */
318 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
319
320 /* Reset Request generator parameters if any */
321 if (((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
322 {
323 /* Initialize parameters for DMAMUX request generator :
324 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
325 */
326 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
327
328 /* Reset the DMAMUX request generator register*/
329 hdma->DMAmuxRequestGen->RGCR = 0U;
330
331 /* Clear the DMAMUX request generator overrun flag */
332 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
333 }
334
335 hdma->DMAmuxRequestGen = 0U;
336 hdma->DMAmuxRequestGenStatus = 0U;
337 hdma->DMAmuxRequestGenStatusMask = 0U;
338
339 /* Clean callbacks */
340 hdma->XferCpltCallback = NULL;
341 hdma->XferHalfCpltCallback = NULL;
342 hdma->XferErrorCallback = NULL;
343 hdma->XferAbortCallback = NULL;
344
345 /* Initialize the error code */
346 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
347
348 /* Initialize the DMA state */
349 hdma->State = HAL_DMA_STATE_RESET;
350
351 /* Release Lock */
352 __HAL_UNLOCK(hdma);
353
354 return HAL_OK;
355 }
356
357 /**
358 * @}
359 */
360
361 /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
362 * @brief Input and Output operation functions
363 *
364 @verbatim
365 ===============================================================================
366 ##### IO operation functions #####
367 ===============================================================================
368 [..] This section provides functions allowing to:
369 (+) Configure the source, destination address and data length and Start DMA transfer
370 (+) Configure the source, destination address and data length and
371 Start DMA transfer with interrupt
372 (+) Abort DMA transfer
373 (+) Poll for transfer complete
374 (+) Handle DMA interrupt request
375
376 @endverbatim
377 * @{
378 */
379
380 /**
381 * @brief Start the DMA Transfer.
382 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
383 * the configuration information for the specified DMA Channel.
384 * @param SrcAddress The source memory Buffer address
385 * @param DstAddress The destination memory Buffer address
386 * @param DataLength The length of data to be transferred from source to destination
387 * @retval HAL status
388 */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)389 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
390 {
391 HAL_StatusTypeDef status = HAL_OK;
392
393 /* Check the parameters */
394 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
395
396 /* Process locked */
397 __HAL_LOCK(hdma);
398
399 if (HAL_DMA_STATE_READY == hdma->State)
400 {
401 /* Change DMA peripheral state */
402 hdma->State = HAL_DMA_STATE_BUSY;
403 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
404
405 /* Disable the peripheral */
406 __HAL_DMA_DISABLE(hdma);
407
408 /* Configure the source, destination address and the data length & clear flags*/
409 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
410
411 /* Enable the Peripheral */
412 __HAL_DMA_ENABLE(hdma);
413 }
414 else
415 {
416 /* Process Unlocked */
417 __HAL_UNLOCK(hdma);
418 status = HAL_BUSY;
419 }
420 return status;
421 }
422
423 /**
424 * @brief Start the DMA Transfer with interrupt enabled.
425 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
426 * the configuration information for the specified DMA Channel.
427 * @param SrcAddress The source memory Buffer address
428 * @param DstAddress The destination memory Buffer address
429 * @param DataLength The length of data to be transferred from source to destination
430 * @retval HAL status
431 */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)432 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress,
433 uint32_t DataLength)
434 {
435 HAL_StatusTypeDef status = HAL_OK;
436
437 /* Check the parameters */
438 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
439
440 /* Process locked */
441 __HAL_LOCK(hdma);
442
443 if (HAL_DMA_STATE_READY == hdma->State)
444 {
445 /* Change DMA peripheral state */
446 hdma->State = HAL_DMA_STATE_BUSY;
447 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
448
449 /* Disable the peripheral */
450 __HAL_DMA_DISABLE(hdma);
451
452 /* Configure the source, destination address and the data length & clear flags*/
453 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
454
455 /* Enable the transfer complete interrupt */
456 /* Enable the transfer Error interrupt */
457 if (NULL != hdma->XferHalfCpltCallback)
458 {
459 /* Enable the Half transfer complete interrupt as well */
460 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
461 }
462 else
463 {
464 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
465 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
466 }
467
468 /* Check if DMAMUX Synchronization is enabled*/
469 if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
470 {
471 /* Enable DMAMUX sync overrun IT*/
472 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
473 }
474
475 if (hdma->DMAmuxRequestGen != 0U)
476 {
477 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
478 /* enable the request gen overrun IT*/
479 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
480 }
481
482 /* Enable the Peripheral */
483 __HAL_DMA_ENABLE(hdma);
484 }
485 else
486 {
487 /* Process Unlocked */
488 __HAL_UNLOCK(hdma);
489
490 /* Remain BUSY */
491 status = HAL_BUSY;
492 }
493 return status;
494 }
495
496 /**
497 * @brief Abort the DMA Transfer.
498 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
499 * the configuration information for the specified DMA Channel.
500 * @retval HAL status
501 */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)502 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
503 {
504
505 /* Check the DMA peripheral handle */
506 if (NULL == hdma)
507 {
508 return HAL_ERROR;
509 }
510
511 /* Check the DMA peripheral state */
512 if (hdma->State != HAL_DMA_STATE_BUSY)
513 {
514 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
515
516 /* Process Unlocked */
517 __HAL_UNLOCK(hdma);
518
519 return HAL_ERROR;
520 }
521 else
522 {
523 /* Disable DMA IT */
524 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
525
526 /* disable the DMAMUX sync overrun IT*/
527 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
528
529 /* Disable the channel */
530 __HAL_DMA_DISABLE(hdma);
531
532 /* Clear all flags */
533 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
534
535 /* Clear the DMAMUX synchro overrun flag */
536 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
537
538 if (hdma->DMAmuxRequestGen != 0U)
539 {
540 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
541 /* disable the request gen overrun IT*/
542 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
543
544 /* Clear the DMAMUX request generator overrun flag */
545 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
546 }
547
548 /* Change the DMA state */
549 hdma->State = HAL_DMA_STATE_READY;
550
551 /* Process Unlocked */
552 __HAL_UNLOCK(hdma);
553 }
554
555 return HAL_OK;
556 }
557
558 /**
559 * @brief Aborts the DMA Transfer in Interrupt mode.
560 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
561 * the configuration information for the specified DMA Channel.
562 * @retval HAL status
563 */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)564 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
565 {
566 HAL_StatusTypeDef status = HAL_OK;
567
568 if (HAL_DMA_STATE_BUSY != hdma->State)
569 {
570 /* no transfer ongoing */
571 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
572
573 status = HAL_ERROR;
574 }
575 else
576 {
577 /* Disable DMA IT */
578 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
579
580 /* Disable the channel */
581 __HAL_DMA_DISABLE(hdma);
582
583 /* disable the DMAMUX sync overrun IT*/
584 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
585
586 /* Clear all flags */
587 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
588
589 /* Clear the DMAMUX synchro overrun flag */
590 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
591
592 if (hdma->DMAmuxRequestGen != 0U)
593 {
594 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
595 /* disable the request gen overrun IT*/
596 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
597
598 /* Clear the DMAMUX request generator overrun flag */
599 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
600 }
601
602 /* Change the DMA state */
603 hdma->State = HAL_DMA_STATE_READY;
604
605 /* Process Unlocked */
606 __HAL_UNLOCK(hdma);
607
608 /* Call User Abort callback */
609 if (hdma->XferAbortCallback != NULL)
610 {
611 hdma->XferAbortCallback(hdma);
612 }
613 }
614 return status;
615 }
616
617 /**
618 * @brief Polling for transfer complete.
619 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
620 * the configuration information for the specified DMA Channel.
621 * @param CompleteLevel Specifies the DMA level complete.
622 * @param Timeout Timeout duration.
623 * @retval HAL status
624 */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)625 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel,
626 uint32_t Timeout)
627 {
628 uint32_t temp;
629 uint32_t tickstart;
630
631 if (HAL_DMA_STATE_BUSY != hdma->State)
632 {
633 /* no transfer ongoing */
634 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
635 __HAL_UNLOCK(hdma);
636 return HAL_ERROR;
637 }
638
639 /* Polling mode not supported in circular mode */
640 if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
641 {
642 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
643 return HAL_ERROR;
644 }
645
646 /* Get the level transfer complete flag */
647 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
648 {
649 /* Transfer Complete flag */
650 temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
651 }
652 else
653 {
654 /* Half Transfer Complete flag */
655 temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU);
656 }
657
658 /* Get tick */
659 tickstart = HAL_GetTick();
660
661 while ((hdma->DmaBaseAddress->ISR & temp) == 0U)
662 {
663 if ((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU))) != 0U)
664 {
665 /* When a DMA transfer error occurs */
666 /* A hardware clear of its EN bits is performed */
667 /* Clear all flags */
668 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
669
670 /* Update error code */
671 hdma->ErrorCode = HAL_DMA_ERROR_TE;
672
673 /* Change the DMA state */
674 hdma->State = HAL_DMA_STATE_READY;
675
676 /* Process Unlocked */
677 __HAL_UNLOCK(hdma);
678
679 return HAL_ERROR;
680 }
681 /* Check for the Timeout */
682 if (Timeout != HAL_MAX_DELAY)
683 {
684 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
685 {
686 /* Update error code */
687 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
688
689 /* Change the DMA state */
690 hdma->State = HAL_DMA_STATE_READY;
691
692 /* Process Unlocked */
693 __HAL_UNLOCK(hdma);
694
695 return HAL_ERROR;
696 }
697 }
698 }
699
700 /*Check for DMAMUX Request generator (if used) overrun status */
701 if (hdma->DMAmuxRequestGen != 0U)
702 {
703 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
704 if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
705 {
706 /* Disable the request gen overrun interrupt */
707 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
708
709 /* Clear the DMAMUX request generator overrun flag */
710 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
711
712 /* Update error code */
713 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
714 }
715 }
716
717 /* Check for DMAMUX Synchronization overrun */
718 if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
719 {
720 /* Clear the DMAMUX synchro overrun flag */
721 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
722
723 /* Update error code */
724 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
725 }
726
727 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
728 {
729 /* Clear the transfer complete flag */
730 hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU));
731
732 /* Process unlocked */
733 __HAL_UNLOCK(hdma);
734
735 /* The selected Channelx EN bit is cleared (DMA is disabled and
736 all transfers are complete) */
737 hdma->State = HAL_DMA_STATE_READY;
738 }
739 else
740 {
741 /* Clear the half transfer complete flag */
742 hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU));
743 }
744
745 return HAL_OK;
746 }
747
748 /**
749 * @brief Handle DMA interrupt request.
750 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
751 * the configuration information for the specified DMA Channel.
752 * @retval None
753 */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)754 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
755 {
756 uint32_t flag_it = hdma->DmaBaseAddress->ISR;
757 uint32_t source_it = hdma->Instance->CCR;
758
759 /* Half Transfer Complete Interrupt management ******************************/
760 if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
761 {
762 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
763 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
764 {
765 /* Disable the half transfer interrupt */
766 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
767 }
768 /* Clear the half transfer complete flag */
769 hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU));
770
771 /* DMA peripheral state is not updated in Half Transfer */
772 /* but in Transfer Complete case */
773
774 if (hdma->XferHalfCpltCallback != NULL)
775 {
776 /* Half transfer callback */
777 hdma->XferHalfCpltCallback(hdma);
778 }
779 }
780
781 /* Transfer Complete Interrupt management ***********************************/
782 else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
783 {
784 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
785 {
786 /* Disable the transfer complete and error interrupt */
787 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
788
789 /* Change the DMA state */
790 hdma->State = HAL_DMA_STATE_READY;
791 }
792 /* Clear the transfer complete flag */
793 hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1cU));
794
795 /* Process Unlocked */
796 __HAL_UNLOCK(hdma);
797
798 if (hdma->XferCpltCallback != NULL)
799 {
800 /* Transfer complete callback */
801 hdma->XferCpltCallback(hdma);
802 }
803 }
804
805 /* Transfer Error Interrupt management **************************************/
806 else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
807 {
808 /* When a DMA transfer error occurs */
809 /* A hardware clear of its EN bits is performed */
810 /* Disable ALL DMA IT */
811 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
812
813 /* Clear all flags */
814 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
815
816 /* Update error code */
817 hdma->ErrorCode = HAL_DMA_ERROR_TE;
818
819 /* Change the DMA state */
820 hdma->State = HAL_DMA_STATE_READY;
821
822 /* Process Unlocked */
823 __HAL_UNLOCK(hdma);
824
825 if (hdma->XferErrorCallback != NULL)
826 {
827 /* Transfer error callback */
828 hdma->XferErrorCallback(hdma);
829 }
830 }
831 else
832 {
833 /* Nothing To Do */
834 }
835 return;
836 }
837
838 /**
839 * @brief Register callbacks
840 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
841 * the configuration information for the specified DMA Channel.
842 * @param CallbackID User Callback identifier
843 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
844 * @param pCallback Pointer to private callback function which has pointer to
845 * a DMA_HandleTypeDef structure as parameter.
846 * @retval HAL status
847 */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))848 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
849 {
850 HAL_StatusTypeDef status = HAL_OK;
851
852 /* Process locked */
853 __HAL_LOCK(hdma);
854
855 if (HAL_DMA_STATE_READY == hdma->State)
856 {
857 switch (CallbackID)
858 {
859 case HAL_DMA_XFER_CPLT_CB_ID:
860 hdma->XferCpltCallback = pCallback;
861 break;
862
863 case HAL_DMA_XFER_HALFCPLT_CB_ID:
864 hdma->XferHalfCpltCallback = pCallback;
865 break;
866
867 case HAL_DMA_XFER_ERROR_CB_ID:
868 hdma->XferErrorCallback = pCallback;
869 break;
870
871 case HAL_DMA_XFER_ABORT_CB_ID:
872 hdma->XferAbortCallback = pCallback;
873 break;
874
875 default:
876 status = HAL_ERROR;
877 break;
878 }
879 }
880 else
881 {
882 status = HAL_ERROR;
883 }
884
885 /* Release Lock */
886 __HAL_UNLOCK(hdma);
887
888 return status;
889 }
890
891 /**
892 * @brief UnRegister callbacks
893 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
894 * the configuration information for the specified DMA Channel.
895 * @param CallbackID User Callback identifier
896 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
897 * @retval HAL status
898 */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)899 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
900 {
901 HAL_StatusTypeDef status = HAL_OK;
902
903 /* Process locked */
904 __HAL_LOCK(hdma);
905
906 if (HAL_DMA_STATE_READY == hdma->State)
907 {
908 switch (CallbackID)
909 {
910 case HAL_DMA_XFER_CPLT_CB_ID:
911 hdma->XferCpltCallback = NULL;
912 break;
913
914 case HAL_DMA_XFER_HALFCPLT_CB_ID:
915 hdma->XferHalfCpltCallback = NULL;
916 break;
917
918 case HAL_DMA_XFER_ERROR_CB_ID:
919 hdma->XferErrorCallback = NULL;
920 break;
921
922 case HAL_DMA_XFER_ABORT_CB_ID:
923 hdma->XferAbortCallback = NULL;
924 break;
925
926 case HAL_DMA_XFER_ALL_CB_ID:
927 hdma->XferCpltCallback = NULL;
928 hdma->XferHalfCpltCallback = NULL;
929 hdma->XferErrorCallback = NULL;
930 hdma->XferAbortCallback = NULL;
931 break;
932
933 default:
934 status = HAL_ERROR;
935 break;
936 }
937 }
938 else
939 {
940 status = HAL_ERROR;
941 }
942
943 /* Release Lock */
944 __HAL_UNLOCK(hdma);
945
946 return status;
947 }
948
949 /**
950 * @}
951 */
952
953
954
955 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
956 * @brief Peripheral State and Errors functions
957 *
958 @verbatim
959 ===============================================================================
960 ##### Peripheral State and Errors functions #####
961 ===============================================================================
962 [..]
963 This subsection provides functions allowing to
964 (+) Check the DMA state
965 (+) Get error code
966
967 @endverbatim
968 * @{
969 */
970
971 /**
972 * @brief Return the DMA handle state.
973 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
974 * the configuration information for the specified DMA Channel.
975 * @retval HAL state
976 */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)977 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
978 {
979 /* Return DMA handle state */
980 return hdma->State;
981 }
982
983 /**
984 * @brief Return the DMA error code.
985 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
986 * the configuration information for the specified DMA Channel.
987 * @retval DMA Error Code
988 */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)989 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
990 {
991 return hdma->ErrorCode;
992 }
993
994 /**
995 * @}
996 */
997
998 /**
999 * @}
1000 */
1001
1002 /** @addtogroup DMA_Private_Functions
1003 * @{
1004 */
1005
1006 /**
1007 * @brief Sets the DMA Transfer parameter.
1008 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1009 * the configuration information for the specified DMA Channel.
1010 * @param SrcAddress The source memory Buffer address
1011 * @param DstAddress The destination memory Buffer address
1012 * @param DataLength The length of data to be transferred from source to destination
1013 * @retval HAL status
1014 */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)1015 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
1016 {
1017 /* Clear the DMAMUX synchro overrun flag */
1018 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
1019
1020 if (hdma->DMAmuxRequestGen != 0U)
1021 {
1022 /* Clear the DMAMUX request generator overrun flag */
1023 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
1024 }
1025
1026 /* Clear all flags */
1027 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
1028
1029 /* Configure DMA Channel data length */
1030 hdma->Instance->CNDTR = DataLength;
1031
1032 /* Memory to Peripheral */
1033 if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1034 {
1035 /* Configure DMA Channel destination address */
1036 hdma->Instance->CPAR = DstAddress;
1037
1038 /* Configure DMA Channel source address */
1039 hdma->Instance->CMAR = SrcAddress;
1040 }
1041 /* Peripheral to Memory */
1042 else
1043 {
1044 /* Configure DMA Channel source address */
1045 hdma->Instance->CPAR = SrcAddress;
1046
1047 /* Configure DMA Channel destination address */
1048 hdma->Instance->CMAR = DstAddress;
1049 }
1050 }
1051
1052 /**
1053 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on channel number
1054 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1055 * the configuration information for the specified DMA Channel.
1056 * @retval None
1057 */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1058 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1059 {
1060 uint32_t channel_number;
1061
1062 /* check if instance is not outside the DMA channel range */
1063 #if defined(DMA2)
1064 if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1)
1065 {
1066 /* DMA1 */
1067 hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
1068 }
1069 else
1070 {
1071 /* DMA2 */
1072 hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U));
1073 }
1074 #else
1075 /* DMA1 */
1076 hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
1077 #endif /* DMA2 */
1078 channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
1079 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1080
1081 /* Initialize the field DMAmuxChannelStatusMask with the corresponding index of the DMAMUX channel selected for the current ChannelIndex */
1082 hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1FU);
1083 }
1084
1085 /**
1086 * @brief Updates the DMA handle with the DMAMUX request generator params
1087 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1088 * the configuration information for the specified DMA Channel.
1089 * @retval None
1090 */
1091
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1092 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1093 {
1094 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1095
1096 /* DMA Channels are connected to DMAMUX1 request generator blocks*/
1097 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
1098
1099 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1100
1101 /* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/
1102 hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
1103 }
1104
1105 /**
1106 * @}
1107 */
1108
1109 /**
1110 * @}
1111 */
1112
1113 #endif /* HAL_DMA_MODULE_ENABLED */
1114 /**
1115 * @}
1116 */
1117
1118 /**
1119 * @}
1120 */
1121