1 /**
2 ******************************************************************************
3 * @file stm32mp1xx_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 Stream
28 (except for internal SRAM/FLASH memories: no initialization is
29 necessary) please refer to Reference manual for connection between peripherals
30 and DMA requests .
31
32 (#) For a given Stream, program the required configuration through the following parameters:
33 Transfer Direction, Source and Destination data formats,
34 Circular, Normal or peripheral flow control mode, Stream Priority level,
35 Source and Destination Increment mode, FIFO mode and its Threshold (if needed),
36 Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function.
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. In this
53 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 by customization of function pointer XferCpltCallback and
57 XferErrorCallback (i.e a member of DMA handle structure).
58 [..]
59 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
60 detection.
61
62 (#) Use HAL_DMA_Abort() function to abort the current transfer
63
64 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
65
66 -@- The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
67 possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
68 Half-Word data size for the peripheral to access its data register and set Word data size
69 for the Memory to gain in access time. Each two half words will be packed and written in
70 a single access to a Word in the Memory).
71
72 -@- When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
73 and Destination. In this case the Peripheral Data Size will be applied to both Source
74 and Destination.
75
76 *** DMA HAL driver macros list ***
77 =============================================
78 [..]
79 Below the list of most used macros in DMA HAL driver.
80
81 (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream.
82 (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream.
83 (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level.
84 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts.
85 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts.
86 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream interrupt has occurred or not.
87
88 [..]
89 (@) You can refer to the DMA HAL driver header file for more useful macros.
90
91 @endverbatim
92 ******************************************************************************
93 */
94
95 /* Includes ------------------------------------------------------------------*/
96 #include "stm32mp1xx_hal.h"
97
98 /** @addtogroup STM32MP1xx_HAL_Driver
99 * @{
100 */
101
102 /** @defgroup DMA DMA
103 * @brief DMA HAL module driver
104 * @{
105 */
106
107 #ifdef HAL_DMA_MODULE_ENABLED
108
109 /* Private types -------------------------------------------------------------*/
110 typedef struct
111 {
112 __IO uint32_t ISR; /*!< DMA interrupt status register */
113 __IO uint32_t Reserved0;
114 __IO uint32_t IFCR; /*!< DMA interrupt flag clear register */
115 } DMA_Base_Registers;
116
117 /* Private variables ---------------------------------------------------------*/
118 /* Private constants ---------------------------------------------------------*/
119 /** @addtogroup DMA_Private_Constants
120 * @{
121 */
122 #define HAL_TIMEOUT_DMA_ABORT (5U) /* 5 ms */
123
124
125 /**
126 * @}
127 */
128 /* Private macros ------------------------------------------------------------*/
129 /* Private functions ---------------------------------------------------------*/
130 /** @addtogroup DMA_Private_Functions
131 * @{
132 */
133 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
134 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
135 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma);
136 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
137 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
138
139 /**
140 * @}
141 */
142
143 /* Exported functions ---------------------------------------------------------*/
144 /** @addtogroup DMA_Exported_Functions
145 * @{
146 */
147
148 /** @addtogroup DMA_Exported_Functions_Group1
149 *
150 @verbatim
151 ===============================================================================
152 ##### Initialization and de-initialization functions #####
153 ===============================================================================
154 [..]
155 This section provides functions allowing to initialize the DMA Stream source
156 and destination incrementation and data sizes, transfer direction,
157 circular/normal mode selection, memory-to-memory mode selection and Stream priority value.
158 [..]
159 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
160 reference manual.
161 The HAL_DMA_DeInit function allows to deinitialize the DMA stream.
162
163 @endverbatim
164 * @{
165 */
166
167 /**
168 * @brief Initialize the DMA according to the specified
169 * parameters in the DMA_InitTypeDef and create the associated handle.
170 * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
171 * the configuration information for the specified DMA Stream.
172 * @retval HAL status
173 */
HAL_DMA_Init(DMA_HandleTypeDef * hdma)174 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
175 {
176 uint32_t registerValue;
177 uint32_t tickstart = HAL_GetTick();
178 DMA_Base_Registers *regs_dma;
179
180 /* Check the DMA peripheral handle */
181 if (hdma == NULL)
182 {
183 return HAL_ERROR;
184 }
185
186 /* Check the parameters */
187 assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));
188 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
189 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
190 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
191 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
192 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
193 assert_param(IS_DMA_MODE(hdma->Init.Mode));
194 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
195
196 if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
197 {
198
199 assert_param(IS_DMA_REQUEST(hdma->Init.Request));
200 assert_param(IS_DMA_FIFO_MODE_STATE(hdma->Init.FIFOMode));
201 /* Check the memory burst, peripheral burst and FIFO threshold parameters only
202 when FIFO mode is enabled */
203 if (hdma->Init.FIFOMode != DMA_FIFOMODE_DISABLE)
204 {
205 assert_param(IS_DMA_FIFO_THRESHOLD(hdma->Init.FIFOThreshold));
206 assert_param(IS_DMA_MEMORY_BURST(hdma->Init.MemBurst));
207 assert_param(IS_DMA_PERIPHERAL_BURST(hdma->Init.PeriphBurst));
208 }
209
210
211
212 /* Change DMA peripheral state */
213 hdma->State = HAL_DMA_STATE_BUSY;
214
215 /* Allocate lock resource */
216 __HAL_UNLOCK(hdma);
217
218 /* Disable the peripheral */
219 __HAL_DMA_DISABLE(hdma);
220
221 /* Check if the DMA Stream is effectively disabled */
222 while ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
223 {
224 /* Check for the Timeout */
225 if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
226 {
227 /* Update error code */
228 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
229
230 /* Change the DMA state */
231 hdma->State = HAL_DMA_STATE_ERROR;
232
233 return HAL_ERROR;
234 }
235 }
236
237 /* Get the CR register value */
238 registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->CR;
239
240 /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
241 registerValue &= ((uint32_t)~(DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
242 DMA_SxCR_PL | DMA_SxCR_MSIZE | DMA_SxCR_PSIZE | \
243 DMA_SxCR_MINC | DMA_SxCR_PINC | DMA_SxCR_CIRC | \
244 DMA_SxCR_DIR | DMA_SxCR_CT | DMA_SxCR_DBM));
245
246 /* Prepare the DMA Stream configuration */
247 registerValue |= hdma->Init.Direction |
248 hdma->Init.PeriphInc | hdma->Init.MemInc |
249 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
250 hdma->Init.Mode | hdma->Init.Priority;
251
252 /* the Memory burst and peripheral burst are not used when the FIFO is disabled */
253 if (hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
254 {
255 /* Get memory burst and peripheral burst */
256 registerValue |= hdma->Init.MemBurst | hdma->Init.PeriphBurst;
257 }
258
259 /* Write to DMA Stream CR register */
260 ((DMA_Stream_TypeDef *)hdma->Instance)->CR = registerValue;
261
262 /* Get the FCR register value */
263 registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->FCR;
264
265 /* Clear Direct mode and FIFO threshold bits */
266 registerValue &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
267
268 /* Prepare the DMA Stream FIFO configuration */
269 registerValue |= hdma->Init.FIFOMode;
270
271 /* the FIFO threshold is not used when the FIFO mode is disabled */
272 if (hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
273 {
274 /* Get the FIFO threshold */
275 registerValue |= hdma->Init.FIFOThreshold;
276
277 /* Check compatibility between FIFO threshold level and size of the memory burst */
278 /* for INCR4, INCR8, INCR16 */
279 if (hdma->Init.MemBurst != DMA_MBURST_SINGLE)
280 {
281 if (DMA_CheckFifoParam(hdma) != HAL_OK)
282 {
283 /* Update error code */
284 hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
285
286 /* Change the DMA state */
287 hdma->State = HAL_DMA_STATE_READY;
288
289 return HAL_ERROR;
290 }
291 }
292 }
293
294 /* Write to DMA Stream FCR */
295 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = registerValue;
296
297 /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
298 DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
299 regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
300
301 /* Clear all interrupt flags */
302 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
303 }
304 else
305 {
306 hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
307 hdma->State = HAL_DMA_STATE_ERROR;
308
309 return HAL_ERROR;
310 }
311
312 /* Initialize parameters for DMAMUX channel :
313 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
314 */
315 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
316
317 if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
318 {
319 /* if memory to memory force the request to 0*/
320 hdma->Init.Request = DMA_REQUEST_MEM2MEM;
321 }
322
323
324 /* Set peripheral request to DMAMUX channel */
325 hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
326
327 /* Clear the DMAMUX synchro overrun flag */
328 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
329
330 /* Initialize parameters for DMAMUX request generator :
331 if the DMA request is DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR7
332 */
333
334 if ((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
335 {
336 /* Initialize parameters for DMAMUX request generator :
337 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
338 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
339
340 /* Reset the DMAMUX request generator register*/
341 hdma->DMAmuxRequestGen->RGCR = 0U;
342
343 /* Clear the DMAMUX request generator overrun flag */
344 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
345 }
346 else
347 {
348 hdma->DMAmuxRequestGen = 0U;
349 hdma->DMAmuxRequestGenStatus = 0U;
350 hdma->DMAmuxRequestGenStatusMask = 0U;
351 }
352
353 /* Initialize the error code */
354 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
355
356 /* Initialize the DMA state */
357 hdma->State = HAL_DMA_STATE_READY;
358
359 return HAL_OK;
360 }
361
362 /**
363 * @brief DeInitializes the DMA peripheral
364 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
365 * the configuration information for the specified DMA Stream.
366 * @retval HAL status
367 */
HAL_DMA_DeInit(DMA_HandleTypeDef * hdma)368 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
369 {
370 DMA_Base_Registers *regs_dma;
371
372 /* Check the DMA peripheral handle */
373 if (hdma == NULL)
374 {
375 return HAL_ERROR;
376 }
377
378 /* Disable the selected DMA Streamx */
379 __HAL_DMA_DISABLE(hdma);
380
381
382 /* Reset DMA Streamx control register */
383 ((DMA_Stream_TypeDef *)hdma->Instance)->CR = 0U;
384
385 /* Reset DMA Streamx number of data to transfer register */
386 ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = 0U;
387
388 /* Reset DMA Streamx peripheral address register */
389 ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = 0U;
390
391 /* Reset DMA Streamx memory 0 address register */
392 ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = 0U;
393
394 /* Reset DMA Streamx memory 1 address register */
395 ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = 0U;
396
397 /* Reset DMA Streamx FIFO control register */
398 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = (uint32_t)0x00000021U;
399
400 /* Get DMA steam Base Address */
401 regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
402
403 /* Clear all interrupt flags at correct offset within the register */
404 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
405 /* Initialize parameters for DMAMUX channel :
406 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
407 DMA_CalcDMAMUXChannelBaseAndMask(hdma);
408
409 if(hdma->DMAmuxChannel != 0U)
410 {
411 /* Resett he DMAMUX channel that corresponds to the DMA stream */
412 hdma->DMAmuxChannel->CCR = 0U;
413
414 /* Clear the DMAMUX synchro overrun flag */
415 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
416 }
417
418 if ((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
419 {
420 /* Initialize parameters for DMAMUX request generator :
421 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
422 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
423
424 /* Reset the DMAMUX request generator register*/
425 hdma->DMAmuxRequestGen->RGCR = 0U;
426
427 /* Clear the DMAMUX request generator overrun flag */
428 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
429 }
430
431 hdma->DMAmuxRequestGen = 0U;
432 hdma->DMAmuxRequestGenStatus = 0U;
433 hdma->DMAmuxRequestGenStatusMask = 0U;
434
435 /* Clean callbacks */
436 hdma->XferCpltCallback = NULL;
437 hdma->XferHalfCpltCallback = NULL;
438 hdma->XferM1CpltCallback = NULL;
439 hdma->XferM1HalfCpltCallback = NULL;
440 hdma->XferErrorCallback = NULL;
441 hdma->XferAbortCallback = NULL;
442
443 /* Initialize the error code */
444 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
445
446 /* Initialize the DMA state */
447 hdma->State = HAL_DMA_STATE_RESET;
448
449 /* Release Lock */
450 __HAL_UNLOCK(hdma);
451
452 return HAL_OK;
453 }
454
455 /**
456 * @}
457 */
458
459 /** @addtogroup DMA_Exported_Functions_Group2
460 *
461 @verbatim
462 ===============================================================================
463 ##### IO operation functions #####
464 ===============================================================================
465 [..] This section provides functions allowing to:
466 (+) Configure the source, destination address and data length and Start DMA transfer
467 (+) Configure the source, destination address and data length and
468 Start DMA transfer with interrupt
469 (+) Register and Unregister DMA callbacks
470 (+) Abort DMA transfer
471 (+) Poll for transfer complete
472 (+) Handle DMA interrupt request
473
474 @endverbatim
475 * @{
476 */
477
478 /**
479 * @brief Starts the DMA Transfer.
480 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
481 * the configuration information for the specified DMA Stream.
482 * @param SrcAddress: The source memory Buffer address
483 * @param DstAddress: The destination memory Buffer address
484 * @param DataLength: The length of data to be transferred from source to destination
485 * @retval HAL status
486 */
HAL_DMA_Start(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)487 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
488 {
489 HAL_StatusTypeDef status = HAL_OK;
490
491 /* Check the parameters */
492 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
493
494 /* Check the DMA peripheral handle */
495 if (hdma == NULL)
496 {
497 return HAL_ERROR;
498 }
499
500 /* Process locked */
501 __HAL_LOCK(hdma);
502
503 if (HAL_DMA_STATE_READY == hdma->State)
504 {
505 /* Change DMA peripheral state */
506 hdma->State = HAL_DMA_STATE_BUSY;
507
508 /* Initialize the error code */
509 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
510
511 /* Disable the peripheral */
512 __HAL_DMA_DISABLE(hdma);
513
514 /* Configure the source, destination address and the data length */
515 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
516
517 /* Enable the Peripheral */
518 __HAL_DMA_ENABLE(hdma);
519 }
520 else
521 {
522 /* Set the error code to busy */
523 hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
524
525 /* Process unlocked */
526 __HAL_UNLOCK(hdma);
527
528 /* Return error status */
529 status = HAL_ERROR;
530 }
531 return status;
532 }
533
534 /**
535 * @brief Start the DMA Transfer with interrupt enabled.
536 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
537 * the configuration information for the specified DMA Stream.
538 * @param SrcAddress: The source memory Buffer address
539 * @param DstAddress: The destination memory Buffer address
540 * @param DataLength: The length of data to be transferred from source to destination
541 * @retval HAL status
542 */
HAL_DMA_Start_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)543 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
544 {
545 HAL_StatusTypeDef status = HAL_OK;
546
547 /* Check the parameters */
548 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
549
550 /* Check the DMA peripheral handle */
551 if (hdma == NULL)
552 {
553 return HAL_ERROR;
554 }
555
556 /* Process locked */
557 __HAL_LOCK(hdma);
558
559 if (HAL_DMA_STATE_READY == hdma->State)
560 {
561 /* Change DMA peripheral state */
562 hdma->State = HAL_DMA_STATE_BUSY;
563
564 /* Initialize the error code */
565 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
566
567 /* Disable the peripheral */
568 __HAL_DMA_DISABLE(hdma);
569
570 /* Configure the source, destination address and the data length */
571 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
572
573 /* Enable Common interrupts*/
574 MODIFY_REG(((DMA_Stream_TypeDef *)hdma->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
575 if (hdma->XferHalfCpltCallback != NULL)
576 {
577 /*Enable Half Transfer IT if corresponding Callback is set*/
578 ((DMA_Stream_TypeDef *)hdma->Instance)->CR |= DMA_IT_HT;
579 }
580
581 /* Check if DMAMUX Synchronization is enabled*/
582 if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
583 {
584 /* Enable DMAMUX sync overrun IT*/
585 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
586 }
587
588 if(hdma->DMAmuxRequestGen != 0U)
589 {
590 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
591 /* enable the request gen overrun IT*/
592 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
593
594 }
595
596 /* Enable the Peripheral */
597 __HAL_DMA_ENABLE(hdma);
598 }
599 else
600 {
601 /* Set the error code to busy */
602 hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
603
604 /* Process unlocked */
605 __HAL_UNLOCK(hdma);
606
607 /* Return error status */
608 status = HAL_ERROR;
609 }
610
611 return status;
612 }
613
614 /**
615 * @brief Aborts the DMA Transfer.
616 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
617 * the configuration information for the specified DMA Stream.
618 *
619 * @note After disabling a DMA Stream, a check for wait until the DMA Stream is
620 * effectively disabled is added. If a Stream is disabled
621 * while a data transfer is ongoing, the current data will be transferred
622 * and the Stream will be effectively disabled only after the transfer of
623 * this single data is finished.
624 * @retval HAL status
625 */
HAL_DMA_Abort(DMA_HandleTypeDef * hdma)626 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
627 {
628 /* calculate DMA base and stream number */
629 DMA_Base_Registers *regs_dma;
630 const __IO uint32_t *enableRegister;
631
632 uint32_t tickstart = HAL_GetTick();
633
634 /* Check the DMA peripheral handle */
635 if (hdma == NULL)
636 {
637 return HAL_ERROR;
638 }
639
640 /* Check the DMA peripheral state */
641 if (hdma->State != HAL_DMA_STATE_BUSY)
642 {
643 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
644
645 /* Process Unlocked */
646 __HAL_UNLOCK(hdma);
647
648 return HAL_ERROR;
649 }
650 else
651 {
652 /* Disable DMA All Interrupts */
653 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT);
654 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
655
656 enableRegister = (__IO uint32_t *)(&(((DMA_Stream_TypeDef *)hdma->Instance)->CR));
657
658 /* disable the DMAMUX sync overrun IT*/
659 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
660
661 /* Disable the stream */
662 __HAL_DMA_DISABLE(hdma);
663
664 /* Check if the DMA Stream is effectively disabled */
665 while (((*enableRegister) & DMA_SxCR_EN) != 0U)
666 {
667 /* Check for the Timeout */
668 if ((HAL_GetTick() - tickstart) > HAL_TIMEOUT_DMA_ABORT)
669 {
670 /* Update error code */
671 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
672
673 /* Change the DMA state */
674 hdma->State = HAL_DMA_STATE_ERROR;
675
676 /* Process Unlocked */
677 __HAL_UNLOCK(hdma);
678
679 return HAL_ERROR;
680 }
681 }
682 regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
683 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
684
685 /* Clear the DMAMUX synchro overrun flag */
686 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
687
688 if(hdma->DMAmuxRequestGen != 0U)
689 {
690 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
691 /* disable the request gen overrun IT*/
692 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
693
694 /* Clear the DMAMUX request generator overrun flag */
695 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
696 }
697
698 /* Change the DMA state*/
699 hdma->State = HAL_DMA_STATE_READY;
700 /* Process Unlocked */
701 __HAL_UNLOCK(hdma);
702 }
703 return HAL_OK;
704 }
705
706 /**
707 * @brief Aborts the DMA Transfer in Interrupt mode.
708 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
709 * the configuration information for the specified DMA Stream.
710 * @retval HAL status
711 */
HAL_DMA_Abort_IT(DMA_HandleTypeDef * hdma)712 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
713 {
714 /* Check the DMA peripheral handle */
715 if (hdma == NULL)
716 {
717 return HAL_ERROR;
718 }
719
720 if (hdma->State != HAL_DMA_STATE_BUSY)
721 {
722 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
723 return HAL_ERROR;
724 }
725 else
726 {
727 /* Set Abort State */
728 hdma->State = HAL_DMA_STATE_ABORT;
729
730 /* Disable the stream */
731 __HAL_DMA_DISABLE(hdma);
732 }
733
734 return HAL_OK;
735 }
736
737 /**
738 * @brief Polling for transfer complete.
739 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
740 * the configuration information for the specified DMA Stream.
741 * @param CompleteLevel: Specifies the DMA level complete.
742 * @note The polling mode is kept in this version for legacy. it is recommended to use the IT model instead.
743 * This model could be used for debug purpose.
744 * @note The HAL_DMA_PollForTransfer API cannot be used in circular and double buffering mode (automatic circular mode).
745 * @param Timeout: Timeout duration.
746 * @retval HAL status
747 */
HAL_DMA_PollForTransfer(DMA_HandleTypeDef * hdma,HAL_DMA_LevelCompleteTypeDef CompleteLevel,uint32_t Timeout)748 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
749 {
750 HAL_StatusTypeDef status = HAL_OK;
751 uint32_t cpltlevel_mask;
752 uint32_t tickstart = HAL_GetTick();
753
754 /* IT status register */
755 const __IO uint32_t *isr_reg;
756 /* IT clear flag register */
757 __IO uint32_t *ifcr_reg;
758
759 /* Check the DMA peripheral handle */
760 if (hdma == NULL)
761 {
762 return HAL_ERROR;
763 }
764
765 if (HAL_DMA_STATE_BUSY != hdma->State)
766 {
767 /* No transfer ongoing */
768 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
769 __HAL_UNLOCK(hdma);
770
771 return HAL_ERROR;
772 }
773 /* Polling mode not supported in circular mode and double buffering mode */
774 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) != 0U)
775 {
776 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
777 return HAL_ERROR;
778 }
779
780 /* Get the level transfer complete flag */
781 if (CompleteLevel == HAL_DMA_FULL_TRANSFER)
782 {
783 /* Transfer Complete flag */
784 cpltlevel_mask = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
785 }
786 else
787 {
788 /* Half Transfer Complete flag */
789 cpltlevel_mask = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
790 }
791
792 isr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->ISR);
793 ifcr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR);
794
795 while(((*isr_reg) & cpltlevel_mask) == 0U)
796 {
797 if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
798 {
799 if(((*isr_reg) & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
800 {
801 /* Update error code */
802 hdma->ErrorCode |= HAL_DMA_ERROR_FE;
803
804 /* Clear the FIFO error flag */
805 (*ifcr_reg) = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
806 }
807
808 if(((*isr_reg) & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
809 {
810 /* Update error code */
811 hdma->ErrorCode |= HAL_DMA_ERROR_DME;
812
813 /* Clear the Direct Mode error flag */
814 (*ifcr_reg) = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
815 }
816
817 if(((*isr_reg) & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
818 {
819 /* Update error code */
820 hdma->ErrorCode |= HAL_DMA_ERROR_TE;
821
822 /* Clear the transfer error flag */
823 (*ifcr_reg) = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
824
825 /* Change the DMA state */
826 hdma->State = HAL_DMA_STATE_READY;
827
828 /* Process Unlocked */
829 __HAL_UNLOCK(hdma);
830
831 return HAL_ERROR;
832 }
833 }
834
835 }
836
837 /* Check for the Timeout (Not applicable in circular mode)*/
838 if (Timeout != HAL_MAX_DELAY)
839 {
840 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
841 {
842 /* Update error code */
843 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
844
845 /* if timeout then abort the current transfer */
846 /* No need to check return value: as in this case we will return HAL_ERROR with HAL_DMA_ERROR_TIMEOUT error code */
847 (void) HAL_DMA_Abort(hdma);
848 /*
849 Note that the Abort function will
850 - Clear the transfer error flags
851 - Unlock
852 - Set the State
853 */
854
855
856 return HAL_ERROR;
857 }
858 }
859
860 /*Check for DMAMUX Request generator (if used) overrun status */
861 if(hdma->DMAmuxRequestGen != 0U)
862 {
863 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
864 if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
865 {
866 /* Clear the DMAMUX request generator overrun flag */
867 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
868
869 /* Update error code */
870 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
871 }
872 }
873
874 /* Check for DMAMUX Synchronization overrun */
875 if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
876 {
877 /* Clear the DMAMUX synchro overrun flag */
878 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
879
880 /* Update error code */
881 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
882 }
883
884
885
886 /* Get the level transfer complete flag */
887 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
888 {
889 /* Clear the half transfer and transfer complete flags */
890 if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
891 {
892 (*ifcr_reg) = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << (hdma->StreamIndex & 0x1FU);
893 }
894 hdma->State = HAL_DMA_STATE_READY;
895 /* Process Unlocked */
896 __HAL_UNLOCK(hdma);
897 }
898 else /*CompleteLevel = HAL_DMA_HALF_TRANSFER*/
899 {
900 /* Clear the half transfer and transfer complete flags */
901 if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
902 {
903 (*ifcr_reg) = (DMA_FLAG_HTIF0_4) << (hdma->StreamIndex & 0x1FU);
904 }
905 }
906
907 return status;
908 }
909
910 /**
911 * @brief Handles DMA interrupt request.
912 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
913 * the configuration information for the specified DMA Stream.
914 * @retval None
915 */
HAL_DMA_IRQHandler(DMA_HandleTypeDef * hdma)916 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
917 {
918 uint32_t tmpisr_dma;
919 __IO uint32_t count = 0U;
920 uint32_t timeout = SystemCoreClock / 9600U;
921
922 /* calculate DMA base and stream number */
923 DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
924
925 tmpisr_dma = regs_dma->ISR;
926
927 if(IS_DMA_INSTANCE(hdma) != 0U) /* DMA1 or DMA2 instance */
928 {
929 /* Transfer Error Interrupt management ***************************************/
930 if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
931 {
932 if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U)
933 {
934 /* Disable the transfer error interrupt */
935 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TE);
936
937 /* Clear the transfer error flag */
938 regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
939
940 /* Update error code */
941 hdma->ErrorCode |= HAL_DMA_ERROR_TE;
942 }
943 }
944 /* FIFO Error Interrupt management ******************************************/
945 if ((tmpisr_dma & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
946 {
947 if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != 0U)
948 {
949 /* Clear the FIFO error flag */
950 regs_dma->IFCR = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
951
952 /* Update error code */
953 hdma->ErrorCode |= HAL_DMA_ERROR_FE;
954 }
955 }
956 /* Direct Mode Error Interrupt management ***********************************/
957 if ((tmpisr_dma & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
958 {
959 if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != 0U)
960 {
961 /* Clear the direct mode error flag */
962 regs_dma->IFCR = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
963
964 /* Update error code */
965 hdma->ErrorCode |= HAL_DMA_ERROR_DME;
966 }
967 }
968 /* Half Transfer Complete Interrupt management ******************************/
969 if ((tmpisr_dma & (DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
970 {
971 if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U)
972 {
973 /* Clear the half transfer complete flag */
974 regs_dma->IFCR = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
975
976 /* Multi_Buffering mode enabled */
977 if (((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
978 {
979 /* Current memory buffer used is Memory 0 */
980 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
981 {
982 if (hdma->XferHalfCpltCallback != NULL)
983 {
984 /* Half transfer callback */
985 hdma->XferHalfCpltCallback(hdma);
986 }
987 }
988 /* Current memory buffer used is Memory 1 */
989 else
990 {
991 if (hdma->XferM1HalfCpltCallback != NULL)
992 {
993 /* Half transfer callback */
994 hdma->XferM1HalfCpltCallback(hdma);
995 }
996 }
997 }
998 else
999 {
1000 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
1001 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
1002 {
1003 /* Disable the half transfer interrupt */
1004 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT);
1005 }
1006
1007 if (hdma->XferHalfCpltCallback != NULL)
1008 {
1009 /* Half transfer callback */
1010 hdma->XferHalfCpltCallback(hdma);
1011 }
1012 }
1013 }
1014 }
1015 /* Transfer Complete Interrupt management ***********************************/
1016 if ((tmpisr_dma & (DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
1017 {
1018 if (__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U)
1019 {
1020 /* Clear the transfer complete flag */
1021 regs_dma->IFCR = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
1022
1023 if (HAL_DMA_STATE_ABORT == hdma->State)
1024 {
1025 /* Disable all the transfer interrupts */
1026 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME);
1027 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
1028
1029 if ((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
1030 {
1031 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT);
1032 }
1033
1034 /* Clear all interrupt flags at correct offset within the register */
1035 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
1036
1037 /* Change the DMA state */
1038 hdma->State = HAL_DMA_STATE_READY;
1039
1040 /* Process Unlocked */
1041 __HAL_UNLOCK(hdma);
1042
1043 if (hdma->XferAbortCallback != NULL)
1044 {
1045 hdma->XferAbortCallback(hdma);
1046 }
1047 return;
1048 }
1049
1050 if (((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
1051 {
1052 /* Current memory buffer used is Memory 0 */
1053 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
1054 {
1055 if (hdma->XferM1CpltCallback != NULL)
1056 {
1057 /* Transfer complete Callback for memory1 */
1058 hdma->XferM1CpltCallback(hdma);
1059 }
1060 }
1061 /* Current memory buffer used is Memory 1 */
1062 else
1063 {
1064 if (hdma->XferCpltCallback != NULL)
1065 {
1066 /* Transfer complete Callback for memory0 */
1067 hdma->XferCpltCallback(hdma);
1068 }
1069 }
1070 }
1071 /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
1072 else
1073 {
1074 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
1075 {
1076 /* Disable the transfer complete interrupt */
1077 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC);
1078
1079 /* Change the DMA state */
1080 hdma->State = HAL_DMA_STATE_READY;
1081 /* Process Unlocked */
1082 __HAL_UNLOCK(hdma);
1083 }
1084
1085 if (hdma->XferCpltCallback != NULL)
1086 {
1087 /* Transfer complete callback */
1088 hdma->XferCpltCallback(hdma);
1089 }
1090 }
1091 }
1092 }
1093
1094 /* manage error case */
1095 if (hdma->ErrorCode != HAL_DMA_ERROR_NONE)
1096 {
1097 if ((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U)
1098 {
1099 hdma->State = HAL_DMA_STATE_ABORT;
1100
1101 /* Disable the stream */
1102 __HAL_DMA_DISABLE(hdma);
1103
1104 do
1105 {
1106 if (++count > timeout)
1107 {
1108 break;
1109 }
1110 }
1111 while ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);
1112
1113 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
1114 {
1115 /* Change the DMA state to error if DMA disable fails */
1116 hdma->State = HAL_DMA_STATE_ERROR;
1117 }
1118 else
1119 {
1120 /* Change the DMA state to Ready if DMA disable success */
1121 hdma->State = HAL_DMA_STATE_READY;
1122 }
1123 /* Process Unlocked */
1124 __HAL_UNLOCK(hdma);
1125 }
1126
1127 if (hdma->XferErrorCallback != NULL)
1128 {
1129 /* Transfer error callback */
1130 hdma->XferErrorCallback(hdma);
1131 }
1132 }
1133 }
1134 else
1135 {
1136 /* Nothing To Do */
1137 }
1138 }
1139
1140 /**
1141 * @brief Register callbacks
1142 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1143 * the configuration information for the specified DMA Stream.
1144 * @param CallbackID: User Callback identifier
1145 * a DMA_HandleTypeDef structure as parameter.
1146 * @param pCallback: pointer to private callback function which has pointer to
1147 * a DMA_HandleTypeDef structure as parameter.
1148 * @retval HAL status
1149 */
HAL_DMA_RegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID,void (* pCallback)(DMA_HandleTypeDef * _hdma))1150 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
1151 {
1152
1153 HAL_StatusTypeDef status = HAL_OK;
1154
1155 /* Check the DMA peripheral handle */
1156 if (hdma == NULL)
1157 {
1158 return HAL_ERROR;
1159 }
1160
1161 /* Process locked */
1162 __HAL_LOCK(hdma);
1163
1164 if (HAL_DMA_STATE_READY == hdma->State)
1165 {
1166 switch (CallbackID)
1167 {
1168 case HAL_DMA_XFER_CPLT_CB_ID:
1169 hdma->XferCpltCallback = pCallback;
1170 break;
1171
1172 case HAL_DMA_XFER_HALFCPLT_CB_ID:
1173 hdma->XferHalfCpltCallback = pCallback;
1174 break;
1175
1176 case HAL_DMA_XFER_M1CPLT_CB_ID:
1177 hdma->XferM1CpltCallback = pCallback;
1178 break;
1179
1180 case HAL_DMA_XFER_M1HALFCPLT_CB_ID:
1181 hdma->XferM1HalfCpltCallback = pCallback;
1182 break;
1183
1184 case HAL_DMA_XFER_ERROR_CB_ID:
1185 hdma->XferErrorCallback = pCallback;
1186 break;
1187
1188 case HAL_DMA_XFER_ABORT_CB_ID:
1189 hdma->XferAbortCallback = pCallback;
1190 break;
1191
1192 default:
1193 status = HAL_ERROR;
1194 break;
1195 }
1196 }
1197 else
1198 {
1199 /* Return error status */
1200 status = HAL_ERROR;
1201 }
1202
1203 /* Release Lock */
1204 __HAL_UNLOCK(hdma);
1205
1206 return status;
1207 }
1208
1209 /**
1210 * @brief UnRegister callbacks
1211 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1212 * the configuration information for the specified DMA Stream.
1213 * @param CallbackID: User Callback identifier
1214 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
1215 * @retval HAL status
1216 */
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef * hdma,HAL_DMA_CallbackIDTypeDef CallbackID)1217 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
1218 {
1219 HAL_StatusTypeDef status = HAL_OK;
1220
1221 /* Check the DMA peripheral handle */
1222 if (hdma == NULL)
1223 {
1224 return HAL_ERROR;
1225 }
1226
1227 /* Process locked */
1228 __HAL_LOCK(hdma);
1229
1230 if (HAL_DMA_STATE_READY == hdma->State)
1231 {
1232 switch (CallbackID)
1233 {
1234 case HAL_DMA_XFER_CPLT_CB_ID:
1235 hdma->XferCpltCallback = NULL;
1236 break;
1237
1238 case HAL_DMA_XFER_HALFCPLT_CB_ID:
1239 hdma->XferHalfCpltCallback = NULL;
1240 break;
1241
1242 case HAL_DMA_XFER_M1CPLT_CB_ID:
1243 hdma->XferM1CpltCallback = NULL;
1244 break;
1245
1246 case HAL_DMA_XFER_M1HALFCPLT_CB_ID:
1247 hdma->XferM1HalfCpltCallback = NULL;
1248 break;
1249
1250 case HAL_DMA_XFER_ERROR_CB_ID:
1251 hdma->XferErrorCallback = NULL;
1252 break;
1253
1254 case HAL_DMA_XFER_ABORT_CB_ID:
1255 hdma->XferAbortCallback = NULL;
1256 break;
1257
1258 case HAL_DMA_XFER_ALL_CB_ID:
1259 hdma->XferCpltCallback = NULL;
1260 hdma->XferHalfCpltCallback = NULL;
1261 hdma->XferM1CpltCallback = NULL;
1262 hdma->XferM1HalfCpltCallback = NULL;
1263 hdma->XferErrorCallback = NULL;
1264 hdma->XferAbortCallback = NULL;
1265 break;
1266
1267 default:
1268 status = HAL_ERROR;
1269 break;
1270 }
1271 }
1272 else
1273 {
1274 status = HAL_ERROR;
1275 }
1276
1277 /* Release Lock */
1278 __HAL_UNLOCK(hdma);
1279
1280 return status;
1281 }
1282
1283 /**
1284 * @}
1285 */
1286
1287 /** @addtogroup DMA_Exported_Functions_Group3
1288 *
1289 @verbatim
1290 ===============================================================================
1291 ##### State and Errors functions #####
1292 ===============================================================================
1293 [..]
1294 This subsection provides functions allowing to
1295 (+) Check the DMA state
1296 (+) Get error code
1297
1298 @endverbatim
1299 * @{
1300 */
1301
1302 /**
1303 * @brief Returns the DMA state.
1304 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1305 * the configuration information for the specified DMA Stream.
1306 * @retval HAL state
1307 */
HAL_DMA_GetState(DMA_HandleTypeDef * hdma)1308 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
1309 {
1310 return hdma->State;
1311 }
1312
1313 /**
1314 * @brief Return the DMA error code
1315 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
1316 * the configuration information for the specified DMA Stream.
1317 * @retval DMA Error Code
1318 */
HAL_DMA_GetError(DMA_HandleTypeDef * hdma)1319 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
1320 {
1321 return hdma->ErrorCode;
1322 }
1323
1324 /**
1325 * @}
1326 */
1327
1328 /**
1329 * @}
1330 */
1331
1332 /** @addtogroup DMA_Private_Functions
1333 * @{
1334 */
1335
1336 /**
1337 * @brief Sets the DMA Transfer parameter.
1338 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1339 * the configuration information for the specified DMA Stream.
1340 * @param SrcAddress: The source memory Buffer address
1341 * @param DstAddress: The destination memory Buffer address
1342 * @param DataLength: The length of data to be transferred from source to destination
1343 * @retval None
1344 */
DMA_SetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)1345 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
1346 {
1347 /* calculate DMA base and stream number */
1348 DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
1349
1350 /* Clear the DMAMUX synchro overrun flag */
1351 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
1352
1353 if(hdma->DMAmuxRequestGen != 0U)
1354 {
1355 /* Clear the DMAMUX request generator overrun flag */
1356 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
1357 }
1358 /* Clear all interrupt flags at correct offset within the register */
1359 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
1360
1361 /* Clear DBM bit */
1362 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
1363
1364 /* Configure DMA Stream data length */
1365 ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = DataLength;
1366
1367 /* Peripheral to Memory */
1368 if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
1369 {
1370 /* Configure DMA Stream destination address */
1371 ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = DstAddress;
1372
1373 /* Configure DMA Stream source address */
1374 ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = SrcAddress;
1375 }
1376 /* Memory to Peripheral */
1377 else
1378 {
1379 /* Configure DMA Stream source address */
1380 ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = SrcAddress;
1381
1382 /* Configure DMA Stream destination address */
1383 ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = DstAddress;
1384 }
1385 }
1386
1387 /**
1388 * @brief Returns the DMA Stream base address depending on stream number
1389 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1390 * the configuration information for the specified DMA Stream.
1391 * @retval Stream base address
1392 */
DMA_CalcBaseAndBitshift(DMA_HandleTypeDef * hdma)1393 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
1394 {
1395 uint32_t stream_number = (((uint32_t)((uint32_t *)hdma->Instance) & 0xFFU) - 16U) / 24U;
1396
1397 /* lookup table for necessary bitshift of flags within status registers */
1398 static const uint8_t flagBitshiftOffset[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U};
1399 hdma->StreamIndex = flagBitshiftOffset[stream_number & 0x7U];
1400
1401 if (stream_number > 3U)
1402 {
1403 /* return pointer to HISR and HIFCR */
1404 hdma->StreamBaseAddress = (((uint32_t)((uint32_t *)hdma->Instance) & (uint32_t)(~0x3FFU)) + 4U);
1405 }
1406 else
1407 {
1408 /* return pointer to LISR and LIFCR */
1409 hdma->StreamBaseAddress = ((uint32_t)((uint32_t *)hdma->Instance) & (uint32_t)(~0x3FFU));
1410 }
1411
1412 return hdma->StreamBaseAddress;
1413 }
1414
1415 /**
1416 * @brief Check compatibility between FIFO threshold level and size of the memory burst
1417 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1418 * the configuration information for the specified DMA Stream.
1419 * @retval HAL status
1420 */
DMA_CheckFifoParam(DMA_HandleTypeDef * hdma)1421 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma)
1422 {
1423 HAL_StatusTypeDef status = HAL_OK;
1424
1425 /* Memory Data size equal to Byte */
1426 if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_BYTE)
1427 {
1428 switch (hdma->Init.FIFOThreshold)
1429 {
1430 case DMA_FIFO_THRESHOLD_1QUARTERFULL:
1431 case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
1432
1433 if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
1434 {
1435 status = HAL_ERROR;
1436 }
1437 break;
1438
1439 case DMA_FIFO_THRESHOLD_HALFFULL:
1440 if (hdma->Init.MemBurst == DMA_MBURST_INC16)
1441 {
1442 status = HAL_ERROR;
1443 }
1444 break;
1445
1446 case DMA_FIFO_THRESHOLD_FULL:
1447 break;
1448
1449 default:
1450 break;
1451 }
1452 }
1453
1454 /* Memory Data size equal to Half-Word */
1455 else if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
1456 {
1457 switch (hdma->Init.FIFOThreshold)
1458 {
1459 case DMA_FIFO_THRESHOLD_1QUARTERFULL:
1460 case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
1461 status = HAL_ERROR;
1462 break;
1463
1464 case DMA_FIFO_THRESHOLD_HALFFULL:
1465 if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
1466 {
1467 status = HAL_ERROR;
1468 }
1469 break;
1470
1471 case DMA_FIFO_THRESHOLD_FULL:
1472 if (hdma->Init.MemBurst == DMA_MBURST_INC16)
1473 {
1474 status = HAL_ERROR;
1475 }
1476 break;
1477
1478 default:
1479 break;
1480 }
1481 }
1482
1483 /* Memory Data size equal to Word */
1484 else
1485 {
1486 switch (hdma->Init.FIFOThreshold)
1487 {
1488 case DMA_FIFO_THRESHOLD_1QUARTERFULL:
1489 case DMA_FIFO_THRESHOLD_HALFFULL:
1490 case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
1491 status = HAL_ERROR;
1492 break;
1493
1494 case DMA_FIFO_THRESHOLD_FULL:
1495 if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
1496 {
1497 status = HAL_ERROR;
1498 }
1499 break;
1500
1501 default:
1502 break;
1503 }
1504 }
1505
1506 return status;
1507 }
1508
1509 /**
1510 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number
1511 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1512 * the configuration information for the specified DMA Stream.
1513 * @retval HAL status
1514 */
DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef * hdma)1515 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
1516 {
1517 uint32_t stream_number;
1518 uint32_t stream_baseaddress = (uint32_t)((uint32_t *)hdma->Instance);
1519 /*DMA1/DMA2 Streams are connected to DMAMUX1 channels*/
1520 stream_number = (((uint32_t)((uint32_t *)hdma->Instance) & 0xFFU) - 16U) / 24U;
1521
1522 if ((stream_baseaddress <= ((uint32_t)DMA2_Stream7)) && \
1523 (stream_baseaddress >= ((uint32_t)DMA2_Stream0)))
1524 {
1525 stream_number += 8U;
1526 }
1527
1528 hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_Channel0) + (stream_number * 4U)));
1529 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
1530 hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU);
1531
1532 }
1533
1534 /**
1535 * @brief Updates the DMA handle with the DMAMUX request generator params
1536 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
1537 * the configuration information for the specified DMA Stream.
1538 * @retval HAL status
1539 */
DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef * hdma)1540 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
1541 {
1542 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
1543
1544 if ((request >= DMA_REQUEST_GENERATOR0) && (request <= DMA_REQUEST_GENERATOR7))
1545 {
1546 /*DMA1 and DMA2 Streams use DMAMUX1 request generator blocks*/
1547 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
1548 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
1549 hdma->DMAmuxRequestGenStatusMask = 1UL << (request - 1U);
1550 }
1551 }
1552
1553 /**
1554 * @}
1555 */
1556
1557 #endif /* HAL_DMA_MODULE_ENABLED */
1558 /**
1559 * @}
1560 */
1561
1562 /**
1563 * @}
1564 */
1565