STM32H735xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h7xx_hal_dma.c 00004 * @author MCD Application Team 00005 * @brief DMA HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of the Direct Memory Access (DMA) peripheral: 00008 * + Initialization and de-initialization functions 00009 * + IO operation functions 00010 * + Peripheral State and errors functions 00011 ****************************************************************************** 00012 * @attention 00013 * 00014 * Copyright (c) 2017 STMicroelectronics. 00015 * All rights reserved. 00016 * 00017 * This software is licensed under terms that can be found in the LICENSE file 00018 * in the root directory of this software component. 00019 * If no LICENSE file comes with this software, it is provided AS-IS. 00020 * 00021 ****************************************************************************** 00022 @verbatim 00023 ============================================================================== 00024 ##### How to use this driver ##### 00025 ============================================================================== 00026 [..] 00027 (#) Enable and configure the peripheral to be connected to the DMA Stream 00028 (except for internal SRAM/FLASH memories: no initialization is 00029 necessary) please refer to Reference manual for connection between peripherals 00030 and DMA requests . 00031 00032 (#) For a given Stream, program the required configuration through the following parameters: 00033 Transfer Direction, Source and Destination data formats, 00034 Circular, Normal or peripheral flow control mode, Stream Priority level, 00035 Source and Destination Increment mode, FIFO mode and its Threshold (if needed), 00036 Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function. 00037 00038 *** Polling mode IO operation *** 00039 ================================= 00040 [..] 00041 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source 00042 address and destination address and the Length of data to be transferred 00043 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this 00044 case a fixed Timeout can be configured by User depending from his application. 00045 00046 *** Interrupt mode IO operation *** 00047 =================================== 00048 [..] 00049 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority() 00050 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ() 00051 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of 00052 Source address and destination address and the Length of data to be transferred. In this 00053 case the DMA interrupt is configured 00054 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine 00055 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can 00056 add his own function by customization of function pointer XferCpltCallback and 00057 XferErrorCallback (i.e a member of DMA handle structure). 00058 [..] 00059 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error 00060 detection. 00061 00062 (#) Use HAL_DMA_Abort() function to abort the current transfer 00063 00064 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed. 00065 00066 -@- The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is 00067 possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set 00068 Half-Word data size for the peripheral to access its data register and set Word data size 00069 for the Memory to gain in access time. Each two half words will be packed and written in 00070 a single access to a Word in the Memory). 00071 00072 -@- When FIFO is disabled, it is not allowed to configure different Data Sizes for Source 00073 and Destination. In this case the Peripheral Data Size will be applied to both Source 00074 and Destination. 00075 00076 *** DMA HAL driver macros list *** 00077 ============================================= 00078 [..] 00079 Below the list of most used macros in DMA HAL driver. 00080 00081 (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream. 00082 (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream. 00083 (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level. 00084 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts. 00085 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts. 00086 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream interrupt has occurred or not. 00087 00088 [..] 00089 (@) You can refer to the DMA HAL driver header file for more useful macros. 00090 00091 @endverbatim 00092 */ 00093 00094 /* Includes ------------------------------------------------------------------*/ 00095 #include "stm32h7xx_hal.h" 00096 00097 /** @addtogroup STM32H7xx_HAL_Driver 00098 * @{ 00099 */ 00100 00101 /** @defgroup DMA DMA 00102 * @brief DMA HAL module driver 00103 * @{ 00104 */ 00105 00106 #ifdef HAL_DMA_MODULE_ENABLED 00107 00108 /* Private types -------------------------------------------------------------*/ 00109 typedef struct 00110 { 00111 __IO uint32_t ISR; /*!< DMA interrupt status register */ 00112 __IO uint32_t Reserved0; 00113 __IO uint32_t IFCR; /*!< DMA interrupt flag clear register */ 00114 } DMA_Base_Registers; 00115 00116 typedef struct 00117 { 00118 __IO uint32_t ISR; /*!< BDMA interrupt status register */ 00119 __IO uint32_t IFCR; /*!< BDMA interrupt flag clear register */ 00120 } BDMA_Base_Registers; 00121 00122 /* Private variables ---------------------------------------------------------*/ 00123 /* Private constants ---------------------------------------------------------*/ 00124 /** @addtogroup DMA_Private_Constants 00125 * @{ 00126 */ 00127 #define HAL_TIMEOUT_DMA_ABORT (5U) /* 5 ms */ 00128 00129 #define BDMA_PERIPH_TO_MEMORY (0x00000000U) /*!< Peripheral to memory direction */ 00130 #define BDMA_MEMORY_TO_PERIPH ((uint32_t)BDMA_CCR_DIR) /*!< Memory to peripheral direction */ 00131 #define BDMA_MEMORY_TO_MEMORY ((uint32_t)BDMA_CCR_MEM2MEM) /*!< Memory to memory direction */ 00132 00133 /* DMA to BDMA conversion */ 00134 #define DMA_TO_BDMA_DIRECTION(__DMA_DIRECTION__) (((__DMA_DIRECTION__) == DMA_MEMORY_TO_PERIPH)? BDMA_MEMORY_TO_PERIPH: \ 00135 ((__DMA_DIRECTION__) == DMA_MEMORY_TO_MEMORY)? BDMA_MEMORY_TO_MEMORY: \ 00136 BDMA_PERIPH_TO_MEMORY) 00137 00138 #define DMA_TO_BDMA_PERIPHERAL_INC(__DMA_PERIPHERAL_INC__) ((__DMA_PERIPHERAL_INC__) >> 3U) 00139 #define DMA_TO_BDMA_MEMORY_INC(__DMA_MEMORY_INC__) ((__DMA_MEMORY_INC__) >> 3U) 00140 00141 #define DMA_TO_BDMA_PDATA_SIZE(__DMA_PDATA_SIZE__) ((__DMA_PDATA_SIZE__) >> 3U) 00142 #define DMA_TO_BDMA_MDATA_SIZE(__DMA_MDATA_SIZE__) ((__DMA_MDATA_SIZE__) >> 3U) 00143 00144 #define DMA_TO_BDMA_MODE(__DMA_MODE__) ((__DMA_MODE__) >> 3U) 00145 00146 #define DMA_TO_BDMA_PRIORITY(__DMA_PRIORITY__) ((__DMA_PRIORITY__) >> 4U) 00147 00148 #if defined(UART9) 00149 #define IS_DMA_UART_USART_REQUEST(__REQUEST__) ((((__REQUEST__) >= DMA_REQUEST_USART1_RX) && ((__REQUEST__) <= DMA_REQUEST_USART3_TX)) || \ 00150 (((__REQUEST__) >= DMA_REQUEST_UART4_RX) && ((__REQUEST__) <= DMA_REQUEST_UART5_TX )) || \ 00151 (((__REQUEST__) >= DMA_REQUEST_USART6_RX) && ((__REQUEST__) <= DMA_REQUEST_USART6_TX)) || \ 00152 (((__REQUEST__) >= DMA_REQUEST_UART7_RX) && ((__REQUEST__) <= DMA_REQUEST_UART8_TX )) || \ 00153 (((__REQUEST__) >= DMA_REQUEST_UART9_RX) && ((__REQUEST__) <= DMA_REQUEST_USART10_TX ))) 00154 #else 00155 #define IS_DMA_UART_USART_REQUEST(__REQUEST__) ((((__REQUEST__) >= DMA_REQUEST_USART1_RX) && ((__REQUEST__) <= DMA_REQUEST_USART3_TX)) || \ 00156 (((__REQUEST__) >= DMA_REQUEST_UART4_RX) && ((__REQUEST__) <= DMA_REQUEST_UART5_TX )) || \ 00157 (((__REQUEST__) >= DMA_REQUEST_USART6_RX) && ((__REQUEST__) <= DMA_REQUEST_USART6_TX)) || \ 00158 (((__REQUEST__) >= DMA_REQUEST_UART7_RX) && ((__REQUEST__) <= DMA_REQUEST_UART8_TX ))) 00159 00160 #endif 00161 /** 00162 * @} 00163 */ 00164 /* Private macros ------------------------------------------------------------*/ 00165 /* Private functions ---------------------------------------------------------*/ 00166 /** @addtogroup DMA_Private_Functions 00167 * @{ 00168 */ 00169 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); 00170 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma); 00171 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma); 00172 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma); 00173 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma); 00174 00175 /** 00176 * @} 00177 */ 00178 00179 /* Exported functions ---------------------------------------------------------*/ 00180 /** @addtogroup DMA_Exported_Functions 00181 * @{ 00182 */ 00183 00184 /** @addtogroup DMA_Exported_Functions_Group1 00185 * 00186 @verbatim 00187 =============================================================================== 00188 ##### Initialization and de-initialization functions ##### 00189 =============================================================================== 00190 [..] 00191 This section provides functions allowing to initialize the DMA Stream source 00192 and destination incrementation and data sizes, transfer direction, 00193 circular/normal mode selection, memory-to-memory mode selection and Stream priority value. 00194 [..] 00195 The HAL_DMA_Init() function follows the DMA configuration procedures as described in 00196 reference manual. 00197 The HAL_DMA_DeInit function allows to deinitialize the DMA stream. 00198 00199 @endverbatim 00200 * @{ 00201 */ 00202 00203 /** 00204 * @brief Initialize the DMA according to the specified 00205 * parameters in the DMA_InitTypeDef and create the associated handle. 00206 * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains 00207 * the configuration information for the specified DMA Stream. 00208 * @retval HAL status 00209 */ 00210 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma) 00211 { 00212 uint32_t registerValue; 00213 uint32_t tickstart = HAL_GetTick(); 00214 DMA_Base_Registers *regs_dma; 00215 BDMA_Base_Registers *regs_bdma; 00216 00217 /* Check the DMA peripheral handle */ 00218 if(hdma == NULL) 00219 { 00220 return HAL_ERROR; 00221 } 00222 00223 /* Check the parameters */ 00224 assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); 00225 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction)); 00226 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc)); 00227 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc)); 00228 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment)); 00229 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment)); 00230 assert_param(IS_DMA_MODE(hdma->Init.Mode)); 00231 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority)); 00232 00233 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 00234 { 00235 assert_param(IS_DMA_REQUEST(hdma->Init.Request)); 00236 assert_param(IS_DMA_FIFO_MODE_STATE(hdma->Init.FIFOMode)); 00237 /* Check the memory burst, peripheral burst and FIFO threshold parameters only 00238 when FIFO mode is enabled */ 00239 if(hdma->Init.FIFOMode != DMA_FIFOMODE_DISABLE) 00240 { 00241 assert_param(IS_DMA_FIFO_THRESHOLD(hdma->Init.FIFOThreshold)); 00242 assert_param(IS_DMA_MEMORY_BURST(hdma->Init.MemBurst)); 00243 assert_param(IS_DMA_PERIPHERAL_BURST(hdma->Init.PeriphBurst)); 00244 } 00245 00246 /* Change DMA peripheral state */ 00247 hdma->State = HAL_DMA_STATE_BUSY; 00248 00249 /* Allocate lock resource */ 00250 __HAL_UNLOCK(hdma); 00251 00252 /* Disable the peripheral */ 00253 __HAL_DMA_DISABLE(hdma); 00254 00255 /* Check if the DMA Stream is effectively disabled */ 00256 while((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U) 00257 { 00258 /* Check for the Timeout */ 00259 if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT) 00260 { 00261 /* Update error code */ 00262 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT; 00263 00264 /* Change the DMA state */ 00265 hdma->State = HAL_DMA_STATE_ERROR; 00266 00267 return HAL_ERROR; 00268 } 00269 } 00270 00271 /* Get the CR register value */ 00272 registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->CR; 00273 00274 /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */ 00275 registerValue &= ((uint32_t)~(DMA_SxCR_MBURST | DMA_SxCR_PBURST | \ 00276 DMA_SxCR_PL | DMA_SxCR_MSIZE | DMA_SxCR_PSIZE | \ 00277 DMA_SxCR_MINC | DMA_SxCR_PINC | DMA_SxCR_CIRC | \ 00278 DMA_SxCR_DIR | DMA_SxCR_CT | DMA_SxCR_DBM)); 00279 00280 /* Prepare the DMA Stream configuration */ 00281 registerValue |= hdma->Init.Direction | 00282 hdma->Init.PeriphInc | hdma->Init.MemInc | 00283 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | 00284 hdma->Init.Mode | hdma->Init.Priority; 00285 00286 /* the Memory burst and peripheral burst are not used when the FIFO is disabled */ 00287 if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE) 00288 { 00289 /* Get memory burst and peripheral burst */ 00290 registerValue |= hdma->Init.MemBurst | hdma->Init.PeriphBurst; 00291 } 00292 00293 /* Work around for Errata 2.22: UART/USART- DMA transfer lock: DMA stream could be 00294 lock when transferring data to/from USART/UART */ 00295 #if (STM32H7_DEV_ID == 0x450UL) 00296 if((DBGMCU->IDCODE & 0xFFFF0000U) >= 0x20000000U) 00297 { 00298 #endif /* STM32H7_DEV_ID == 0x450UL */ 00299 if(IS_DMA_UART_USART_REQUEST(hdma->Init.Request) != 0U) 00300 { 00301 registerValue |= DMA_SxCR_TRBUFF; 00302 } 00303 #if (STM32H7_DEV_ID == 0x450UL) 00304 } 00305 #endif /* STM32H7_DEV_ID == 0x450UL */ 00306 00307 /* Write to DMA Stream CR register */ 00308 ((DMA_Stream_TypeDef *)hdma->Instance)->CR = registerValue; 00309 00310 /* Get the FCR register value */ 00311 registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->FCR; 00312 00313 /* Clear Direct mode and FIFO threshold bits */ 00314 registerValue &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); 00315 00316 /* Prepare the DMA Stream FIFO configuration */ 00317 registerValue |= hdma->Init.FIFOMode; 00318 00319 /* the FIFO threshold is not used when the FIFO mode is disabled */ 00320 if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE) 00321 { 00322 /* Get the FIFO threshold */ 00323 registerValue |= hdma->Init.FIFOThreshold; 00324 00325 /* Check compatibility between FIFO threshold level and size of the memory burst */ 00326 /* for INCR4, INCR8, INCR16 */ 00327 if(hdma->Init.MemBurst != DMA_MBURST_SINGLE) 00328 { 00329 if (DMA_CheckFifoParam(hdma) != HAL_OK) 00330 { 00331 /* Update error code */ 00332 hdma->ErrorCode = HAL_DMA_ERROR_PARAM; 00333 00334 /* Change the DMA state */ 00335 hdma->State = HAL_DMA_STATE_READY; 00336 00337 return HAL_ERROR; 00338 } 00339 } 00340 } 00341 00342 /* Write to DMA Stream FCR */ 00343 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = registerValue; 00344 00345 /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate 00346 DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */ 00347 regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma); 00348 00349 /* Clear all interrupt flags */ 00350 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU); 00351 } 00352 else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */ 00353 { 00354 if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U) 00355 { 00356 /* Check the request parameter */ 00357 assert_param(IS_BDMA_REQUEST(hdma->Init.Request)); 00358 } 00359 00360 /* Change DMA peripheral state */ 00361 hdma->State = HAL_DMA_STATE_BUSY; 00362 00363 /* Allocate lock resource */ 00364 __HAL_UNLOCK(hdma); 00365 00366 /* Get the CR register value */ 00367 registerValue = ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR; 00368 00369 /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, MEM2MEM, DBM and CT bits */ 00370 registerValue &= ((uint32_t)~(BDMA_CCR_PL | BDMA_CCR_MSIZE | BDMA_CCR_PSIZE | \ 00371 BDMA_CCR_MINC | BDMA_CCR_PINC | BDMA_CCR_CIRC | \ 00372 BDMA_CCR_DIR | BDMA_CCR_MEM2MEM | BDMA_CCR_DBM | \ 00373 BDMA_CCR_CT)); 00374 00375 /* Prepare the DMA Channel configuration */ 00376 registerValue |= DMA_TO_BDMA_DIRECTION(hdma->Init.Direction) | 00377 DMA_TO_BDMA_PERIPHERAL_INC(hdma->Init.PeriphInc) | 00378 DMA_TO_BDMA_MEMORY_INC(hdma->Init.MemInc) | 00379 DMA_TO_BDMA_PDATA_SIZE(hdma->Init.PeriphDataAlignment) | 00380 DMA_TO_BDMA_MDATA_SIZE(hdma->Init.MemDataAlignment) | 00381 DMA_TO_BDMA_MODE(hdma->Init.Mode) | 00382 DMA_TO_BDMA_PRIORITY(hdma->Init.Priority); 00383 00384 /* Write to DMA Channel CR register */ 00385 ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR = registerValue; 00386 00387 /* calculation of the channel index */ 00388 hdma->StreamIndex = (((uint32_t)((uint32_t*)hdma->Instance) - (uint32_t)BDMA_Channel0) / ((uint32_t)BDMA_Channel1 - (uint32_t)BDMA_Channel0)) << 2U; 00389 00390 /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate 00391 DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */ 00392 regs_bdma = (BDMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma); 00393 00394 /* Clear all interrupt flags */ 00395 regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU)); 00396 } 00397 else 00398 { 00399 hdma->ErrorCode = HAL_DMA_ERROR_PARAM; 00400 hdma->State = HAL_DMA_STATE_ERROR; 00401 00402 return HAL_ERROR; 00403 } 00404 00405 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 00406 { 00407 /* Initialize parameters for DMAMUX channel : 00408 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask 00409 */ 00410 DMA_CalcDMAMUXChannelBaseAndMask(hdma); 00411 00412 if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) 00413 { 00414 /* if memory to memory force the request to 0*/ 00415 hdma->Init.Request = DMA_REQUEST_MEM2MEM; 00416 } 00417 00418 /* Set peripheral request to DMAMUX channel */ 00419 hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID); 00420 00421 /* Clear the DMAMUX synchro overrun flag */ 00422 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; 00423 00424 /* Initialize parameters for DMAMUX request generator : 00425 if the DMA request is DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR7 00426 */ 00427 if((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7)) 00428 { 00429 /* Initialize parameters for DMAMUX request generator : 00430 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */ 00431 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); 00432 00433 /* Reset the DMAMUX request generator register */ 00434 hdma->DMAmuxRequestGen->RGCR = 0U; 00435 00436 /* Clear the DMAMUX request generator overrun flag */ 00437 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; 00438 } 00439 else 00440 { 00441 hdma->DMAmuxRequestGen = 0U; 00442 hdma->DMAmuxRequestGenStatus = 0U; 00443 hdma->DMAmuxRequestGenStatusMask = 0U; 00444 } 00445 } 00446 00447 /* Initialize the error code */ 00448 hdma->ErrorCode = HAL_DMA_ERROR_NONE; 00449 00450 /* Initialize the DMA state */ 00451 hdma->State = HAL_DMA_STATE_READY; 00452 00453 return HAL_OK; 00454 } 00455 00456 /** 00457 * @brief DeInitializes the DMA peripheral 00458 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 00459 * the configuration information for the specified DMA Stream. 00460 * @retval HAL status 00461 */ 00462 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) 00463 { 00464 DMA_Base_Registers *regs_dma; 00465 BDMA_Base_Registers *regs_bdma; 00466 00467 /* Check the DMA peripheral handle */ 00468 if(hdma == NULL) 00469 { 00470 return HAL_ERROR; 00471 } 00472 00473 /* Disable the selected DMA Streamx */ 00474 __HAL_DMA_DISABLE(hdma); 00475 00476 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 00477 { 00478 /* Reset DMA Streamx control register */ 00479 ((DMA_Stream_TypeDef *)hdma->Instance)->CR = 0U; 00480 00481 /* Reset DMA Streamx number of data to transfer register */ 00482 ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = 0U; 00483 00484 /* Reset DMA Streamx peripheral address register */ 00485 ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = 0U; 00486 00487 /* Reset DMA Streamx memory 0 address register */ 00488 ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = 0U; 00489 00490 /* Reset DMA Streamx memory 1 address register */ 00491 ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = 0U; 00492 00493 /* Reset DMA Streamx FIFO control register */ 00494 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = (uint32_t)0x00000021U; 00495 00496 /* Get DMA steam Base Address */ 00497 regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma); 00498 00499 /* Clear all interrupt flags at correct offset within the register */ 00500 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU); 00501 } 00502 else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */ 00503 { 00504 /* Reset DMA Channel control register */ 00505 ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR = 0U; 00506 00507 /* Reset DMA Channel Number of Data to Transfer register */ 00508 ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = 0U; 00509 00510 /* Reset DMA Channel peripheral address register */ 00511 ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = 0U; 00512 00513 /* Reset DMA Channel memory 0 address register */ 00514 ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = 0U; 00515 00516 /* Reset DMA Channel memory 1 address register */ 00517 ((BDMA_Channel_TypeDef *)hdma->Instance)->CM1AR = 0U; 00518 00519 /* Get DMA steam Base Address */ 00520 regs_bdma = (BDMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma); 00521 00522 /* Clear all interrupt flags at correct offset within the register */ 00523 regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU)); 00524 } 00525 else 00526 { 00527 /* Return error status */ 00528 return HAL_ERROR; 00529 } 00530 00531 #if defined (BDMA1) /* No DMAMUX available for BDMA1 available on STM32H7Ax/Bx devices only */ 00532 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 00533 #endif /* BDMA1 */ 00534 { 00535 /* Initialize parameters for DMAMUX channel : 00536 DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */ 00537 DMA_CalcDMAMUXChannelBaseAndMask(hdma); 00538 00539 if(hdma->DMAmuxChannel != 0U) 00540 { 00541 /* Resett he DMAMUX channel that corresponds to the DMA stream */ 00542 hdma->DMAmuxChannel->CCR = 0U; 00543 00544 /* Clear the DMAMUX synchro overrun flag */ 00545 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; 00546 } 00547 00548 if((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7)) 00549 { 00550 /* Initialize parameters for DMAMUX request generator : 00551 DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */ 00552 DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); 00553 00554 /* Reset the DMAMUX request generator register */ 00555 hdma->DMAmuxRequestGen->RGCR = 0U; 00556 00557 /* Clear the DMAMUX request generator overrun flag */ 00558 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; 00559 } 00560 00561 hdma->DMAmuxRequestGen = 0U; 00562 hdma->DMAmuxRequestGenStatus = 0U; 00563 hdma->DMAmuxRequestGenStatusMask = 0U; 00564 } 00565 00566 00567 /* Clean callbacks */ 00568 hdma->XferCpltCallback = NULL; 00569 hdma->XferHalfCpltCallback = NULL; 00570 hdma->XferM1CpltCallback = NULL; 00571 hdma->XferM1HalfCpltCallback = NULL; 00572 hdma->XferErrorCallback = NULL; 00573 hdma->XferAbortCallback = NULL; 00574 00575 /* Initialize the error code */ 00576 hdma->ErrorCode = HAL_DMA_ERROR_NONE; 00577 00578 /* Initialize the DMA state */ 00579 hdma->State = HAL_DMA_STATE_RESET; 00580 00581 /* Release Lock */ 00582 __HAL_UNLOCK(hdma); 00583 00584 return HAL_OK; 00585 } 00586 00587 /** 00588 * @} 00589 */ 00590 00591 /** @addtogroup DMA_Exported_Functions_Group2 00592 * 00593 @verbatim 00594 =============================================================================== 00595 ##### IO operation functions ##### 00596 =============================================================================== 00597 [..] This section provides functions allowing to: 00598 (+) Configure the source, destination address and data length and Start DMA transfer 00599 (+) Configure the source, destination address and data length and 00600 Start DMA transfer with interrupt 00601 (+) Register and Unregister DMA callbacks 00602 (+) Abort DMA transfer 00603 (+) Poll for transfer complete 00604 (+) Handle DMA interrupt request 00605 00606 @endverbatim 00607 * @{ 00608 */ 00609 00610 /** 00611 * @brief Starts the DMA Transfer. 00612 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains 00613 * the configuration information for the specified DMA Stream. 00614 * @param SrcAddress: The source memory Buffer address 00615 * @param DstAddress: The destination memory Buffer address 00616 * @param DataLength: The length of data to be transferred from source to destination 00617 * @retval HAL status 00618 */ 00619 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) 00620 { 00621 HAL_StatusTypeDef status = HAL_OK; 00622 00623 /* Check the parameters */ 00624 assert_param(IS_DMA_BUFFER_SIZE(DataLength)); 00625 00626 /* Check the DMA peripheral handle */ 00627 if(hdma == NULL) 00628 { 00629 return HAL_ERROR; 00630 } 00631 00632 /* Process locked */ 00633 __HAL_LOCK(hdma); 00634 00635 if(HAL_DMA_STATE_READY == hdma->State) 00636 { 00637 /* Change DMA peripheral state */ 00638 hdma->State = HAL_DMA_STATE_BUSY; 00639 00640 /* Initialize the error code */ 00641 hdma->ErrorCode = HAL_DMA_ERROR_NONE; 00642 00643 /* Disable the peripheral */ 00644 __HAL_DMA_DISABLE(hdma); 00645 00646 /* Configure the source, destination address and the data length */ 00647 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); 00648 00649 /* Enable the Peripheral */ 00650 __HAL_DMA_ENABLE(hdma); 00651 } 00652 else 00653 { 00654 /* Set the error code to busy */ 00655 hdma->ErrorCode = HAL_DMA_ERROR_BUSY; 00656 00657 /* Process unlocked */ 00658 __HAL_UNLOCK(hdma); 00659 00660 /* Return error status */ 00661 status = HAL_ERROR; 00662 } 00663 return status; 00664 } 00665 00666 /** 00667 * @brief Start the DMA Transfer with interrupt enabled. 00668 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 00669 * the configuration information for the specified DMA Stream. 00670 * @param SrcAddress: The source memory Buffer address 00671 * @param DstAddress: The destination memory Buffer address 00672 * @param DataLength: The length of data to be transferred from source to destination 00673 * @retval HAL status 00674 */ 00675 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) 00676 { 00677 HAL_StatusTypeDef status = HAL_OK; 00678 00679 /* Check the parameters */ 00680 assert_param(IS_DMA_BUFFER_SIZE(DataLength)); 00681 00682 /* Check the DMA peripheral handle */ 00683 if(hdma == NULL) 00684 { 00685 return HAL_ERROR; 00686 } 00687 00688 /* Process locked */ 00689 __HAL_LOCK(hdma); 00690 00691 if(HAL_DMA_STATE_READY == hdma->State) 00692 { 00693 /* Change DMA peripheral state */ 00694 hdma->State = HAL_DMA_STATE_BUSY; 00695 00696 /* Initialize the error code */ 00697 hdma->ErrorCode = HAL_DMA_ERROR_NONE; 00698 00699 /* Disable the peripheral */ 00700 __HAL_DMA_DISABLE(hdma); 00701 00702 /* Configure the source, destination address and the data length */ 00703 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); 00704 00705 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 00706 { 00707 /* Enable Common interrupts*/ 00708 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)); 00709 00710 if(hdma->XferHalfCpltCallback != NULL) 00711 { 00712 /* Enable Half Transfer IT if corresponding Callback is set */ 00713 ((DMA_Stream_TypeDef *)hdma->Instance)->CR |= DMA_IT_HT; 00714 } 00715 } 00716 else /* BDMA channel */ 00717 { 00718 /* Enable Common interrupts */ 00719 MODIFY_REG(((BDMA_Channel_TypeDef *)hdma->Instance)->CCR, (BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE), (BDMA_CCR_TCIE | BDMA_CCR_TEIE)); 00720 00721 if(hdma->XferHalfCpltCallback != NULL) 00722 { 00723 /*Enable Half Transfer IT if corresponding Callback is set */ 00724 ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR |= BDMA_CCR_HTIE; 00725 } 00726 } 00727 00728 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 00729 { 00730 /* Check if DMAMUX Synchronization is enabled */ 00731 if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U) 00732 { 00733 /* Enable DMAMUX sync overrun IT*/ 00734 hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE; 00735 } 00736 00737 if(hdma->DMAmuxRequestGen != 0U) 00738 { 00739 /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/ 00740 /* enable the request gen overrun IT */ 00741 hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; 00742 } 00743 } 00744 00745 /* Enable the Peripheral */ 00746 __HAL_DMA_ENABLE(hdma); 00747 } 00748 else 00749 { 00750 /* Set the error code to busy */ 00751 hdma->ErrorCode = HAL_DMA_ERROR_BUSY; 00752 00753 /* Process unlocked */ 00754 __HAL_UNLOCK(hdma); 00755 00756 /* Return error status */ 00757 status = HAL_ERROR; 00758 } 00759 00760 return status; 00761 } 00762 00763 /** 00764 * @brief Aborts the DMA Transfer. 00765 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains 00766 * the configuration information for the specified DMA Stream. 00767 * 00768 * @note After disabling a DMA Stream, a check for wait until the DMA Stream is 00769 * effectively disabled is added. If a Stream is disabled 00770 * while a data transfer is ongoing, the current data will be transferred 00771 * and the Stream will be effectively disabled only after the transfer of 00772 * this single data is finished. 00773 * @retval HAL status 00774 */ 00775 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) 00776 { 00777 /* calculate DMA base and stream number */ 00778 DMA_Base_Registers *regs_dma; 00779 BDMA_Base_Registers *regs_bdma; 00780 const __IO uint32_t *enableRegister; 00781 00782 uint32_t tickstart = HAL_GetTick(); 00783 00784 /* Check the DMA peripheral handle */ 00785 if(hdma == NULL) 00786 { 00787 return HAL_ERROR; 00788 } 00789 00790 /* Check the DMA peripheral state */ 00791 if(hdma->State != HAL_DMA_STATE_BUSY) 00792 { 00793 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; 00794 00795 /* Process Unlocked */ 00796 __HAL_UNLOCK(hdma); 00797 00798 return HAL_ERROR; 00799 } 00800 else 00801 { 00802 /* Disable all the transfer interrupts */ 00803 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 00804 { 00805 /* Disable DMA All Interrupts */ 00806 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT); 00807 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE); 00808 00809 enableRegister = (__IO uint32_t *)(&(((DMA_Stream_TypeDef *)hdma->Instance)->CR)); 00810 } 00811 else /* BDMA channel */ 00812 { 00813 /* Disable DMA All Interrupts */ 00814 ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE); 00815 00816 enableRegister = (__IO uint32_t *)(&(((BDMA_Channel_TypeDef *)hdma->Instance)->CCR)); 00817 } 00818 00819 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 00820 { 00821 /* disable the DMAMUX sync overrun IT */ 00822 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; 00823 } 00824 00825 /* Disable the stream */ 00826 __HAL_DMA_DISABLE(hdma); 00827 00828 /* Check if the DMA Stream is effectively disabled */ 00829 while(((*enableRegister) & DMA_SxCR_EN) != 0U) 00830 { 00831 /* Check for the Timeout */ 00832 if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT) 00833 { 00834 /* Update error code */ 00835 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT; 00836 00837 /* Change the DMA state */ 00838 hdma->State = HAL_DMA_STATE_ERROR; 00839 00840 /* Process Unlocked */ 00841 __HAL_UNLOCK(hdma); 00842 00843 return HAL_ERROR; 00844 } 00845 } 00846 00847 /* Clear all interrupt flags at correct offset within the register */ 00848 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 00849 { 00850 regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress; 00851 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU); 00852 } 00853 else /* BDMA channel */ 00854 { 00855 regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress; 00856 regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU)); 00857 } 00858 00859 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 00860 { 00861 /* Clear the DMAMUX synchro overrun flag */ 00862 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; 00863 00864 if(hdma->DMAmuxRequestGen != 0U) 00865 { 00866 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT */ 00867 /* disable the request gen overrun IT */ 00868 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; 00869 00870 /* Clear the DMAMUX request generator overrun flag */ 00871 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; 00872 } 00873 } 00874 00875 /* Change the DMA state */ 00876 hdma->State = HAL_DMA_STATE_READY; 00877 00878 /* Process Unlocked */ 00879 __HAL_UNLOCK(hdma); 00880 } 00881 00882 return HAL_OK; 00883 } 00884 00885 /** 00886 * @brief Aborts the DMA Transfer in Interrupt mode. 00887 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains 00888 * the configuration information for the specified DMA Stream. 00889 * @retval HAL status 00890 */ 00891 HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) 00892 { 00893 BDMA_Base_Registers *regs_bdma; 00894 00895 /* Check the DMA peripheral handle */ 00896 if(hdma == NULL) 00897 { 00898 return HAL_ERROR; 00899 } 00900 00901 if(hdma->State != HAL_DMA_STATE_BUSY) 00902 { 00903 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; 00904 return HAL_ERROR; 00905 } 00906 else 00907 { 00908 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 00909 { 00910 /* Set Abort State */ 00911 hdma->State = HAL_DMA_STATE_ABORT; 00912 00913 /* Disable the stream */ 00914 __HAL_DMA_DISABLE(hdma); 00915 } 00916 else /* BDMA channel */ 00917 { 00918 /* Disable DMA All Interrupts */ 00919 ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE); 00920 00921 /* Disable the channel */ 00922 __HAL_DMA_DISABLE(hdma); 00923 00924 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 00925 { 00926 /* disable the DMAMUX sync overrun IT */ 00927 hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; 00928 00929 /* Clear all flags */ 00930 regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress; 00931 regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU)); 00932 00933 /* Clear the DMAMUX synchro overrun flag */ 00934 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; 00935 00936 if(hdma->DMAmuxRequestGen != 0U) 00937 { 00938 /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ 00939 /* disable the request gen overrun IT */ 00940 hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; 00941 00942 /* Clear the DMAMUX request generator overrun flag */ 00943 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; 00944 } 00945 } 00946 00947 /* Change the DMA state */ 00948 hdma->State = HAL_DMA_STATE_READY; 00949 00950 /* Process Unlocked */ 00951 __HAL_UNLOCK(hdma); 00952 00953 /* Call User Abort callback */ 00954 if(hdma->XferAbortCallback != NULL) 00955 { 00956 hdma->XferAbortCallback(hdma); 00957 } 00958 } 00959 } 00960 00961 return HAL_OK; 00962 } 00963 00964 /** 00965 * @brief Polling for transfer complete. 00966 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 00967 * the configuration information for the specified DMA Stream. 00968 * @param CompleteLevel: Specifies the DMA level complete. 00969 * @note The polling mode is kept in this version for legacy. it is recommended to use the IT model instead. 00970 * This model could be used for debug purpose. 00971 * @note The HAL_DMA_PollForTransfer API cannot be used in circular and double buffering mode (automatic circular mode). 00972 * @param Timeout: Timeout duration. 00973 * @retval HAL status 00974 */ 00975 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout) 00976 { 00977 HAL_StatusTypeDef status = HAL_OK; 00978 uint32_t cpltlevel_mask; 00979 uint32_t tickstart = HAL_GetTick(); 00980 00981 /* IT status register */ 00982 __IO uint32_t *isr_reg; 00983 /* IT clear flag register */ 00984 __IO uint32_t *ifcr_reg; 00985 00986 /* Check the DMA peripheral handle */ 00987 if(hdma == NULL) 00988 { 00989 return HAL_ERROR; 00990 } 00991 00992 if(HAL_DMA_STATE_BUSY != hdma->State) 00993 { 00994 /* No transfer ongoing */ 00995 hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; 00996 __HAL_UNLOCK(hdma); 00997 00998 return HAL_ERROR; 00999 } 01000 01001 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01002 { 01003 /* Polling mode not supported in circular mode and double buffering mode */ 01004 if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) != 0U) 01005 { 01006 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; 01007 return HAL_ERROR; 01008 } 01009 01010 /* Get the level transfer complete flag */ 01011 if(CompleteLevel == HAL_DMA_FULL_TRANSFER) 01012 { 01013 /* Transfer Complete flag */ 01014 cpltlevel_mask = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU); 01015 } 01016 else 01017 { 01018 /* Half Transfer Complete flag */ 01019 cpltlevel_mask = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU); 01020 } 01021 01022 isr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->ISR); 01023 ifcr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR); 01024 } 01025 else /* BDMA channel */ 01026 { 01027 /* Polling mode not supported in circular mode */ 01028 if ((((BDMA_Channel_TypeDef *)hdma->Instance)->CCR & BDMA_CCR_CIRC) != 0U) 01029 { 01030 hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; 01031 return HAL_ERROR; 01032 } 01033 01034 /* Get the level transfer complete flag */ 01035 if(CompleteLevel == HAL_DMA_FULL_TRANSFER) 01036 { 01037 /* Transfer Complete flag */ 01038 cpltlevel_mask = BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU); 01039 } 01040 else 01041 { 01042 /* Half Transfer Complete flag */ 01043 cpltlevel_mask = BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU); 01044 } 01045 01046 isr_reg = &(((BDMA_Base_Registers *)hdma->StreamBaseAddress)->ISR); 01047 ifcr_reg = &(((BDMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR); 01048 } 01049 01050 while(((*isr_reg) & cpltlevel_mask) == 0U) 01051 { 01052 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01053 { 01054 if(((*isr_reg) & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01055 { 01056 /* Update error code */ 01057 hdma->ErrorCode |= HAL_DMA_ERROR_FE; 01058 01059 /* Clear the FIFO error flag */ 01060 (*ifcr_reg) = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU); 01061 } 01062 01063 if(((*isr_reg) & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01064 { 01065 /* Update error code */ 01066 hdma->ErrorCode |= HAL_DMA_ERROR_DME; 01067 01068 /* Clear the Direct Mode error flag */ 01069 (*ifcr_reg) = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU); 01070 } 01071 01072 if(((*isr_reg) & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01073 { 01074 /* Update error code */ 01075 hdma->ErrorCode |= HAL_DMA_ERROR_TE; 01076 01077 /* Clear the transfer error flag */ 01078 (*ifcr_reg) = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU); 01079 01080 /* Change the DMA state */ 01081 hdma->State = HAL_DMA_STATE_READY; 01082 01083 /* Process Unlocked */ 01084 __HAL_UNLOCK(hdma); 01085 01086 return HAL_ERROR; 01087 } 01088 } 01089 else /* BDMA channel */ 01090 { 01091 if(((*isr_reg) & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U) 01092 { 01093 /* When a DMA transfer error occurs */ 01094 /* A hardware clear of its EN bits is performed */ 01095 /* Clear all flags */ 01096 (*isr_reg) = ((BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU)); 01097 01098 /* Update error code */ 01099 hdma->ErrorCode = HAL_DMA_ERROR_TE; 01100 01101 /* Change the DMA state */ 01102 hdma->State = HAL_DMA_STATE_READY; 01103 01104 /* Process Unlocked */ 01105 __HAL_UNLOCK(hdma); 01106 01107 return HAL_ERROR; 01108 } 01109 } 01110 01111 /* Check for the Timeout (Not applicable in circular mode)*/ 01112 if(Timeout != HAL_MAX_DELAY) 01113 { 01114 if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U)) 01115 { 01116 /* Update error code */ 01117 hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT; 01118 01119 /* if timeout then abort the current transfer */ 01120 /* No need to check return value: as in this case we will return HAL_ERROR with HAL_DMA_ERROR_TIMEOUT error code */ 01121 (void) HAL_DMA_Abort(hdma); 01122 /* 01123 Note that the Abort function will 01124 - Clear the transfer error flags 01125 - Unlock 01126 - Set the State 01127 */ 01128 01129 return HAL_ERROR; 01130 } 01131 } 01132 01133 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 01134 { 01135 /* Check for DMAMUX Request generator (if used) overrun status */ 01136 if(hdma->DMAmuxRequestGen != 0U) 01137 { 01138 /* if using DMAMUX request generator Check for DMAMUX request generator overrun */ 01139 if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U) 01140 { 01141 /* Clear the DMAMUX request generator overrun flag */ 01142 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; 01143 01144 /* Update error code */ 01145 hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN; 01146 } 01147 } 01148 01149 /* Check for DMAMUX Synchronization overrun */ 01150 if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U) 01151 { 01152 /* Clear the DMAMUX synchro overrun flag */ 01153 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; 01154 01155 /* Update error code */ 01156 hdma->ErrorCode |= HAL_DMA_ERROR_SYNC; 01157 } 01158 } 01159 } 01160 01161 01162 /* Get the level transfer complete flag */ 01163 if(CompleteLevel == HAL_DMA_FULL_TRANSFER) 01164 { 01165 /* Clear the half transfer and transfer complete flags */ 01166 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01167 { 01168 (*ifcr_reg) = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << (hdma->StreamIndex & 0x1FU); 01169 } 01170 else /* BDMA channel */ 01171 { 01172 (*ifcr_reg) = (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU)); 01173 } 01174 01175 hdma->State = HAL_DMA_STATE_READY; 01176 01177 /* Process Unlocked */ 01178 __HAL_UNLOCK(hdma); 01179 } 01180 else /*CompleteLevel = HAL_DMA_HALF_TRANSFER*/ 01181 { 01182 /* Clear the half transfer and transfer complete flags */ 01183 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01184 { 01185 (*ifcr_reg) = (DMA_FLAG_HTIF0_4) << (hdma->StreamIndex & 0x1FU); 01186 } 01187 else /* BDMA channel */ 01188 { 01189 (*ifcr_reg) = (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU)); 01190 } 01191 } 01192 01193 return status; 01194 } 01195 01196 /** 01197 * @brief Handles DMA interrupt request. 01198 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01199 * the configuration information for the specified DMA Stream. 01200 * @retval None 01201 */ 01202 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) 01203 { 01204 uint32_t tmpisr_dma, tmpisr_bdma; 01205 uint32_t ccr_reg; 01206 __IO uint32_t count = 0U; 01207 uint32_t timeout = SystemCoreClock / 9600U; 01208 01209 /* calculate DMA base and stream number */ 01210 DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress; 01211 BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress; 01212 01213 tmpisr_dma = regs_dma->ISR; 01214 tmpisr_bdma = regs_bdma->ISR; 01215 01216 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01217 { 01218 /* Transfer Error Interrupt management ***************************************/ 01219 if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01220 { 01221 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U) 01222 { 01223 /* Disable the transfer error interrupt */ 01224 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TE); 01225 01226 /* Clear the transfer error flag */ 01227 regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU); 01228 01229 /* Update error code */ 01230 hdma->ErrorCode |= HAL_DMA_ERROR_TE; 01231 } 01232 } 01233 /* FIFO Error Interrupt management ******************************************/ 01234 if ((tmpisr_dma & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01235 { 01236 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != 0U) 01237 { 01238 /* Clear the FIFO error flag */ 01239 regs_dma->IFCR = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU); 01240 01241 /* Update error code */ 01242 hdma->ErrorCode |= HAL_DMA_ERROR_FE; 01243 } 01244 } 01245 /* Direct Mode Error Interrupt management ***********************************/ 01246 if ((tmpisr_dma & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01247 { 01248 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != 0U) 01249 { 01250 /* Clear the direct mode error flag */ 01251 regs_dma->IFCR = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU); 01252 01253 /* Update error code */ 01254 hdma->ErrorCode |= HAL_DMA_ERROR_DME; 01255 } 01256 } 01257 /* Half Transfer Complete Interrupt management ******************************/ 01258 if ((tmpisr_dma & (DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01259 { 01260 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U) 01261 { 01262 /* Clear the half transfer complete flag */ 01263 regs_dma->IFCR = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU); 01264 01265 /* Multi_Buffering mode enabled */ 01266 if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U) 01267 { 01268 /* Current memory buffer used is Memory 0 */ 01269 if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U) 01270 { 01271 if(hdma->XferHalfCpltCallback != NULL) 01272 { 01273 /* Half transfer callback */ 01274 hdma->XferHalfCpltCallback(hdma); 01275 } 01276 } 01277 /* Current memory buffer used is Memory 1 */ 01278 else 01279 { 01280 if(hdma->XferM1HalfCpltCallback != NULL) 01281 { 01282 /* Half transfer callback */ 01283 hdma->XferM1HalfCpltCallback(hdma); 01284 } 01285 } 01286 } 01287 else 01288 { 01289 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ 01290 if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U) 01291 { 01292 /* Disable the half transfer interrupt */ 01293 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT); 01294 } 01295 01296 if(hdma->XferHalfCpltCallback != NULL) 01297 { 01298 /* Half transfer callback */ 01299 hdma->XferHalfCpltCallback(hdma); 01300 } 01301 } 01302 } 01303 } 01304 /* Transfer Complete Interrupt management ***********************************/ 01305 if ((tmpisr_dma & (DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U) 01306 { 01307 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U) 01308 { 01309 /* Clear the transfer complete flag */ 01310 regs_dma->IFCR = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU); 01311 01312 if(HAL_DMA_STATE_ABORT == hdma->State) 01313 { 01314 /* Disable all the transfer interrupts */ 01315 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME); 01316 ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE); 01317 01318 if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL)) 01319 { 01320 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT); 01321 } 01322 01323 /* Clear all interrupt flags at correct offset within the register */ 01324 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU); 01325 01326 /* Change the DMA state */ 01327 hdma->State = HAL_DMA_STATE_READY; 01328 01329 /* Process Unlocked */ 01330 __HAL_UNLOCK(hdma); 01331 01332 if(hdma->XferAbortCallback != NULL) 01333 { 01334 hdma->XferAbortCallback(hdma); 01335 } 01336 return; 01337 } 01338 01339 if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U) 01340 { 01341 /* Current memory buffer used is Memory 0 */ 01342 if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U) 01343 { 01344 if(hdma->XferM1CpltCallback != NULL) 01345 { 01346 /* Transfer complete Callback for memory1 */ 01347 hdma->XferM1CpltCallback(hdma); 01348 } 01349 } 01350 /* Current memory buffer used is Memory 1 */ 01351 else 01352 { 01353 if(hdma->XferCpltCallback != NULL) 01354 { 01355 /* Transfer complete Callback for memory0 */ 01356 hdma->XferCpltCallback(hdma); 01357 } 01358 } 01359 } 01360 /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */ 01361 else 01362 { 01363 if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U) 01364 { 01365 /* Disable the transfer complete interrupt */ 01366 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC); 01367 01368 /* Change the DMA state */ 01369 hdma->State = HAL_DMA_STATE_READY; 01370 01371 /* Process Unlocked */ 01372 __HAL_UNLOCK(hdma); 01373 } 01374 01375 if(hdma->XferCpltCallback != NULL) 01376 { 01377 /* Transfer complete callback */ 01378 hdma->XferCpltCallback(hdma); 01379 } 01380 } 01381 } 01382 } 01383 01384 /* manage error case */ 01385 if(hdma->ErrorCode != HAL_DMA_ERROR_NONE) 01386 { 01387 if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U) 01388 { 01389 hdma->State = HAL_DMA_STATE_ABORT; 01390 01391 /* Disable the stream */ 01392 __HAL_DMA_DISABLE(hdma); 01393 01394 do 01395 { 01396 if (++count > timeout) 01397 { 01398 break; 01399 } 01400 } 01401 while((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U); 01402 01403 if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U) 01404 { 01405 /* Change the DMA state to error if DMA disable fails */ 01406 hdma->State = HAL_DMA_STATE_ERROR; 01407 } 01408 else 01409 { 01410 /* Change the DMA state to Ready if DMA disable success */ 01411 hdma->State = HAL_DMA_STATE_READY; 01412 } 01413 01414 /* Process Unlocked */ 01415 __HAL_UNLOCK(hdma); 01416 } 01417 01418 if(hdma->XferErrorCallback != NULL) 01419 { 01420 /* Transfer error callback */ 01421 hdma->XferErrorCallback(hdma); 01422 } 01423 } 01424 } 01425 else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */ 01426 { 01427 ccr_reg = (((BDMA_Channel_TypeDef *)hdma->Instance)->CCR); 01428 01429 /* Half Transfer Complete Interrupt management ******************************/ 01430 if (((tmpisr_bdma & (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_HTIE) != 0U)) 01431 { 01432 /* Clear the half transfer complete flag */ 01433 regs_bdma->IFCR = (BDMA_ISR_HTIF0 << (hdma->StreamIndex & 0x1FU)); 01434 01435 /* Disable the transfer complete interrupt if the DMA mode is Double Buffering */ 01436 if((ccr_reg & BDMA_CCR_DBM) != 0U) 01437 { 01438 /* Current memory buffer used is Memory 0 */ 01439 if((ccr_reg & BDMA_CCR_CT) == 0U) 01440 { 01441 if(hdma->XferM1HalfCpltCallback != NULL) 01442 { 01443 /* Half transfer Callback for Memory 1 */ 01444 hdma->XferM1HalfCpltCallback(hdma); 01445 } 01446 } 01447 /* Current memory buffer used is Memory 1 */ 01448 else 01449 { 01450 if(hdma->XferHalfCpltCallback != NULL) 01451 { 01452 /* Half transfer Callback for Memory 0 */ 01453 hdma->XferHalfCpltCallback(hdma); 01454 } 01455 } 01456 } 01457 else 01458 { 01459 if((ccr_reg & BDMA_CCR_CIRC) == 0U) 01460 { 01461 /* Disable the half transfer interrupt */ 01462 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); 01463 } 01464 01465 /* DMA peripheral state is not updated in Half Transfer */ 01466 /* but in Transfer Complete case */ 01467 01468 if(hdma->XferHalfCpltCallback != NULL) 01469 { 01470 /* Half transfer callback */ 01471 hdma->XferHalfCpltCallback(hdma); 01472 } 01473 } 01474 } 01475 01476 /* Transfer Complete Interrupt management ***********************************/ 01477 else if (((tmpisr_bdma & (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TCIE) != 0U)) 01478 { 01479 /* Clear the transfer complete flag */ 01480 regs_bdma->IFCR = (BDMA_ISR_TCIF0) << (hdma->StreamIndex & 0x1FU); 01481 01482 /* Disable the transfer complete interrupt if the DMA mode is Double Buffering */ 01483 if((ccr_reg & BDMA_CCR_DBM) != 0U) 01484 { 01485 /* Current memory buffer used is Memory 0 */ 01486 if((ccr_reg & BDMA_CCR_CT) == 0U) 01487 { 01488 if(hdma->XferM1CpltCallback != NULL) 01489 { 01490 /* Transfer complete Callback for Memory 1 */ 01491 hdma->XferM1CpltCallback(hdma); 01492 } 01493 } 01494 /* Current memory buffer used is Memory 1 */ 01495 else 01496 { 01497 if(hdma->XferCpltCallback != NULL) 01498 { 01499 /* Transfer complete Callback for Memory 0 */ 01500 hdma->XferCpltCallback(hdma); 01501 } 01502 } 01503 } 01504 else 01505 { 01506 if((ccr_reg & BDMA_CCR_CIRC) == 0U) 01507 { 01508 /* Disable the transfer complete and error interrupt, if the DMA mode is not CIRCULAR */ 01509 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC); 01510 01511 /* Change the DMA state */ 01512 hdma->State = HAL_DMA_STATE_READY; 01513 01514 /* Process Unlocked */ 01515 __HAL_UNLOCK(hdma); 01516 } 01517 01518 if(hdma->XferCpltCallback != NULL) 01519 { 01520 /* Transfer complete callback */ 01521 hdma->XferCpltCallback(hdma); 01522 } 01523 } 01524 } 01525 /* Transfer Error Interrupt management **************************************/ 01526 else if (((tmpisr_bdma & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TEIE) != 0U)) 01527 { 01528 /* When a DMA transfer error occurs */ 01529 /* A hardware clear of its EN bits is performed */ 01530 /* Disable ALL DMA IT */ 01531 __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); 01532 01533 /* Clear all flags */ 01534 regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU); 01535 01536 /* Update error code */ 01537 hdma->ErrorCode = HAL_DMA_ERROR_TE; 01538 01539 /* Change the DMA state */ 01540 hdma->State = HAL_DMA_STATE_READY; 01541 01542 /* Process Unlocked */ 01543 __HAL_UNLOCK(hdma); 01544 01545 if (hdma->XferErrorCallback != NULL) 01546 { 01547 /* Transfer error callback */ 01548 hdma->XferErrorCallback(hdma); 01549 } 01550 } 01551 else 01552 { 01553 /* Nothing To Do */ 01554 } 01555 } 01556 else 01557 { 01558 /* Nothing To Do */ 01559 } 01560 } 01561 01562 /** 01563 * @brief Register callbacks 01564 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01565 * the configuration information for the specified DMA Stream. 01566 * @param CallbackID: User Callback identifier 01567 * a DMA_HandleTypeDef structure as parameter. 01568 * @param pCallback: pointer to private callback function which has pointer to 01569 * a DMA_HandleTypeDef structure as parameter. 01570 * @retval HAL status 01571 */ 01572 HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma)) 01573 { 01574 01575 HAL_StatusTypeDef status = HAL_OK; 01576 01577 /* Check the DMA peripheral handle */ 01578 if(hdma == NULL) 01579 { 01580 return HAL_ERROR; 01581 } 01582 01583 /* Process locked */ 01584 __HAL_LOCK(hdma); 01585 01586 if(HAL_DMA_STATE_READY == hdma->State) 01587 { 01588 switch (CallbackID) 01589 { 01590 case HAL_DMA_XFER_CPLT_CB_ID: 01591 hdma->XferCpltCallback = pCallback; 01592 break; 01593 01594 case HAL_DMA_XFER_HALFCPLT_CB_ID: 01595 hdma->XferHalfCpltCallback = pCallback; 01596 break; 01597 01598 case HAL_DMA_XFER_M1CPLT_CB_ID: 01599 hdma->XferM1CpltCallback = pCallback; 01600 break; 01601 01602 case HAL_DMA_XFER_M1HALFCPLT_CB_ID: 01603 hdma->XferM1HalfCpltCallback = pCallback; 01604 break; 01605 01606 case HAL_DMA_XFER_ERROR_CB_ID: 01607 hdma->XferErrorCallback = pCallback; 01608 break; 01609 01610 case HAL_DMA_XFER_ABORT_CB_ID: 01611 hdma->XferAbortCallback = pCallback; 01612 break; 01613 01614 default: 01615 status = HAL_ERROR; 01616 break; 01617 } 01618 } 01619 else 01620 { 01621 /* Return error status */ 01622 status = HAL_ERROR; 01623 } 01624 01625 /* Release Lock */ 01626 __HAL_UNLOCK(hdma); 01627 01628 return status; 01629 } 01630 01631 /** 01632 * @brief UnRegister callbacks 01633 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01634 * the configuration information for the specified DMA Stream. 01635 * @param CallbackID: User Callback identifier 01636 * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. 01637 * @retval HAL status 01638 */ 01639 HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID) 01640 { 01641 HAL_StatusTypeDef status = HAL_OK; 01642 01643 /* Check the DMA peripheral handle */ 01644 if(hdma == NULL) 01645 { 01646 return HAL_ERROR; 01647 } 01648 01649 /* Process locked */ 01650 __HAL_LOCK(hdma); 01651 01652 if(HAL_DMA_STATE_READY == hdma->State) 01653 { 01654 switch (CallbackID) 01655 { 01656 case HAL_DMA_XFER_CPLT_CB_ID: 01657 hdma->XferCpltCallback = NULL; 01658 break; 01659 01660 case HAL_DMA_XFER_HALFCPLT_CB_ID: 01661 hdma->XferHalfCpltCallback = NULL; 01662 break; 01663 01664 case HAL_DMA_XFER_M1CPLT_CB_ID: 01665 hdma->XferM1CpltCallback = NULL; 01666 break; 01667 01668 case HAL_DMA_XFER_M1HALFCPLT_CB_ID: 01669 hdma->XferM1HalfCpltCallback = NULL; 01670 break; 01671 01672 case HAL_DMA_XFER_ERROR_CB_ID: 01673 hdma->XferErrorCallback = NULL; 01674 break; 01675 01676 case HAL_DMA_XFER_ABORT_CB_ID: 01677 hdma->XferAbortCallback = NULL; 01678 break; 01679 01680 case HAL_DMA_XFER_ALL_CB_ID: 01681 hdma->XferCpltCallback = NULL; 01682 hdma->XferHalfCpltCallback = NULL; 01683 hdma->XferM1CpltCallback = NULL; 01684 hdma->XferM1HalfCpltCallback = NULL; 01685 hdma->XferErrorCallback = NULL; 01686 hdma->XferAbortCallback = NULL; 01687 break; 01688 01689 default: 01690 status = HAL_ERROR; 01691 break; 01692 } 01693 } 01694 else 01695 { 01696 status = HAL_ERROR; 01697 } 01698 01699 /* Release Lock */ 01700 __HAL_UNLOCK(hdma); 01701 01702 return status; 01703 } 01704 01705 /** 01706 * @} 01707 */ 01708 01709 /** @addtogroup DMA_Exported_Functions_Group3 01710 * 01711 @verbatim 01712 =============================================================================== 01713 ##### State and Errors functions ##### 01714 =============================================================================== 01715 [..] 01716 This subsection provides functions allowing to 01717 (+) Check the DMA state 01718 (+) Get error code 01719 01720 @endverbatim 01721 * @{ 01722 */ 01723 01724 /** 01725 * @brief Returns the DMA state. 01726 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01727 * the configuration information for the specified DMA Stream. 01728 * @retval HAL state 01729 */ 01730 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma) 01731 { 01732 return hdma->State; 01733 } 01734 01735 /** 01736 * @brief Return the DMA error code 01737 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains 01738 * the configuration information for the specified DMA Stream. 01739 * @retval DMA Error Code 01740 */ 01741 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma) 01742 { 01743 return hdma->ErrorCode; 01744 } 01745 01746 /** 01747 * @} 01748 */ 01749 01750 /** 01751 * @} 01752 */ 01753 01754 /** @addtogroup DMA_Private_Functions 01755 * @{ 01756 */ 01757 01758 /** 01759 * @brief Sets the DMA Transfer parameter. 01760 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01761 * the configuration information for the specified DMA Stream. 01762 * @param SrcAddress: The source memory Buffer address 01763 * @param DstAddress: The destination memory Buffer address 01764 * @param DataLength: The length of data to be transferred from source to destination 01765 * @retval None 01766 */ 01767 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) 01768 { 01769 /* calculate DMA base and stream number */ 01770 DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress; 01771 BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress; 01772 01773 if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */ 01774 { 01775 /* Clear the DMAMUX synchro overrun flag */ 01776 hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; 01777 01778 if(hdma->DMAmuxRequestGen != 0U) 01779 { 01780 /* Clear the DMAMUX request generator overrun flag */ 01781 hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; 01782 } 01783 } 01784 01785 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01786 { 01787 /* Clear all interrupt flags at correct offset within the register */ 01788 regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU); 01789 01790 /* Clear DBM bit */ 01791 ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM); 01792 01793 /* Configure DMA Stream data length */ 01794 ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = DataLength; 01795 01796 /* Peripheral to Memory */ 01797 if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) 01798 { 01799 /* Configure DMA Stream destination address */ 01800 ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = DstAddress; 01801 01802 /* Configure DMA Stream source address */ 01803 ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = SrcAddress; 01804 } 01805 /* Memory to Peripheral */ 01806 else 01807 { 01808 /* Configure DMA Stream source address */ 01809 ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = SrcAddress; 01810 01811 /* Configure DMA Stream destination address */ 01812 ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = DstAddress; 01813 } 01814 } 01815 else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */ 01816 { 01817 /* Clear all flags */ 01818 regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU); 01819 01820 /* Configure DMA Channel data length */ 01821 ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = DataLength; 01822 01823 /* Peripheral to Memory */ 01824 if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) 01825 { 01826 /* Configure DMA Channel destination address */ 01827 ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = DstAddress; 01828 01829 /* Configure DMA Channel source address */ 01830 ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = SrcAddress; 01831 } 01832 /* Memory to Peripheral */ 01833 else 01834 { 01835 /* Configure DMA Channel source address */ 01836 ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = SrcAddress; 01837 01838 /* Configure DMA Channel destination address */ 01839 ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = DstAddress; 01840 } 01841 } 01842 else 01843 { 01844 /* Nothing To Do */ 01845 } 01846 } 01847 01848 /** 01849 * @brief Returns the DMA Stream base address depending on stream number 01850 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01851 * the configuration information for the specified DMA Stream. 01852 * @retval Stream base address 01853 */ 01854 static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma) 01855 { 01856 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */ 01857 { 01858 uint32_t stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U; 01859 01860 /* lookup table for necessary bitshift of flags within status registers */ 01861 static const uint8_t flagBitshiftOffset[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U}; 01862 hdma->StreamIndex = flagBitshiftOffset[stream_number & 0x7U]; 01863 01864 if (stream_number > 3U) 01865 { 01866 /* return pointer to HISR and HIFCR */ 01867 hdma->StreamBaseAddress = (((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU)) + 4U); 01868 } 01869 else 01870 { 01871 /* return pointer to LISR and LIFCR */ 01872 hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU)); 01873 } 01874 } 01875 else /* BDMA instance(s) */ 01876 { 01877 /* return pointer to ISR and IFCR */ 01878 hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0xFFU)); 01879 } 01880 01881 return hdma->StreamBaseAddress; 01882 } 01883 01884 /** 01885 * @brief Check compatibility between FIFO threshold level and size of the memory burst 01886 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01887 * the configuration information for the specified DMA Stream. 01888 * @retval HAL status 01889 */ 01890 static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma) 01891 { 01892 HAL_StatusTypeDef status = HAL_OK; 01893 01894 /* Memory Data size equal to Byte */ 01895 if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_BYTE) 01896 { 01897 switch (hdma->Init.FIFOThreshold) 01898 { 01899 case DMA_FIFO_THRESHOLD_1QUARTERFULL: 01900 case DMA_FIFO_THRESHOLD_3QUARTERSFULL: 01901 01902 if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1) 01903 { 01904 status = HAL_ERROR; 01905 } 01906 break; 01907 01908 case DMA_FIFO_THRESHOLD_HALFFULL: 01909 if (hdma->Init.MemBurst == DMA_MBURST_INC16) 01910 { 01911 status = HAL_ERROR; 01912 } 01913 break; 01914 01915 case DMA_FIFO_THRESHOLD_FULL: 01916 break; 01917 01918 default: 01919 break; 01920 } 01921 } 01922 01923 /* Memory Data size equal to Half-Word */ 01924 else if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD) 01925 { 01926 switch (hdma->Init.FIFOThreshold) 01927 { 01928 case DMA_FIFO_THRESHOLD_1QUARTERFULL: 01929 case DMA_FIFO_THRESHOLD_3QUARTERSFULL: 01930 status = HAL_ERROR; 01931 break; 01932 01933 case DMA_FIFO_THRESHOLD_HALFFULL: 01934 if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1) 01935 { 01936 status = HAL_ERROR; 01937 } 01938 break; 01939 01940 case DMA_FIFO_THRESHOLD_FULL: 01941 if (hdma->Init.MemBurst == DMA_MBURST_INC16) 01942 { 01943 status = HAL_ERROR; 01944 } 01945 break; 01946 01947 default: 01948 break; 01949 } 01950 } 01951 01952 /* Memory Data size equal to Word */ 01953 else 01954 { 01955 switch (hdma->Init.FIFOThreshold) 01956 { 01957 case DMA_FIFO_THRESHOLD_1QUARTERFULL: 01958 case DMA_FIFO_THRESHOLD_HALFFULL: 01959 case DMA_FIFO_THRESHOLD_3QUARTERSFULL: 01960 status = HAL_ERROR; 01961 break; 01962 01963 case DMA_FIFO_THRESHOLD_FULL: 01964 if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1) 01965 { 01966 status = HAL_ERROR; 01967 } 01968 break; 01969 01970 default: 01971 break; 01972 } 01973 } 01974 01975 return status; 01976 } 01977 01978 /** 01979 * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number 01980 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 01981 * the configuration information for the specified DMA Stream. 01982 * @retval HAL status 01983 */ 01984 static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma) 01985 { 01986 uint32_t stream_number; 01987 uint32_t stream_baseaddress = (uint32_t)((uint32_t*)hdma->Instance); 01988 01989 if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U) 01990 { 01991 /* BDMA Channels are connected to DMAMUX2 channels */ 01992 stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 8U) / 20U; 01993 hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX2_Channel0) + (stream_number * 4U))); 01994 hdma->DMAmuxChannelStatus = DMAMUX2_ChannelStatus; 01995 hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU); 01996 } 01997 else 01998 { 01999 /* DMA1/DMA2 Streams are connected to DMAMUX1 channels */ 02000 stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U; 02001 02002 if((stream_baseaddress <= ((uint32_t)DMA2_Stream7) ) && \ 02003 (stream_baseaddress >= ((uint32_t)DMA2_Stream0))) 02004 { 02005 stream_number += 8U; 02006 } 02007 hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_Channel0) + (stream_number * 4U))); 02008 hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus; 02009 hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU); 02010 } 02011 } 02012 02013 /** 02014 * @brief Updates the DMA handle with the DMAMUX request generator params 02015 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains 02016 * the configuration information for the specified DMA Stream. 02017 * @retval HAL status 02018 */ 02019 static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma) 02020 { 02021 uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID; 02022 02023 if((request >= DMA_REQUEST_GENERATOR0) && (request <= DMA_REQUEST_GENERATOR7)) 02024 { 02025 if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U) 02026 { 02027 /* BDMA Channels are connected to DMAMUX2 request generator blocks */ 02028 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX2_RequestGenerator0) + ((request - 1U) * 4U))); 02029 02030 hdma->DMAmuxRequestGenStatus = DMAMUX2_RequestGenStatus; 02031 } 02032 else 02033 { 02034 /* DMA1 and DMA2 Streams use DMAMUX1 request generator blocks */ 02035 hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U))); 02036 02037 hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus; 02038 } 02039 02040 hdma->DMAmuxRequestGenStatusMask = 1UL << (request - 1U); 02041 } 02042 } 02043 02044 /** 02045 * @} 02046 */ 02047 02048 #endif /* HAL_DMA_MODULE_ENABLED */ 02049 /** 02050 * @} 02051 */ 02052 02053 /** 02054 * @} 02055 */ 02056