880 lines
35 KiB
C
880 lines
35 KiB
C
/*
|
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* o Redistributions of source code must retain the above copyright notice, this list
|
|
* of conditions and the following disclaimer.
|
|
*
|
|
* o Redistributions in binary form must reproduce the above copyright notice, this
|
|
* list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef _FSL_EDMA_H_
|
|
#define _FSL_EDMA_H_
|
|
|
|
#include "fsl_common.h"
|
|
|
|
/*!
|
|
* @addtogroup edma_driver
|
|
* @{
|
|
*/
|
|
|
|
/*! @file */
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/*! @name Driver version */
|
|
/*@{*/
|
|
/*! @brief eDMA driver version */
|
|
#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
|
|
/*@}*/
|
|
|
|
/*! @brief Compute the offset unit from DCHPRI3 */
|
|
#define DMA_DCHPRI_INDEX(channel) (((channel) & ~0x03U) | (3 - ((channel)&0x03U)))
|
|
|
|
/*! @brief Get the pointer of DCHPRIn */
|
|
#define DMA_DCHPRIn(base, channel) ((volatile uint8_t *)&(base->DCHPRI3))[DMA_DCHPRI_INDEX(channel)]
|
|
|
|
/*! @brief eDMA transfer configuration */
|
|
typedef enum _edma_transfer_size
|
|
{
|
|
kEDMA_TransferSize1Bytes = 0x0U, /*!< Source/Destination data transfer size is 1 byte every time */
|
|
kEDMA_TransferSize2Bytes = 0x1U, /*!< Source/Destination data transfer size is 2 bytes every time */
|
|
kEDMA_TransferSize4Bytes = 0x2U, /*!< Source/Destination data transfer size is 4 bytes every time */
|
|
kEDMA_TransferSize16Bytes = 0x4U, /*!< Source/Destination data transfer size is 16 bytes every time */
|
|
kEDMA_TransferSize32Bytes = 0x5U, /*!< Source/Destination data transfer size is 32 bytes every time */
|
|
} edma_transfer_size_t;
|
|
|
|
/*! @brief eDMA modulo configuration */
|
|
typedef enum _edma_modulo
|
|
{
|
|
kEDMA_ModuloDisable = 0x0U, /*!< Disable modulo */
|
|
kEDMA_Modulo2bytes, /*!< Circular buffer size is 2 bytes. */
|
|
kEDMA_Modulo4bytes, /*!< Circular buffer size is 4 bytes. */
|
|
kEDMA_Modulo8bytes, /*!< Circular buffer size is 8 bytes. */
|
|
kEDMA_Modulo16bytes, /*!< Circular buffer size is 16 bytes. */
|
|
kEDMA_Modulo32bytes, /*!< Circular buffer size is 32 bytes. */
|
|
kEDMA_Modulo64bytes, /*!< Circular buffer size is 64 bytes. */
|
|
kEDMA_Modulo128bytes, /*!< Circular buffer size is 128 bytes. */
|
|
kEDMA_Modulo256bytes, /*!< Circular buffer size is 256 bytes. */
|
|
kEDMA_Modulo512bytes, /*!< Circular buffer size is 512 bytes. */
|
|
kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1K bytes. */
|
|
kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2K bytes. */
|
|
kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4K bytes. */
|
|
kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8K bytes. */
|
|
kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16K bytes. */
|
|
kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32K bytes. */
|
|
kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64K bytes. */
|
|
kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128K bytes. */
|
|
kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256K bytes. */
|
|
kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512K bytes. */
|
|
kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1M bytes. */
|
|
kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2M bytes. */
|
|
kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4M bytes. */
|
|
kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8M bytes. */
|
|
kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16M bytes. */
|
|
kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32M bytes. */
|
|
kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64M bytes. */
|
|
kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128M bytes. */
|
|
kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256M bytes. */
|
|
kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512M bytes. */
|
|
kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1G bytes. */
|
|
kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2G bytes. */
|
|
} edma_modulo_t;
|
|
|
|
/*! @brief Bandwidth control */
|
|
typedef enum _edma_bandwidth
|
|
{
|
|
kEDMA_BandwidthStallNone = 0x0U, /*!< No eDMA engine stalls. */
|
|
kEDMA_BandwidthStall4Cycle = 0x2U, /*!< eDMA engine stalls for 4 cycles after each read/write. */
|
|
kEDMA_BandwidthStall8Cycle = 0x3U, /*!< eDMA engine stalls for 8 cycles after each read/write. */
|
|
} edma_bandwidth_t;
|
|
|
|
/*! @brief Channel link type */
|
|
typedef enum _edma_channel_link_type
|
|
{
|
|
kEDMA_LinkNone = 0x0U, /*!< No channel link */
|
|
kEDMA_MinorLink, /*!< Channel link after each minor loop */
|
|
kEDMA_MajorLink, /*!< Channel link while major loop count exhausted */
|
|
} edma_channel_link_type_t;
|
|
|
|
/*!@brief eDMA channel status flags. */
|
|
enum _edma_channel_status_flags
|
|
{
|
|
kEDMA_DoneFlag = 0x1U, /*!< DONE flag, set while transfer finished, CITER value exhausted*/
|
|
kEDMA_ErrorFlag = 0x2U, /*!< eDMA error flag, an error occurred in a transfer */
|
|
kEDMA_InterruptFlag = 0x4U, /*!< eDMA interrupt flag, set while an interrupt occurred of this channel */
|
|
};
|
|
|
|
/*! @brief eDMA channel error status flags. */
|
|
enum _edma_error_status_flags
|
|
{
|
|
kEDMA_DestinationBusErrorFlag = DMA_ES_DBE_MASK, /*!< Bus error on destination address */
|
|
kEDMA_SourceBusErrorFlag = DMA_ES_SBE_MASK, /*!< Bus error on the source address */
|
|
kEDMA_ScatterGatherErrorFlag = DMA_ES_SGE_MASK, /*!< Error on the Scatter/Gather address, not 32byte aligned. */
|
|
kEDMA_NbytesErrorFlag = DMA_ES_NCE_MASK, /*!< NBYTES/CITER configuration error */
|
|
kEDMA_DestinationOffsetErrorFlag = DMA_ES_DOE_MASK, /*!< Destination offset not aligned with destination size */
|
|
kEDMA_DestinationAddressErrorFlag = DMA_ES_DAE_MASK, /*!< Destination address not aligned with destination size */
|
|
kEDMA_SourceOffsetErrorFlag = DMA_ES_SOE_MASK, /*!< Source offset not aligned with source size */
|
|
kEDMA_SourceAddressErrorFlag = DMA_ES_SAE_MASK, /*!< Source address not aligned with source size*/
|
|
kEDMA_ErrorChannelFlag = DMA_ES_ERRCHN_MASK, /*!< Error channel number of the cancelled channel number */
|
|
kEDMA_ChannelPriorityErrorFlag = DMA_ES_CPE_MASK, /*!< Channel priority is not unique. */
|
|
kEDMA_TransferCanceledFlag = DMA_ES_ECX_MASK, /*!< Transfer cancelled */
|
|
#if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1
|
|
kEDMA_GroupPriorityErrorFlag = DMA_ES_GPE_MASK, /*!< Group priority is not unique. */
|
|
#endif
|
|
kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit will be 0, otherwise be 1 */
|
|
};
|
|
|
|
/*! @brief eDMA interrupt source */
|
|
typedef enum _edma_interrupt_enable
|
|
{
|
|
kEDMA_ErrorInterruptEnable = 0x1U, /*!< Enable interrupt while channel error occurs. */
|
|
kEDMA_MajorInterruptEnable = DMA_CSR_INTMAJOR_MASK, /*!< Enable interrupt while major count exhausted. */
|
|
kEDMA_HalfInterruptEnable = DMA_CSR_INTHALF_MASK, /*!< Enable interrupt while major count to half value. */
|
|
} edma_interrupt_enable_t;
|
|
|
|
/*! @brief eDMA transfer type */
|
|
typedef enum _edma_transfer_type
|
|
{
|
|
kEDMA_MemoryToMemory = 0x0U, /*!< Transfer from memory to memory */
|
|
kEDMA_PeripheralToMemory, /*!< Transfer from peripheral to memory */
|
|
kEDMA_MemoryToPeripheral, /*!< Transfer from memory to peripheral */
|
|
} edma_transfer_type_t;
|
|
|
|
/*! @brief eDMA transfer status */
|
|
enum _edma_transfer_status
|
|
{
|
|
kStatus_EDMA_QueueFull = MAKE_STATUS(kStatusGroup_EDMA, 0), /*!< TCD queue is full. */
|
|
kStatus_EDMA_Busy = MAKE_STATUS(kStatusGroup_EDMA, 1), /*!< Channel is busy and can't handle the
|
|
transfer request. */
|
|
};
|
|
|
|
/*! @brief eDMA global configuration structure.*/
|
|
typedef struct _edma_config
|
|
{
|
|
bool enableContinuousLinkMode; /*!< Enable (true) continuous link mode. Upon minor loop completion, the channel
|
|
activates again if that channel has a minor loop channel link enabled and
|
|
the link channel is itself. */
|
|
bool enableHaltOnError; /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set.
|
|
Subsequently, all service requests are ignored until the HALT bit is cleared.*/
|
|
bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method, or fixed priority
|
|
arbitration is used for channel selection */
|
|
bool enableDebugMode; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of
|
|
a new channel. Executing channels are allowed to complete. */
|
|
} edma_config_t;
|
|
|
|
/*!
|
|
* @brief eDMA transfer configuration
|
|
*
|
|
* This structure configures the source/destination transfer attribute.
|
|
* This figure shows the eDMA's transfer model:
|
|
* _________________________________________________
|
|
* | Transfer Size | |
|
|
* Minor Loop |_______________| Major loop Count 1 |
|
|
* Bytes | Transfer Size | |
|
|
* ____________|_______________|____________________|--> Minor loop complete
|
|
* ____________________________________
|
|
* | | |
|
|
* |_______________| Major Loop Count 2 |
|
|
* | | |
|
|
* |_______________|____________________|--> Minor loop Complete
|
|
*
|
|
* ---------------------------------------------------------> Transfer complete
|
|
*/
|
|
typedef struct _edma_transfer_config
|
|
{
|
|
uint32_t srcAddr; /*!< Source data address. */
|
|
uint32_t destAddr; /*!< Destination data address. */
|
|
edma_transfer_size_t srcTransferSize; /*!< Source data transfer size. */
|
|
edma_transfer_size_t destTransferSize; /*!< Destination data transfer size. */
|
|
int16_t srcOffset; /*!< Sign-extended offset applied to the current source address to
|
|
form the next-state value as each source read is completed. */
|
|
int16_t destOffset; /*!< Sign-extended offset applied to the current destination address to
|
|
form the next-state value as each destination write is completed. */
|
|
uint16_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/
|
|
uint32_t majorLoopCounts; /*!< Major loop iteration count. */
|
|
} edma_transfer_config_t;
|
|
|
|
/*! @brief eDMA channel priority configuration */
|
|
typedef struct _edma_channel_Preemption_config
|
|
{
|
|
bool enableChannelPreemption; /*!< If true: channel can be suspended by other channel with higher priority */
|
|
bool enablePreemptAbility; /*!< If true: channel can suspend other channel with low priority */
|
|
uint8_t channelPriority; /*!< Channel priority */
|
|
} edma_channel_Preemption_config_t;
|
|
|
|
/*! @brief eDMA minor offset configuration */
|
|
typedef struct _edma_minor_offset_config
|
|
{
|
|
bool enableSrcMinorOffset; /*!< Enable(true) or Disable(false) source minor loop offset. */
|
|
bool enableDestMinorOffset; /*!< Enable(true) or Disable(false) destination minor loop offset. */
|
|
uint32_t minorOffset; /*!< Offset for minor loop mapping. */
|
|
} edma_minor_offset_config_t;
|
|
|
|
/*!
|
|
* @brief eDMA TCD.
|
|
*
|
|
* This structure is same as TCD register which is described in reference manual,
|
|
* and is used to configure scatter/gather feature as a next hardware TCD.
|
|
*/
|
|
typedef struct _edma_tcd
|
|
{
|
|
__IO uint32_t SADDR; /*!< SADDR register, used to save source address */
|
|
__IO uint16_t SOFF; /*!< SOFF register, save offset bytes every transfer */
|
|
__IO uint16_t ATTR; /*!< ATTR register, source/destination transfer size and modulo */
|
|
__IO uint32_t NBYTES; /*!< Nbytes register, minor loop length in bytes */
|
|
__IO uint32_t SLAST; /*!< SLAST register */
|
|
__IO uint32_t DADDR; /*!< DADDR register, used for destination address */
|
|
__IO uint16_t DOFF; /*!< DOFF register, used for destination offset */
|
|
__IO uint16_t CITER; /*!< CITER register, current minor loop numbers, for unfinished minor loop.*/
|
|
__IO uint32_t DLAST_SGA; /*!< DLASTSGA register, next stcd address used in scatter-gather mode */
|
|
__IO uint16_t CSR; /*!< CSR register, for TCD control status */
|
|
__IO uint16_t BITER; /*!< BITER register, begin minor loop count. */
|
|
} edma_tcd_t;
|
|
|
|
/*! @brief Callback for eDMA */
|
|
struct _edma_handle;
|
|
|
|
/*! @brief Define Callback function for eDMA. */
|
|
typedef void (*edma_callback)(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds);
|
|
|
|
/*! @brief eDMA transfer handle structure */
|
|
typedef struct _edma_handle
|
|
{
|
|
edma_callback callback; /*!< Callback function for major count exhausted. */
|
|
void *userData; /*!< Callback function parameter. */
|
|
DMA_Type *base; /*!< eDMA peripheral base address. */
|
|
edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */
|
|
uint8_t channel; /*!< eDMA channel number. */
|
|
volatile int8_t header; /*!< The first TCD index. */
|
|
volatile int8_t tail; /*!< The last TCD index. */
|
|
volatile int8_t tcdUsed; /*!< The number of used TCD slots. */
|
|
volatile int8_t tcdSize; /*!< The total number of TCD slots in the queue. */
|
|
uint8_t flags; /*!< The status of the current channel. */
|
|
} edma_handle_t;
|
|
|
|
/*******************************************************************************
|
|
* APIs
|
|
******************************************************************************/
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
/*!
|
|
* @name eDMA initialization and De-initialization
|
|
* @{
|
|
*/
|
|
|
|
/*!
|
|
* @brief Initializes eDMA peripheral.
|
|
*
|
|
* This function ungates the eDMA clock and configure eDMA peripheral according
|
|
* to the configuration structure.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param config Pointer to configuration structure, see "edma_config_t".
|
|
* @note This function enable the minor loop map feature.
|
|
*/
|
|
void EDMA_Init(DMA_Type *base, const edma_config_t *config);
|
|
|
|
/*!
|
|
* @brief Deinitializes eDMA peripheral.
|
|
*
|
|
* This function gates the eDMA clock.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
*/
|
|
void EDMA_Deinit(DMA_Type *base);
|
|
|
|
/*!
|
|
* @brief Gets the eDMA default configuration structure.
|
|
*
|
|
* This function sets the configuration structure to a default value.
|
|
* The default configuration is set to the following value:
|
|
* @code
|
|
* config.enableContinuousLinkMode = false;
|
|
* config.enableHaltOnError = true;
|
|
* config.enableRoundRobinArbitration = false;
|
|
* config.enableDebugMode = false;
|
|
* @endcode
|
|
*
|
|
* @param config Pointer to eDMA configuration structure.
|
|
*/
|
|
void EDMA_GetDefaultConfig(edma_config_t *config);
|
|
|
|
/* @} */
|
|
/*!
|
|
* @name eDMA Channel Operation
|
|
* @{
|
|
*/
|
|
|
|
/*!
|
|
* @brief Sets all TCD registers to a default value.
|
|
*
|
|
* This function sets TCD registers for this channel to default value.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @note This function must not be called while the channel transfer is on-going,
|
|
* or it will case unpredicated results.
|
|
* @note This function will enable auto stop request feature.
|
|
*/
|
|
void EDMA_ResetChannel(DMA_Type *base, uint32_t channel);
|
|
|
|
/*!
|
|
* @brief Configures the eDMA transfer attribute.
|
|
*
|
|
* This function configure the transfer attribute, including source address, destination address,
|
|
* transfer size, address offset, and so on. It also configures the scatter gather feature if the
|
|
* user supplies the TCD address.
|
|
* Example:
|
|
* @code
|
|
* edma_transfer_t config;
|
|
* edma_tcd_t tcd;
|
|
* config.srcAddr = ..;
|
|
* config.destAddr = ..;
|
|
* ...
|
|
* EDMA_SetTransferConfig(DMA0, channel, &config, &stcd);
|
|
* @endcode
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param config Pointer to eDMA transfer configuration structure.
|
|
* @param nextTcd Point to TCD structure. It can be NULL if user
|
|
* do not want to enable scatter/gather feature.
|
|
* @note If nextTcd is not NULL, it means scatter gather feature will be enabled.
|
|
* And DREQ bit will be cleared in the previous transfer configuration which
|
|
* will be set in eDMA_ResetChannel.
|
|
*/
|
|
void EDMA_SetTransferConfig(DMA_Type *base,
|
|
uint32_t channel,
|
|
const edma_transfer_config_t *config,
|
|
edma_tcd_t *nextTcd);
|
|
|
|
/*!
|
|
* @brief Configures the eDMA minor offset feature.
|
|
*
|
|
* Minor offset means signed-extended value added to source address or destination
|
|
* address after each minor loop.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param config Pointer to Minor offset configuration structure.
|
|
*/
|
|
void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config);
|
|
|
|
/*!
|
|
* @brief Configures the eDMA channel preemption feature.
|
|
*
|
|
* This function configures the channel preemption attribute and the priority of the channel.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number
|
|
* @param config Pointer to channel preemption configuration structure.
|
|
*/
|
|
static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base,
|
|
uint32_t channel,
|
|
const edma_channel_Preemption_config_t *config)
|
|
{
|
|
assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL);
|
|
assert(config != NULL);
|
|
|
|
DMA_DCHPRIn(base, channel) =
|
|
(DMA_DCHPRI0_DPA(!config->enablePreemptAbility) | DMA_DCHPRI0_ECP(config->enableChannelPreemption) |
|
|
DMA_DCHPRI0_CHPRI(config->channelPriority));
|
|
}
|
|
|
|
/*!
|
|
* @brief Sets the channel link for the eDMA transfer.
|
|
*
|
|
* This function configures minor link or major link mode. The minor link means that the channel link is
|
|
* triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is exhausted.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param type Channel link type, it can be one of:
|
|
* @arg kEDMA_LinkNone
|
|
* @arg kEDMA_MinorLink
|
|
* @arg kEDMA_MajorLink
|
|
* @param linkedChannel The linked channel number.
|
|
* @note User should ensure that DONE flag is cleared before call this interface, or the configuration will be invalid.
|
|
*/
|
|
void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel);
|
|
|
|
/*!
|
|
* @brief Sets the bandwidth for the eDMA transfer.
|
|
*
|
|
* In general, because the eDMA processes the minor loop, it continuously generates read/write sequences
|
|
* until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
|
|
* each read/write access to control the bus request bandwidth seen by the crossbar switch.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param bandWidth Bandwidth setting, it can be one of:
|
|
* @arg kEDMABandwidthStallNone
|
|
* @arg kEDMABandwidthStall4Cycle
|
|
* @arg kEDMABandwidthStall8Cycle
|
|
*/
|
|
void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth);
|
|
|
|
/*!
|
|
* @brief Sets the source modulo and destination modulo for eDMA transfer.
|
|
*
|
|
* This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
|
|
* calculation is performed or the original register value. It provides the ability to implement a circular data
|
|
* queue easily.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param srcModulo Source modulo value.
|
|
* @param destModulo Destination modulo value.
|
|
*/
|
|
void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo);
|
|
|
|
#if defined(FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT) && FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT
|
|
/*!
|
|
* @brief Enables an async request for the eDMA transfer.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param enable The command for enable(ture) or disable(false).
|
|
*/
|
|
static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable)
|
|
{
|
|
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
|
|
|
|
base->EARS = (base->EARS & (~(1U << channel))) | ((uint32_t)enable << channel);
|
|
}
|
|
#endif /* FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT */
|
|
|
|
/*!
|
|
* @brief Enables an auto stop request for the eDMA transfer.
|
|
*
|
|
* If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param enable The command for enable (true) or disable (false).
|
|
*/
|
|
static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable)
|
|
{
|
|
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
|
|
|
|
base->TCD[channel].CSR = (base->TCD[channel].CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
|
|
}
|
|
|
|
/*!
|
|
* @brief Enables the interrupt source for the eDMA transfer.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param mask The mask of interrupt source to be set. User need to use
|
|
* the defined edma_interrupt_enable_t type.
|
|
*/
|
|
void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
|
|
|
|
/*!
|
|
* @brief Disables the interrupt source for the eDMA transfer.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param mask The mask of interrupt source to be set. Use
|
|
* the defined edma_interrupt_enable_t type.
|
|
*/
|
|
void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
|
|
|
|
/* @} */
|
|
/*!
|
|
* @name eDMA TCD Operation
|
|
* @{
|
|
*/
|
|
|
|
/*!
|
|
* @brief Sets all fields to default values for the TCD structure.
|
|
*
|
|
* This function sets all fields for this TCD structure to default value.
|
|
*
|
|
* @param tcd Pointer to the TCD structure.
|
|
* @note This function will enable auto stop request feature.
|
|
*/
|
|
void EDMA_TcdReset(edma_tcd_t *tcd);
|
|
|
|
/*!
|
|
* @brief Configures the eDMA TCD transfer attribute.
|
|
*
|
|
* TCD is a transfer control descriptor. The content of the TCD is the same as hardware TCD registers.
|
|
* STCD is used in scatter-gather mode.
|
|
* This function configures the TCD transfer attribute, including source address, destination address,
|
|
* transfer size, address offset, and so on. It also configures the scatter gather feature if the
|
|
* user supplies the next TCD address.
|
|
* Example:
|
|
* @code
|
|
* edma_transfer_t config = {
|
|
* ...
|
|
* }
|
|
* edma_tcd_t tcd __aligned(32);
|
|
* edma_tcd_t nextTcd __aligned(32);
|
|
* EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
|
|
* @endcode
|
|
*
|
|
* @param tcd Pointer to the TCD structure.
|
|
* @param config Pointer to eDMA transfer configuration structure.
|
|
* @param nextTcd Pointer to the next TCD structure. It can be NULL if user
|
|
* do not want to enable scatter/gather feature.
|
|
* @note TCD address should be 32 bytes aligned, or it will cause eDMA error.
|
|
* @note If nextTcd is not NULL, it means scatter gather feature will be enabled.
|
|
* And DREQ bit will be cleared in the previous transfer configuration which
|
|
* will be set in EDMA_TcdReset.
|
|
*/
|
|
void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd);
|
|
|
|
/*!
|
|
* @brief Configures the eDMA TCD minor offset feature.
|
|
*
|
|
* Minor offset is a signed-extended value added to the source address or destination
|
|
* address after each minor loop.
|
|
*
|
|
* @param tcd Point to the TCD structure.
|
|
* @param config Pointer to Minor offset configuration structure.
|
|
*/
|
|
void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config);
|
|
|
|
/*!
|
|
* @brief Sets the channel link for eDMA TCD.
|
|
*
|
|
* This function configures either a minor link or a major link. The minor link means the channel link is
|
|
* triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is exhausted.
|
|
*
|
|
* @note User should ensure that DONE flag is cleared before call this interface, or the configuration will be invalid.
|
|
* @param tcd Point to the TCD structure.
|
|
* @param type Channel link type, it can be one of:
|
|
* @arg kEDMA_LinkNone
|
|
* @arg kEDMA_MinorLink
|
|
* @arg kEDMA_MajorLink
|
|
* @param linkedChannel The linked channel number.
|
|
*/
|
|
void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel);
|
|
|
|
/*!
|
|
* @brief Sets the bandwidth for the eDMA TCD.
|
|
*
|
|
* In general, because the eDMA processes the minor loop, it continuously generates read/write sequences
|
|
* until the minor count is exhausted. Bandwidth forces the eDMA to stall after the completion of
|
|
* each read/write access to control the bus request bandwidth seen by the crossbar switch.
|
|
* @param tcd Point to the TCD structure.
|
|
* @param bandWidth Bandwidth setting, it can be one of:
|
|
* @arg kEDMABandwidthStallNone
|
|
* @arg kEDMABandwidthStall4Cycle
|
|
* @arg kEDMABandwidthStall8Cycle
|
|
*/
|
|
static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWidth)
|
|
{
|
|
assert(tcd != NULL);
|
|
assert(((uint32_t)tcd & 0x1FU) == 0);
|
|
|
|
tcd->CSR = (tcd->CSR & (~DMA_CSR_BWC_MASK)) | DMA_CSR_BWC(bandWidth);
|
|
}
|
|
|
|
/*!
|
|
* @brief Sets the source modulo and destination modulo for eDMA TCD.
|
|
*
|
|
* This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
|
|
* calculation is performed or the original register value. It provides the ability to implement a circular data
|
|
* queue easily.
|
|
*
|
|
* @param tcd Point to the TCD structure.
|
|
* @param srcModulo Source modulo value.
|
|
* @param destModulo Destination modulo value.
|
|
*/
|
|
void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo);
|
|
|
|
/*!
|
|
* @brief Sets the auto stop request for the eDMA TCD.
|
|
*
|
|
* If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
|
|
*
|
|
* @param tcd Point to the TCD structure.
|
|
* @param enable The command for enable(ture) or disable(false).
|
|
*/
|
|
static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable)
|
|
{
|
|
assert(tcd != NULL);
|
|
assert(((uint32_t)tcd & 0x1FU) == 0);
|
|
|
|
tcd->CSR = (tcd->CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
|
|
}
|
|
|
|
/*!
|
|
* @brief Enables the interrupt source for the eDMA TCD.
|
|
*
|
|
* @param tcd Point to the TCD structure.
|
|
* @param mask The mask of interrupt source to be set. User need to use
|
|
* the defined edma_interrupt_enable_t type.
|
|
*/
|
|
void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask);
|
|
|
|
/*!
|
|
* @brief Disables the interrupt source for the eDMA TCD.
|
|
*
|
|
* @param tcd Point to the TCD structure.
|
|
* @param mask The mask of interrupt source to be set. User need to use
|
|
* the defined edma_interrupt_enable_t type.
|
|
*/
|
|
void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask);
|
|
|
|
/*! @} */
|
|
/*!
|
|
* @name eDMA Channel Transfer Operation
|
|
* @{
|
|
*/
|
|
|
|
/*!
|
|
* @brief Enables the eDMA hardware channel request.
|
|
*
|
|
* This function enables the hardware channel request.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
*/
|
|
static inline void EDMA_EnableChannelRequest(DMA_Type *base, uint32_t channel)
|
|
{
|
|
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
|
|
|
|
base->SERQ = DMA_SERQ_SERQ(channel);
|
|
}
|
|
|
|
/*!
|
|
* @brief Disables the eDMA hardware channel request.
|
|
*
|
|
* This function disables the hardware channel request.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
*/
|
|
static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel)
|
|
{
|
|
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
|
|
|
|
base->CERQ = DMA_CERQ_CERQ(channel);
|
|
}
|
|
|
|
/*!
|
|
* @brief Starts the eDMA transfer by software trigger.
|
|
*
|
|
* This function starts a minor loop transfer.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
*/
|
|
static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel)
|
|
{
|
|
assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
|
|
|
|
base->SSRT = DMA_SSRT_SSRT(channel);
|
|
}
|
|
|
|
/*! @} */
|
|
/*!
|
|
* @name eDMA Channel Status Operation
|
|
* @{
|
|
*/
|
|
|
|
/*!
|
|
* @brief Gets the Remaining bytes from the eDMA current channel TCD.
|
|
*
|
|
* This function checks the TCD (Task Control Descriptor) status for a specified
|
|
* eDMA channel and returns the the number of bytes that have not finished.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @return Bytes have not been transferred yet for the current TCD.
|
|
* @note This function can only be used to get unfinished bytes of transfer without
|
|
* the next TCD, or it might be inaccuracy.
|
|
*/
|
|
uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel);
|
|
|
|
/*!
|
|
* @brief Gets the eDMA channel error status flags.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @return The mask of error status flags. User need to use the
|
|
* _edma_error_status_flags type to decode the return variables.
|
|
*/
|
|
static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base)
|
|
{
|
|
return base->ES;
|
|
}
|
|
|
|
/*!
|
|
* @brief Gets the eDMA channel status flags.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @return The mask of channel status flags. User need to use the
|
|
* _edma_channel_status_flags type to decode the return variables.
|
|
*/
|
|
uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel);
|
|
|
|
/*!
|
|
* @brief Clears the eDMA channel status flags.
|
|
*
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
* @param mask The mask of channel status to be cleared. User need to use
|
|
* the defined _edma_channel_status_flags type.
|
|
*/
|
|
void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask);
|
|
|
|
/*! @} */
|
|
/*!
|
|
* @name eDMA Transactional Operation
|
|
*/
|
|
|
|
/*!
|
|
* @brief Creates the eDMA handle.
|
|
*
|
|
* This function is called if using transaction API for eDMA. This function
|
|
* initializes the internal state of eDMA handle.
|
|
*
|
|
* @param handle eDMA handle pointer. The eDMA handle stores callback function and
|
|
* parameters.
|
|
* @param base eDMA peripheral base address.
|
|
* @param channel eDMA channel number.
|
|
*/
|
|
void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel);
|
|
|
|
/*!
|
|
* @brief Installs the TCDs memory pool into eDMA handle.
|
|
*
|
|
* This function is called after the EDMA_CreateHandle to use scatter/gather feature.
|
|
*
|
|
* @param handle eDMA handle pointer.
|
|
* @param tcdPool Memory pool to store TCDs. It must be 32 bytes aligned.
|
|
* @param tcdSize The number of TCD slots.
|
|
*/
|
|
void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize);
|
|
|
|
/*!
|
|
* @brief Installs a callback function for the eDMA transfer.
|
|
*
|
|
* This callback is called in eDMA IRQ handler. Use the callback to do something after
|
|
* the current major loop transfer completes.
|
|
*
|
|
* @param handle eDMA handle pointer.
|
|
* @param callback eDMA callback function pointer.
|
|
* @param userData Parameter for callback function.
|
|
*/
|
|
void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData);
|
|
|
|
/*!
|
|
* @brief Prepares the eDMA transfer structure.
|
|
*
|
|
* This function prepares the transfer configuration structure according to the user input.
|
|
*
|
|
* @param config The user configuration structure of type edma_transfer_t.
|
|
* @param srcAddr eDMA transfer source address.
|
|
* @param srcWidth eDMA transfer source address width(bytes).
|
|
* @param destAddr eDMA transfer destination address.
|
|
* @param destWidth eDMA transfer destination address width(bytes).
|
|
* @param bytesEachRequest eDMA transfer bytes per channel request.
|
|
* @param transferBytes eDMA transfer bytes to be transferred.
|
|
* @param type eDMA transfer type.
|
|
* @note The data address and the data width must be consistent. For example, if the SRC
|
|
* is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in
|
|
* source address error(SAE).
|
|
*/
|
|
void EDMA_PrepareTransfer(edma_transfer_config_t *config,
|
|
void *srcAddr,
|
|
uint32_t srcWidth,
|
|
void *destAddr,
|
|
uint32_t destWidth,
|
|
uint32_t bytesEachRequest,
|
|
uint32_t transferBytes,
|
|
edma_transfer_type_t type);
|
|
|
|
/*!
|
|
* @brief Submits the eDMA transfer request.
|
|
*
|
|
* This function submits the eDMA transfer request according to the transfer configuration structure.
|
|
* If the user submits the transfer request repeatedly, this function packs an unprocessed request as
|
|
* a TCD and enables scatter/gather feature to process it in the next time.
|
|
*
|
|
* @param handle eDMA handle pointer.
|
|
* @param config Pointer to eDMA transfer configuration structure.
|
|
* @retval kStatus_EDMA_Success It means submit transfer request succeed.
|
|
* @retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
|
|
* @retval kStatus_EDMA_Busy It means the given channel is busy, need to submit request later.
|
|
*/
|
|
status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config);
|
|
|
|
/*!
|
|
* @brief eDMA start transfer.
|
|
*
|
|
* This function enables the channel request. User can call this function after submitting the transfer request
|
|
* or before submitting the transfer request.
|
|
*
|
|
* @param handle eDMA handle pointer.
|
|
*/
|
|
void EDMA_StartTransfer(edma_handle_t *handle);
|
|
|
|
/*!
|
|
* @brief eDMA stop transfer.
|
|
*
|
|
* This function disables the channel request to pause the transfer. User can call EDMA_StartTransfer()
|
|
* again to resume the transfer.
|
|
*
|
|
* @param handle eDMA handle pointer.
|
|
*/
|
|
void EDMA_StopTransfer(edma_handle_t *handle);
|
|
|
|
/*!
|
|
* @brief eDMA abort transfer.
|
|
*
|
|
* This function disables the channel request and clear transfer status bits.
|
|
* User can submit another transfer after calling this API.
|
|
*
|
|
* @param handle DMA handle pointer.
|
|
*/
|
|
void EDMA_AbortTransfer(edma_handle_t *handle);
|
|
|
|
/*!
|
|
* @brief eDMA IRQ handler for current major loop transfer complete.
|
|
*
|
|
* This function clears the channel major interrupt flag and call
|
|
* the callback function if it is not NULL.
|
|
*
|
|
* @param handle eDMA handle pointer.
|
|
*/
|
|
void EDMA_HandleIRQ(edma_handle_t *handle);
|
|
|
|
/* @} */
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
/* @} */
|
|
|
|
#endif /*_FSL_EDMA_H_*/
|