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 @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 Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX
27 thanks to:
28 (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ;
29 (##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE();
30
31 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
32 detection.
33
34 (#) Use HAL_DMA_Abort() function to abort the current transfer
35
36 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
37
38 *** Polling mode IO operation ***
39 =================================
40 [..]
41 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
42 address and destination address and the Length of data to be transferred
43 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
44 case a fixed Timeout can be configured by User depending from his application.
45
46 *** Interrupt mode IO operation ***
47 ===================================
48 [..]
49 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
50 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
51 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
52 Source address and destination address and the Length of data to be transferred.
53 In this case the DMA interrupt is configured
54 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
55 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
56 add his own function to register callbacks with HAL_DMA_RegisterCallback().
57
58 *** DMA HAL driver macros list ***
59 =============================================
60 [..]
61 Below the list of macros in DMA HAL driver.
62
63 (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
64 (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
65 (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
66 (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
67 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
68 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
69 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not.
70
71 [..]
72 (@) You can refer to the DMA HAL driver header file for more useful macros
73
74 @endverbatim
75 ******************************************************************************
76 * @attention
77 *
78 * <h2><center>© Copyright (c) 2019 STMicroelectronics.
79 * All rights reserved.</center></h2>
80 *
81 * This software component is licensed by ST under BSD 3-Clause license,
82 * the "License"; You may not use this file except in compliance with the
83 * License. You may obtain a copy of the License at:
84 * opensource.org/licenses/BSD-3-Clause
85 *
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
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
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, uint32_t DataLength)
433 {
434 HAL_StatusTypeDef status = HAL_OK;
435
436 /* Check the parameters */
437 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
438
439 /* Process locked */
440 __HAL_LOCK(hdma);
441
442 if (HAL_DMA_STATE_READY == hdma->State)
443 {
444 /* Change DMA peripheral state */
445 hdma->State = HAL_DMA_STATE_BUSY;
446 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
447
448 /* Disable the peripheral */
449 __HAL_DMA_DISABLE(hdma);
450
451 /* Configure the source, destination address and the data length & clear flags*/
452 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
453
454 /* Enable the transfer complete interrupt */
455 /* Enable the transfer Error interrupt */
456 if (NULL != hdma->XferHalfCpltCallback)
457 {
458 /* Enable the Half transfer complete interrupt as well */
459 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
460 }
461 else
462 {
463 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
464 __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
465 }
466
467 /* Check if DMAMUX Synchronization is enabled*/
468 if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
469 {
470 /* Enable DMAMUX sync overrun IT*/
471 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
472 }
473
474 if (hdma->DMAmuxRequestGen != 0U)
475 {
476 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
477 /* enable the request gen overrun IT*/
478 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
479 }
480
481 /* Enable the Peripheral */
482 __HAL_DMA_ENABLE(hdma);
483 }
484 else
485 {
486 /* Process Unlocked */
487 __HAL_UNLOCK(hdma);
488
489 /* Remain BUSY */
490 status = HAL_BUSY;
491 }
492 return status;
493 }
494
495 /**
496 * @brief Abort the DMA Transfer.
497 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
498 * the configuration information for the specified DMA Channel.
499 * @retval HAL status
500 */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)501 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
502 {
503
504 /* Check the DMA peripheral handle */
505 if (NULL == hdma)
506 {
507 return HAL_ERROR;
508 }
509
510 /* Check the DMA peripheral state */
511 if(hdma->State != HAL_DMA_STATE_BUSY)
512 {
513 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
514
515 /* Process Unlocked */
516 __HAL_UNLOCK(hdma);
517
518 return HAL_ERROR;
519 }
520 else
521 {
522 /* Disable DMA IT */
523 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
524
525 /* disable the DMAMUX sync overrun IT*/
526 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
527
528 /* Disable the channel */
529 __HAL_DMA_DISABLE(hdma);
530
531 /* Clear all flags */
532 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
533
534 /* Clear the DMAMUX synchro overrun flag */
535 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
536
537 if (hdma->DMAmuxRequestGen != 0U)
538 {
539 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
540 /* disable the request gen overrun IT*/
541 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
542
543 /* Clear the DMAMUX request generator overrun flag */
544 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
545 }
546
547 /* Change the DMA state */
548 hdma->State = HAL_DMA_STATE_READY;
549
550 /* Process Unlocked */
551 __HAL_UNLOCK(hdma);
552 }
553
554 return HAL_OK;
555 }
556
557 /**
558 * @brief Aborts the DMA Transfer in Interrupt mode.
559 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
560 * the configuration information for the specified DMA Channel.
561 * @retval HAL status
562 */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)563 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
564 {
565 HAL_StatusTypeDef status = HAL_OK;
566
567 if (HAL_DMA_STATE_BUSY != hdma->State)
568 {
569 /* no transfer ongoing */
570 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
571
572 status = HAL_ERROR;
573 }
574 else
575 {
576 /* Disable DMA IT */
577 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
578
579 /* Disable the channel */
580 __HAL_DMA_DISABLE(hdma);
581
582 /* disable the DMAMUX sync overrun IT*/
583 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
584
585 /* Clear all flags */
586 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
587
588 /* Clear the DMAMUX synchro overrun flag */
589 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
590
591 if (hdma->DMAmuxRequestGen != 0U)
592 {
593 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
594 /* disable the request gen overrun IT*/
595 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
596
597 /* Clear the DMAMUX request generator overrun flag */
598 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
599 }
600
601 /* Change the DMA state */
602 hdma->State = HAL_DMA_STATE_READY;
603
604 /* Process Unlocked */
605 __HAL_UNLOCK(hdma);
606
607 /* Call User Abort callback */
608 if (hdma->XferAbortCallback != NULL)
609 {
610 hdma->XferAbortCallback(hdma);
611 }
612 }
613 return status;
614 }
615
616 /**
617 * @brief Polling for transfer complete.
618 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
619 * the configuration information for the specified DMA Channel.
620 * @param CompleteLevel Specifies the DMA level complete.
621 * @param Timeout Timeout duration.
622 * @retval HAL status
623 */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)624 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
625 {
626 uint32_t temp;
627 uint32_t tickstart;
628
629 if (HAL_DMA_STATE_BUSY != hdma->State)
630 {
631 /* no transfer ongoing */
632 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
633 __HAL_UNLOCK(hdma);
634 return HAL_ERROR;
635 }
636
637 /* Polling mode not supported in circular mode */
638 if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
639 {
640 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
641 return HAL_ERROR;
642 }
643
644 /* Get the level transfer complete flag */
645 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
646 {
647 /* Transfer Complete flag */
648 temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU);
649 }
650 else
651 {
652 /* Half Transfer Complete flag */
653 temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU);
654 }
655
656 /* Get tick */
657 tickstart = HAL_GetTick();
658
659 while((hdma->DmaBaseAddress->ISR & temp) == 0U)
660 {
661 if((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex& 0x1CU))) != 0U)
662 {
663 /* When a DMA transfer error occurs */
664 /* A hardware clear of its EN bits is performed */
665 /* Clear all flags */
666 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
667
668 /* Update error code */
669 hdma->ErrorCode = HAL_DMA_ERROR_TE;
670
671 /* Change the DMA state */
672 hdma->State = HAL_DMA_STATE_READY;
673
674 /* Process Unlocked */
675 __HAL_UNLOCK(hdma);
676
677 return HAL_ERROR;
678 }
679 /* Check for the Timeout */
680 if (Timeout != HAL_MAX_DELAY)
681 {
682 if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
683 {
684 /* Update error code */
685 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
686
687 /* Change the DMA state */
688 hdma->State = HAL_DMA_STATE_READY;
689
690 /* Process Unlocked */
691 __HAL_UNLOCK(hdma);
692
693 return HAL_ERROR;
694 }
695 }
696 }
697
698 /*Check for DMAMUX Request generator (if used) overrun status */
699 if (hdma->DMAmuxRequestGen != 0U)
700 {
701 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
702 if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
703 {
704 /* Disable the request gen overrun interrupt */
705 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
706
707 /* Clear the DMAMUX request generator overrun flag */
708 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
709
710 /* Update error code */
711 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
712 }
713 }
714
715 /* Check for DMAMUX Synchronization overrun */
716 if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
717 {
718 /* Clear the DMAMUX synchro overrun flag */
719 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
720
721 /* Update error code */
722 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
723 }
724
725 if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
726 {
727 /* Clear the transfer complete flag */
728 hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU));
729
730 /* Process unlocked */
731 __HAL_UNLOCK(hdma);
732
733 /* The selected Channelx EN bit is cleared (DMA is disabled and
734 all transfers are complete) */
735 hdma->State = HAL_DMA_STATE_READY;
736 }
737 else
738 {
739 /* Clear the half transfer complete flag */
740 hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU));
741 }
742
743 return HAL_OK;
744 }
745
746 /**
747 * @brief Handle DMA interrupt request.
748 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
749 * the configuration information for the specified DMA Channel.
750 * @retval None
751 */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)752 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
753 {
754 uint32_t flag_it = hdma->DmaBaseAddress->ISR;
755 uint32_t source_it = hdma->Instance->CCR;
756
757 /* Half Transfer Complete Interrupt management ******************************/
758 if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
759 {
760 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
761 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
762 {
763 /* Disable the half transfer interrupt */
764 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
765 }
766 /* Clear the half transfer complete flag */
767 hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU));
768
769 /* DMA peripheral state is not updated in Half Transfer */
770 /* but in Transfer Complete case */
771
772 if (hdma->XferHalfCpltCallback != NULL)
773 {
774 /* Half transfer callback */
775 hdma->XferHalfCpltCallback(hdma);
776 }
777 }
778
779 /* Transfer Complete Interrupt management ***********************************/
780 else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1cU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
781 {
782 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
783 {
784 /* Disable the transfer complete and error interrupt */
785 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
786
787 /* Change the DMA state */
788 hdma->State = HAL_DMA_STATE_READY;
789 }
790 /* Clear the transfer complete flag */
791 hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1cU));
792
793 /* Process Unlocked */
794 __HAL_UNLOCK(hdma);
795
796 if (hdma->XferCpltCallback != NULL)
797 {
798 /* Transfer complete callback */
799 hdma->XferCpltCallback(hdma);
800 }
801 }
802
803 /* Transfer Error Interrupt management **************************************/
804 else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1cU)))!= 0U) && ((source_it & DMA_IT_TE) != 0U))
805 {
806 /* When a DMA transfer error occurs */
807 /* A hardware clear of its EN bits is performed */
808 /* Disable ALL DMA IT */
809 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
810
811 /* Clear all flags */
812 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
813
814 /* Update error code */
815 hdma->ErrorCode = HAL_DMA_ERROR_TE;
816
817 /* Change the DMA state */
818 hdma->State = HAL_DMA_STATE_READY;
819
820 /* Process Unlocked */
821 __HAL_UNLOCK(hdma);
822
823 if (hdma->XferErrorCallback != NULL)
824 {
825 /* Transfer error callback */
826 hdma->XferErrorCallback(hdma);
827 }
828 }
829 else
830 {
831 /* Nothing To Do */
832 }
833 return;
834 }
835
836 /**
837 * @brief Register callbacks
838 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
839 * the configuration information for the specified DMA Channel.
840 * @param CallbackID User Callback identifer
841 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
842 * @param pCallback Pointer to private callbacsk function which has pointer to
843 * a DMA_HandleTypeDef structure as parameter.
844 * @retval HAL status
845 */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))846 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
847 {
848 HAL_StatusTypeDef status = HAL_OK;
849
850 /* Process locked */
851 __HAL_LOCK(hdma);
852
853 if (HAL_DMA_STATE_READY == hdma->State)
854 {
855 switch (CallbackID)
856 {
857 case HAL_DMA_XFER_CPLT_CB_ID:
858 hdma->XferCpltCallback = pCallback;
859 break;
860
861 case HAL_DMA_XFER_HALFCPLT_CB_ID:
862 hdma->XferHalfCpltCallback = pCallback;
863 break;
864
865 case HAL_DMA_XFER_ERROR_CB_ID:
866 hdma->XferErrorCallback = pCallback;
867 break;
868
869 case HAL_DMA_XFER_ABORT_CB_ID:
870 hdma->XferAbortCallback = pCallback;
871 break;
872
873 default:
874 status = HAL_ERROR;
875 break;
876 }
877 }
878 else
879 {
880 status = HAL_ERROR;
881 }
882
883 /* Release Lock */
884 __HAL_UNLOCK(hdma);
885
886 return status;
887 }
888
889 /**
890 * @brief UnRegister callbacks
891 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
892 * the configuration information for the specified DMA Channel.
893 * @param CallbackID User Callback identifer
894 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
895 * @retval HAL status
896 */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)897 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
898 {
899 HAL_StatusTypeDef status = HAL_OK;
900
901 /* Process locked */
902 __HAL_LOCK(hdma);
903
904 if (HAL_DMA_STATE_READY == hdma->State)
905 {
906 switch (CallbackID)
907 {
908 case HAL_DMA_XFER_CPLT_CB_ID:
909 hdma->XferCpltCallback = NULL;
910 break;
911
912 case HAL_DMA_XFER_HALFCPLT_CB_ID:
913 hdma->XferHalfCpltCallback = NULL;
914 break;
915
916 case HAL_DMA_XFER_ERROR_CB_ID:
917 hdma->XferErrorCallback = NULL;
918 break;
919
920 case HAL_DMA_XFER_ABORT_CB_ID:
921 hdma->XferAbortCallback = NULL;
922 break;
923
924 case HAL_DMA_XFER_ALL_CB_ID:
925 hdma->XferCpltCallback = NULL;
926 hdma->XferHalfCpltCallback = NULL;
927 hdma->XferErrorCallback = NULL;
928 hdma->XferAbortCallback = NULL;
929 break;
930
931 default:
932 status = HAL_ERROR;
933 break;
934 }
935 }
936 else
937 {
938 status = HAL_ERROR;
939 }
940
941 /* Release Lock */
942 __HAL_UNLOCK(hdma);
943
944 return status;
945 }
946
947 /**
948 * @}
949 */
950
951
952
953 /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
954 * @brief Peripheral State and Errors functions
955 *
956 @verbatim
957 ===============================================================================
958 ##### Peripheral State and Errors functions #####
959 ===============================================================================
960 [..]
961 This subsection provides functions allowing to
962 (+) Check the DMA state
963 (+) Get error code
964
965 @endverbatim
966 * @{
967 */
968
969 /**
970 * @brief Return the DMA handle state.
971 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
972 * the configuration information for the specified DMA Channel.
973 * @retval HAL state
974 */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)975 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
976 {
977 /* Return DMA handle state */
978 return hdma->State;
979 }
980
981 /**
982 * @brief Return the DMA error code.
983 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
984 * the configuration information for the specified DMA Channel.
985 * @retval DMA Error Code
986 */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)987 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
988 {
989 return hdma->ErrorCode;
990 }
991
992 /**
993 * @}
994 */
995
996 /**
997 * @}
998 */
999
1000 /** @addtogroup DMA_Private_Functions
1001 * @{
1002 */
1003
1004 /**
1005 * @brief Sets the DMA Transfer parameter.
1006 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1007 * the configuration information for the specified DMA Channel.
1008 * @param SrcAddress The source memory Buffer address
1009 * @param DstAddress The destination memory Buffer address
1010 * @param DataLength The length of data to be transferred from source to destination
1011 * @retval HAL status
1012 */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)1013 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
1014 {
1015 /* Clear the DMAMUX synchro overrun flag */
1016 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
1017
1018 if (hdma->DMAmuxRequestGen != 0U)
1019 {
1020 /* Clear the DMAMUX request generator overrun flag */
1021 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
1022 }
1023
1024 /* Clear all flags */
1025 hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1cU));
1026
1027 /* Configure DMA Channel data length */
1028 hdma->Instance->CNDTR = DataLength;
1029
1030 /* Memory to Peripheral */
1031 if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1032 {
1033 /* Configure DMA Channel destination address */
1034 hdma->Instance->CPAR = DstAddress;
1035
1036 /* Configure DMA Channel source address */
1037 hdma->Instance->CMAR = SrcAddress;
1038 }
1039 /* Peripheral to Memory */
1040 else
1041 {
1042 /* Configure DMA Channel source address */
1043 hdma->Instance->CPAR = SrcAddress;
1044
1045 /* Configure DMA Channel destination address */
1046 hdma->Instance->CMAR = DstAddress;
1047 }
1048 }
1049
1050 /**
1051 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on channel number
1052 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1053 * the configuration information for the specified DMA Channel.
1054 * @retval None
1055 */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1056 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1057 {
1058 uint32_t channel_number;
1059
1060 /* check if instance is not outside the DMA channel range */
1061 #if defined(DMA2)
1062 if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1)
1063 {
1064 /* DMA1 */
1065 hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
1066 }
1067 else
1068 {
1069 /* DMA2 */
1070 hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U));
1071 }
1072 #else
1073 /* DMA1 */
1074 hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
1075 #endif
1076 channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
1077 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1078
1079 /* Initialize the field DMAmuxChannelStatusMask with the corresponding index of the DMAMUX channel selected for the current ChannelIndex */
1080 hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1FU);
1081 }
1082
1083 /**
1084 * @brief Updates the DMA handle with the DMAMUX request generator params
1085 * @param hdma Pointer to a DMA_HandleTypeDef structure that contains
1086 * the configuration information for the specified DMA Channel.
1087 * @retval None
1088 */
1089
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1090 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1091 {
1092 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1093
1094 /* DMA Channels are connected to DMAMUX1 request generator blocks*/
1095 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
1096
1097 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1098
1099 /* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/
1100 hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
1101 }
1102
1103 /**
1104 * @}
1105 */
1106
1107 /**
1108 * @}
1109 */
1110
1111 #endif /* HAL_DMA_MODULE_ENABLED */
1112 /**
1113 * @}
1114 */
1115
1116 /**
1117 * @}
1118 */
1119
1120 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1121