313 lines
10 KiB
313 lines
10 KiB
/** |
|
****************************************************************************** |
|
* @file stm32f4xx_hal_dma_ex.c |
|
* @author MCD Application Team |
|
* @brief DMA Extension HAL module driver |
|
* This file provides firmware functions to manage the following |
|
* functionalities of the DMA Extension peripheral: |
|
* + Extended features functions |
|
* |
|
@verbatim |
|
============================================================================== |
|
##### How to use this driver ##### |
|
============================================================================== |
|
[..] |
|
The DMA Extension HAL driver can be used as follows: |
|
(#) Start a multi buffer transfer using the HAL_DMA_MultiBufferStart() function |
|
for polling mode or HAL_DMA_MultiBufferStart_IT() for interrupt mode. |
|
|
|
-@- In Memory-to-Memory transfer mode, Multi (Double) Buffer mode is not allowed. |
|
-@- When Multi (Double) Buffer mode is enabled the, transfer is circular by default. |
|
-@- In Multi (Double) buffer mode, it is possible to update the base address for |
|
the AHB memory port on the fly (DMA_SxM0AR or DMA_SxM1AR) when the stream is enabled. |
|
|
|
@endverbatim |
|
****************************************************************************** |
|
* @attention |
|
* |
|
* Copyright (c) 2017 STMicroelectronics. |
|
* All rights reserved. |
|
* |
|
* This software is licensed under terms that can be found in the LICENSE file in |
|
* the root directory of this software component. |
|
* If no LICENSE file comes with this software, it is provided AS-IS. |
|
* |
|
****************************************************************************** |
|
*/ |
|
|
|
/* Includes ------------------------------------------------------------------*/ |
|
#include "stm32f4xx_hal.h" |
|
|
|
/** @addtogroup STM32F4xx_HAL_Driver |
|
* @{ |
|
*/ |
|
|
|
/** @defgroup DMAEx DMAEx |
|
* @brief DMA Extended HAL module driver |
|
* @{ |
|
*/ |
|
|
|
#ifdef HAL_DMA_MODULE_ENABLED |
|
|
|
/* Private types -------------------------------------------------------------*/ |
|
/* Private variables ---------------------------------------------------------*/ |
|
/* Private Constants ---------------------------------------------------------*/ |
|
/* Private macros ------------------------------------------------------------*/ |
|
/* Private functions ---------------------------------------------------------*/ |
|
/** @addtogroup DMAEx_Private_Functions |
|
* @{ |
|
*/ |
|
static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); |
|
/** |
|
* @} |
|
*/ |
|
|
|
/* Exported functions ---------------------------------------------------------*/ |
|
|
|
/** @addtogroup DMAEx_Exported_Functions |
|
* @{ |
|
*/ |
|
|
|
|
|
/** @addtogroup DMAEx_Exported_Functions_Group1 |
|
* |
|
@verbatim |
|
=============================================================================== |
|
##### Extended features functions ##### |
|
=============================================================================== |
|
[..] This section provides functions allowing to: |
|
(+) Configure the source, destination address and data length and |
|
Start MultiBuffer DMA transfer |
|
(+) Configure the source, destination address and data length and |
|
Start MultiBuffer DMA transfer with interrupt |
|
(+) Change on the fly the memory0 or memory1 address. |
|
|
|
@endverbatim |
|
* @{ |
|
*/ |
|
|
|
|
|
/** |
|
* @brief Starts the multi_buffer DMA Transfer. |
|
* @param hdma pointer to a DMA_HandleTypeDef structure that contains |
|
* the configuration information for the specified DMA Stream. |
|
* @param SrcAddress The source memory Buffer address |
|
* @param DstAddress The destination memory Buffer address |
|
* @param SecondMemAddress The second memory Buffer address in case of multi buffer Transfer |
|
* @param DataLength The length of data to be transferred from source to destination |
|
* @retval HAL status |
|
*/ |
|
HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength) |
|
{ |
|
HAL_StatusTypeDef status = HAL_OK; |
|
|
|
/* Check the parameters */ |
|
assert_param(IS_DMA_BUFFER_SIZE(DataLength)); |
|
|
|
/* Memory-to-memory transfer not supported in double buffering mode */ |
|
if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) |
|
{ |
|
hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; |
|
status = HAL_ERROR; |
|
} |
|
else |
|
{ |
|
/* Process Locked */ |
|
__HAL_LOCK(hdma); |
|
|
|
if(HAL_DMA_STATE_READY == hdma->State) |
|
{ |
|
/* Change DMA peripheral state */ |
|
hdma->State = HAL_DMA_STATE_BUSY; |
|
|
|
/* Enable the double buffer mode */ |
|
hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM; |
|
|
|
/* Configure DMA Stream destination address */ |
|
hdma->Instance->M1AR = SecondMemAddress; |
|
|
|
/* Configure the source, destination address and the data length */ |
|
DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength); |
|
|
|
/* Enable the peripheral */ |
|
__HAL_DMA_ENABLE(hdma); |
|
} |
|
else |
|
{ |
|
/* Return error status */ |
|
status = HAL_BUSY; |
|
} |
|
} |
|
return status; |
|
} |
|
|
|
/** |
|
* @brief Starts the multi_buffer DMA Transfer with interrupt enabled. |
|
* @param hdma pointer to a DMA_HandleTypeDef structure that contains |
|
* the configuration information for the specified DMA Stream. |
|
* @param SrcAddress The source memory Buffer address |
|
* @param DstAddress The destination memory Buffer address |
|
* @param SecondMemAddress The second memory Buffer address in case of multi buffer Transfer |
|
* @param DataLength The length of data to be transferred from source to destination |
|
* @retval HAL status |
|
*/ |
|
HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength) |
|
{ |
|
HAL_StatusTypeDef status = HAL_OK; |
|
|
|
/* Check the parameters */ |
|
assert_param(IS_DMA_BUFFER_SIZE(DataLength)); |
|
|
|
/* Memory-to-memory transfer not supported in double buffering mode */ |
|
if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) |
|
{ |
|
hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; |
|
return HAL_ERROR; |
|
} |
|
|
|
/* Check callback functions */ |
|
if ((NULL == hdma->XferCpltCallback) || (NULL == hdma->XferM1CpltCallback) || (NULL == hdma->XferErrorCallback)) |
|
{ |
|
hdma->ErrorCode = HAL_DMA_ERROR_PARAM; |
|
return HAL_ERROR; |
|
} |
|
|
|
/* Process locked */ |
|
__HAL_LOCK(hdma); |
|
|
|
if(HAL_DMA_STATE_READY == hdma->State) |
|
{ |
|
/* Change DMA peripheral state */ |
|
hdma->State = HAL_DMA_STATE_BUSY; |
|
|
|
/* Initialize the error code */ |
|
hdma->ErrorCode = HAL_DMA_ERROR_NONE; |
|
|
|
/* Enable the Double buffer mode */ |
|
hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM; |
|
|
|
/* Configure DMA Stream destination address */ |
|
hdma->Instance->M1AR = SecondMemAddress; |
|
|
|
/* Configure the source, destination address and the data length */ |
|
DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength); |
|
|
|
/* Clear all flags */ |
|
__HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); |
|
__HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); |
|
__HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); |
|
__HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); |
|
__HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); |
|
|
|
/* Enable Common interrupts*/ |
|
hdma->Instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME; |
|
hdma->Instance->FCR |= DMA_IT_FE; |
|
|
|
if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL)) |
|
{ |
|
hdma->Instance->CR |= DMA_IT_HT; |
|
} |
|
|
|
/* Enable the peripheral */ |
|
__HAL_DMA_ENABLE(hdma); |
|
} |
|
else |
|
{ |
|
/* Process unlocked */ |
|
__HAL_UNLOCK(hdma); |
|
|
|
/* Return error status */ |
|
status = HAL_BUSY; |
|
} |
|
return status; |
|
} |
|
|
|
/** |
|
* @brief Change the memory0 or memory1 address on the fly. |
|
* @param hdma pointer to a DMA_HandleTypeDef structure that contains |
|
* the configuration information for the specified DMA Stream. |
|
* @param Address The new address |
|
* @param memory the memory to be changed, This parameter can be one of |
|
* the following values: |
|
* MEMORY0 / |
|
* MEMORY1 |
|
* @note The MEMORY0 address can be changed only when the current transfer use |
|
* MEMORY1 and the MEMORY1 address can be changed only when the current |
|
* transfer use MEMORY0. |
|
* @retval HAL status |
|
*/ |
|
HAL_StatusTypeDef HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef *hdma, uint32_t Address, HAL_DMA_MemoryTypeDef memory) |
|
{ |
|
if(memory == MEMORY0) |
|
{ |
|
/* change the memory0 address */ |
|
hdma->Instance->M0AR = Address; |
|
} |
|
else |
|
{ |
|
/* change the memory1 address */ |
|
hdma->Instance->M1AR = Address; |
|
} |
|
|
|
return HAL_OK; |
|
} |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
/** @addtogroup DMAEx_Private_Functions |
|
* @{ |
|
*/ |
|
|
|
/** |
|
* @brief Set the DMA Transfer parameter. |
|
* @param hdma pointer to a DMA_HandleTypeDef structure that contains |
|
* the configuration information for the specified DMA Stream. |
|
* @param SrcAddress The source memory Buffer address |
|
* @param DstAddress The destination memory Buffer address |
|
* @param DataLength The length of data to be transferred from source to destination |
|
* @retval HAL status |
|
*/ |
|
static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) |
|
{ |
|
/* Configure DMA Stream data length */ |
|
hdma->Instance->NDTR = DataLength; |
|
|
|
/* Peripheral to Memory */ |
|
if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) |
|
{ |
|
/* Configure DMA Stream destination address */ |
|
hdma->Instance->PAR = DstAddress; |
|
|
|
/* Configure DMA Stream source address */ |
|
hdma->Instance->M0AR = SrcAddress; |
|
} |
|
/* Memory to Peripheral */ |
|
else |
|
{ |
|
/* Configure DMA Stream source address */ |
|
hdma->Instance->PAR = SrcAddress; |
|
|
|
/* Configure DMA Stream destination address */ |
|
hdma->Instance->M0AR = DstAddress; |
|
} |
|
} |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
#endif /* HAL_DMA_MODULE_ENABLED */ |
|
/** |
|
* @} |
|
*/ |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
|