Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fsl_edma.h Source File

fsl_edma.h

00001 /*
00002  * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003  * Copyright 2016-2018 NXP
00004  * All rights reserved.
00005  *
00006  * SPDX-License-Identifier: BSD-3-Clause
00007  */
00008 
00009 #ifndef _FSL_EDMA_H_
00010 #define _FSL_EDMA_H_
00011 
00012 #include "fsl_common.h"
00013 
00014 /*!
00015  * @addtogroup edma
00016  * @{
00017  */
00018 
00019 /*******************************************************************************
00020  * Definitions
00021  ******************************************************************************/
00022 
00023 /*! @name Driver version */
00024 /*@{*/
00025 /*! @brief eDMA driver version */
00026 #define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 4)) /*!< Version 2.1.4. */
00027 /*@}*/
00028 
00029 /*! @brief Compute the offset unit from DCHPRI3 */
00030 #define DMA_DCHPRI_INDEX(channel) (((channel) & ~0x03U) | (3 - ((channel)&0x03U)))
00031 
00032 /*! @brief Get the pointer of DCHPRIn */
00033 #define DMA_DCHPRIn(base, channel) ((volatile uint8_t *)&((base)->DCHPRI3))[DMA_DCHPRI_INDEX(channel)]
00034 
00035 /*! @brief eDMA transfer configuration */
00036 typedef enum _edma_transfer_size
00037 {
00038     kEDMA_TransferSize1Bytes  = 0x0U,  /*!< Source/Destination data transfer size is 1 byte every time */
00039     kEDMA_TransferSize2Bytes  = 0x1U,  /*!< Source/Destination data transfer size is 2 bytes every time */
00040     kEDMA_TransferSize4Bytes  = 0x2U,  /*!< Source/Destination data transfer size is 4 bytes every time */
00041     kEDMA_TransferSize8Bytes  = 0x3U,  /*!< Source/Destination data transfer size is 8 bytes every time */
00042     kEDMA_TransferSize16Bytes  = 0x4U, /*!< Source/Destination data transfer size is 16 bytes every time */
00043     kEDMA_TransferSize32Bytes  = 0x5U, /*!< Source/Destination data transfer size is 32 bytes every time */
00044 } edma_transfer_size_t;
00045 
00046 /*! @brief eDMA modulo configuration */
00047 typedef enum _edma_modulo
00048 {
00049     kEDMA_ModuloDisable  = 0x0U, /*!< Disable modulo */
00050     kEDMA_Modulo2bytes ,         /*!< Circular buffer size is 2 bytes. */
00051     kEDMA_Modulo4bytes ,         /*!< Circular buffer size is 4 bytes. */
00052     kEDMA_Modulo8bytes ,         /*!< Circular buffer size is 8 bytes. */
00053     kEDMA_Modulo16bytes ,        /*!< Circular buffer size is 16 bytes. */
00054     kEDMA_Modulo32bytes ,        /*!< Circular buffer size is 32 bytes. */
00055     kEDMA_Modulo64bytes ,        /*!< Circular buffer size is 64 bytes. */
00056     kEDMA_Modulo128bytes ,       /*!< Circular buffer size is 128 bytes. */
00057     kEDMA_Modulo256bytes ,       /*!< Circular buffer size is 256 bytes. */
00058     kEDMA_Modulo512bytes ,       /*!< Circular buffer size is 512 bytes. */
00059     kEDMA_Modulo1Kbytes ,        /*!< Circular buffer size is 1 K bytes. */
00060     kEDMA_Modulo2Kbytes ,        /*!< Circular buffer size is 2 K bytes. */
00061     kEDMA_Modulo4Kbytes ,        /*!< Circular buffer size is 4 K bytes. */
00062     kEDMA_Modulo8Kbytes ,        /*!< Circular buffer size is 8 K bytes. */
00063     kEDMA_Modulo16Kbytes ,       /*!< Circular buffer size is 16 K bytes. */
00064     kEDMA_Modulo32Kbytes ,       /*!< Circular buffer size is 32 K bytes. */
00065     kEDMA_Modulo64Kbytes ,       /*!< Circular buffer size is 64 K bytes. */
00066     kEDMA_Modulo128Kbytes ,      /*!< Circular buffer size is 128 K bytes. */
00067     kEDMA_Modulo256Kbytes ,      /*!< Circular buffer size is 256 K bytes. */
00068     kEDMA_Modulo512Kbytes ,      /*!< Circular buffer size is 512 K bytes. */
00069     kEDMA_Modulo1Mbytes ,        /*!< Circular buffer size is 1 M bytes. */
00070     kEDMA_Modulo2Mbytes ,        /*!< Circular buffer size is 2 M bytes. */
00071     kEDMA_Modulo4Mbytes ,        /*!< Circular buffer size is 4 M bytes. */
00072     kEDMA_Modulo8Mbytes ,        /*!< Circular buffer size is 8 M bytes. */
00073     kEDMA_Modulo16Mbytes ,       /*!< Circular buffer size is 16 M bytes. */
00074     kEDMA_Modulo32Mbytes ,       /*!< Circular buffer size is 32 M bytes. */
00075     kEDMA_Modulo64Mbytes ,       /*!< Circular buffer size is 64 M bytes. */
00076     kEDMA_Modulo128Mbytes ,      /*!< Circular buffer size is 128 M bytes. */
00077     kEDMA_Modulo256Mbytes ,      /*!< Circular buffer size is 256 M bytes. */
00078     kEDMA_Modulo512Mbytes ,      /*!< Circular buffer size is 512 M bytes. */
00079     kEDMA_Modulo1Gbytes ,        /*!< Circular buffer size is 1 G bytes. */
00080     kEDMA_Modulo2Gbytes ,        /*!< Circular buffer size is 2 G bytes. */
00081 } edma_modulo_t;
00082 
00083 /*! @brief Bandwidth control */
00084 typedef enum _edma_bandwidth
00085 {
00086     kEDMA_BandwidthStallNone  = 0x0U,   /*!< No eDMA engine stalls. */
00087     kEDMA_BandwidthStall4Cycle  = 0x2U, /*!< eDMA engine stalls for 4 cycles after each read/write. */
00088     kEDMA_BandwidthStall8Cycle  = 0x3U, /*!< eDMA engine stalls for 8 cycles after each read/write. */
00089 } edma_bandwidth_t;
00090 
00091 /*! @brief Channel link type */
00092 typedef enum _edma_channel_link_type
00093 {
00094     kEDMA_LinkNone  = 0x0U, /*!< No channel link  */
00095     kEDMA_MinorLink ,       /*!< Channel link after each minor loop */
00096     kEDMA_MajorLink ,       /*!< Channel link while major loop count exhausted */
00097 } edma_channel_link_type_t;
00098 
00099 /*!@brief eDMA channel status flags. */
00100 enum _edma_channel_status_flags
00101 {
00102     kEDMA_DoneFlag  = 0x1U,      /*!< DONE flag, set while transfer finished, CITER value exhausted*/
00103     kEDMA_ErrorFlag  = 0x2U,     /*!< eDMA error flag, an error occurred in a transfer */
00104     kEDMA_InterruptFlag  = 0x4U, /*!< eDMA interrupt flag, set while an interrupt occurred of this channel */
00105 };
00106 
00107 /*! @brief eDMA channel error status flags. */
00108 enum _edma_error_status_flags
00109 {
00110     kEDMA_DestinationBusErrorFlag  = DMA_ES_DBE_MASK,    /*!< Bus error on destination address */
00111     kEDMA_SourceBusErrorFlag  = DMA_ES_SBE_MASK,         /*!< Bus error on the source address */
00112     kEDMA_ScatterGatherErrorFlag  = DMA_ES_SGE_MASK,     /*!< Error on the Scatter/Gather address, not 32byte aligned. */
00113     kEDMA_NbytesErrorFlag  = DMA_ES_NCE_MASK,            /*!< NBYTES/CITER configuration error */
00114     kEDMA_DestinationOffsetErrorFlag  = DMA_ES_DOE_MASK, /*!< Destination offset not aligned with destination size */
00115     kEDMA_DestinationAddressErrorFlag  = DMA_ES_DAE_MASK, /*!< Destination address not aligned with destination size */
00116     kEDMA_SourceOffsetErrorFlag  = DMA_ES_SOE_MASK,       /*!< Source offset not aligned with source size */
00117     kEDMA_SourceAddressErrorFlag  = DMA_ES_SAE_MASK,      /*!< Source address not aligned with source size*/
00118     kEDMA_ErrorChannelFlag  = DMA_ES_ERRCHN_MASK,         /*!< Error channel number of the cancelled channel number */
00119     kEDMA_ChannelPriorityErrorFlag  = DMA_ES_CPE_MASK,    /*!< Channel priority is not unique. */
00120     kEDMA_TransferCanceledFlag  = DMA_ES_ECX_MASK,        /*!< Transfer cancelled */
00121 #if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1
00122     kEDMA_GroupPriorityErrorFlag  = DMA_ES_GPE_MASK, /*!< Group priority is not unique. */
00123 #endif
00124     kEDMA_ValidFlag  = (int)DMA_ES_VLD_MASK, /*!< No error occurred, this bit is 0. Otherwise, it is 1. */
00125 };
00126 
00127 /*! @brief eDMA interrupt source */
00128 typedef enum _edma_interrupt_enable
00129 {
00130     kEDMA_ErrorInterruptEnable  = 0x1U,                  /*!< Enable interrupt while channel error occurs. */
00131     kEDMA_MajorInterruptEnable  = DMA_CSR_INTMAJOR_MASK, /*!< Enable interrupt while major count exhausted. */
00132     kEDMA_HalfInterruptEnable  = DMA_CSR_INTHALF_MASK,   /*!< Enable interrupt while major count to half value. */
00133 } edma_interrupt_enable_t;
00134 
00135 /*! @brief eDMA transfer type */
00136 typedef enum _edma_transfer_type
00137 {
00138     kEDMA_MemoryToMemory  = 0x0U, /*!< Transfer from memory to memory */
00139     kEDMA_PeripheralToMemory ,    /*!< Transfer from peripheral to memory */
00140     kEDMA_MemoryToPeripheral ,    /*!< Transfer from memory to peripheral */
00141 } edma_transfer_type_t;
00142 
00143 /*! @brief eDMA transfer status */
00144 enum _edma_transfer_status
00145 {
00146     kStatus_EDMA_QueueFull  = MAKE_STATUS(kStatusGroup_EDMA , 0), /*!< TCD queue is full. */
00147     kStatus_EDMA_Busy  = MAKE_STATUS(kStatusGroup_EDMA , 1),      /*!< Channel is busy and can't handle the
00148                                                                      transfer request. */
00149 };
00150 
00151 /*! @brief eDMA global configuration structure.*/
00152 typedef struct _edma_config
00153 {
00154     bool enableContinuousLinkMode ;    /*!< Enable (true) continuous link mode. Upon minor loop completion, the channel
00155                                            activates again if that channel has a minor loop channel link enabled and
00156                                            the link channel is itself. */
00157     bool enableHaltOnError ;           /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set.
00158                                            Subsequently, all service requests are ignored until the HALT bit is cleared.*/
00159     bool enableRoundRobinArbitration ; /*!< Enable (true) round robin channel arbitration method or fixed priority
00160                                            arbitration is used for channel selection */
00161     bool enableDebugMode ; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of
00162                                a new channel. Executing channels are allowed to complete. */
00163 } edma_config_t;
00164 
00165 /*!
00166  * @brief eDMA transfer configuration
00167  *
00168  * This structure configures the source/destination transfer attribute.
00169  */
00170 typedef struct _edma_transfer_config
00171 {
00172     uint32_t srcAddr ;                      /*!< Source data address. */
00173     uint32_t destAddr ;                     /*!< Destination data address. */
00174     edma_transfer_size_t srcTransferSize ;  /*!< Source data transfer size. */
00175     edma_transfer_size_t destTransferSize ; /*!< Destination data transfer size. */
00176     int16_t srcOffset ;                     /*!< Sign-extended offset applied to the current source address to
00177                                                 form the next-state value as each source read is completed. */
00178     int16_t destOffset ;                    /*!< Sign-extended offset applied to the current destination address to
00179                                                 form the next-state value as each destination write is completed. */
00180     uint32_t minorLoopBytes ;               /*!< Bytes to transfer in a minor loop*/
00181     uint32_t majorLoopCounts ;              /*!< Major loop iteration count. */
00182 } edma_transfer_config_t;
00183 
00184 /*! @brief eDMA channel priority configuration */
00185 typedef struct _edma_channel_Preemption_config
00186 {
00187     bool enableChannelPreemption ; /*!< If true: a channel can be suspended by other channel with higher priority */
00188     bool enablePreemptAbility ;    /*!< If true: a channel can suspend other channel with low priority */
00189     uint8_t channelPriority ;      /*!< Channel priority */
00190 } edma_channel_Preemption_config_t;
00191 
00192 /*! @brief eDMA minor offset configuration */
00193 typedef struct _edma_minor_offset_config
00194 {
00195     bool enableSrcMinorOffset ;  /*!< Enable(true) or Disable(false) source minor loop offset. */
00196     bool enableDestMinorOffset ; /*!< Enable(true) or Disable(false) destination minor loop offset. */
00197     uint32_t minorOffset ;       /*!< Offset for a minor loop mapping. */
00198 } edma_minor_offset_config_t;
00199 
00200 /*!
00201  * @brief eDMA TCD.
00202  *
00203  * This structure is same as TCD register which is described in reference manual,
00204  * and is used to configure the scatter/gather feature as a next hardware TCD.
00205  */
00206 typedef struct _edma_tcd
00207 {
00208     __IO uint32_t SADDR ;     /*!< SADDR register, used to save source address */
00209     __IO uint16_t SOFF ;      /*!< SOFF register, save offset bytes every transfer */
00210     __IO uint16_t ATTR ;      /*!< ATTR register, source/destination transfer size and modulo */
00211     __IO uint32_t NBYTES ;    /*!< Nbytes register, minor loop length in bytes */
00212     __IO uint32_t SLAST ;     /*!< SLAST register */
00213     __IO uint32_t DADDR ;     /*!< DADDR register, used for destination address */
00214     __IO uint16_t DOFF ;      /*!< DOFF register, used for destination offset */
00215     __IO uint16_t CITER ;     /*!< CITER register, current minor loop numbers, for unfinished minor loop.*/
00216     __IO uint32_t DLAST_SGA ; /*!< DLASTSGA register, next tcd address used in scatter-gather mode */
00217     __IO uint16_t CSR ;       /*!< CSR register, for TCD control status */
00218     __IO uint16_t BITER ;     /*!< BITER register, begin minor loop count. */
00219 } edma_tcd_t;
00220 
00221 /*! @brief Callback for eDMA */
00222 struct _edma_handle;
00223 
00224 /*! @brief Define callback function for eDMA.
00225  *
00226  * This callback function is called in the EDMA interrupt handle.
00227  * In normal mode, run into callback function means the transfer users need is done.
00228  * In scatter gather mode, run into callback function means a transfer control block (tcd) is finished. Not
00229  * all transfer finished, users can get the finished tcd numbers using interface EDMA_GetUnusedTCDNumber.
00230  *
00231  * @param handle EDMA handle pointer, users shall not touch the values inside.
00232  * @param userData The callback user parameter pointer. Users can use this parameter to involve things users need to
00233  *                 change in EDMA callback function.
00234  * @param transferDone If the current loaded transfer done. In normal mode it means if all transfer done. In scatter
00235  *                     gather mode, this parameter shows is the current transfer block in EDMA register is done. As the
00236  *                     load of core is different, it will be different if the new tcd loaded into EDMA registers while
00237  *                     this callback called. If true, it always means new tcd still not loaded into registers, while
00238  *                     false means new tcd already loaded into registers.
00239  * @param tcds How many tcds are done from the last callback. This parameter only used in scatter gather mode. It
00240  *             tells user how many tcds are finished between the last callback and this.
00241  */
00242 typedef void (*edma_callback)(struct _edma_handle *handle, void *userData , bool transferDone, uint32_t tcds);
00243 
00244 /*! @brief eDMA transfer handle structure */
00245 typedef struct _edma_handle
00246 {
00247     edma_callback callback ; /*!< Callback function for major count exhausted. */
00248     void *userData ;         /*!< Callback function parameter. */
00249     DMA_Type *base ;         /*!< eDMA peripheral base address. */
00250     edma_tcd_t *tcdPool ;    /*!< Pointer to memory stored TCDs. */
00251     uint8_t channel ;        /*!< eDMA channel number. */
00252     volatile int8_t header ; /*!< The first TCD index. Should point to the next TCD to be loaded into the eDMA engine. */
00253     volatile int8_t tail ;   /*!< The last TCD index. Should point to the next TCD to be stored into the memory pool. */
00254     volatile int8_t tcdUsed ; /*!< The number of used TCD slots. Should reflect the number of TCDs can be used/loaded in
00255                                 the memory. */
00256     volatile int8_t tcdSize ; /*!< The total number of TCD slots in the queue. */
00257     uint8_t flags ;           /*!< The status of the current channel. */
00258 } edma_handle_t;
00259 
00260 /*******************************************************************************
00261  * APIs
00262  ******************************************************************************/
00263 #if defined(__cplusplus)
00264 extern "C" {
00265 #endif /* __cplusplus */
00266 
00267 /*!
00268  * @name eDMA initialization and de-initialization
00269  * @{
00270  */
00271 
00272 /*!
00273  * @brief Initializes the eDMA peripheral.
00274  *
00275  * This function ungates the eDMA clock and configures the eDMA peripheral according
00276  * to the configuration structure.
00277  *
00278  * @param base eDMA peripheral base address.
00279  * @param config A pointer to the configuration structure, see "edma_config_t".
00280  * @note This function enables the minor loop map feature.
00281  */
00282 void EDMA_Init(DMA_Type *base, const edma_config_t *config);
00283 
00284 /*!
00285  * @brief Deinitializes the eDMA peripheral.
00286  *
00287  * This function gates the eDMA clock.
00288  *
00289  * @param base eDMA peripheral base address.
00290  */
00291 void EDMA_Deinit(DMA_Type *base);
00292 
00293 /*!
00294  * @brief Push content of TCD structure into hardware TCD register.
00295  *
00296  * @param base EDMA peripheral base address.
00297  * @param channel EDMA channel number.
00298  * @param tcd Point to TCD structure.
00299  */
00300 void EDMA_InstallTCD(DMA_Type *base, uint32_t channel, edma_tcd_t *tcd);
00301 
00302 /*!
00303  * @brief Gets the eDMA default configuration structure.
00304  *
00305  * This function sets the configuration structure to default values.
00306  * The default configuration is set to the following values.
00307  * @code
00308  *   config.enableContinuousLinkMode = false;
00309  *   config.enableHaltOnError = true;
00310  *   config.enableRoundRobinArbitration = false;
00311  *   config.enableDebugMode = false;
00312  * @endcode
00313  *
00314  * @param config A pointer to the eDMA configuration structure.
00315  */
00316 void EDMA_GetDefaultConfig(edma_config_t *config);
00317 
00318 /* @} */
00319 /*!
00320  * @name eDMA Channel Operation
00321  * @{
00322  */
00323 
00324 /*!
00325  * @brief Sets all TCD registers to default values.
00326  *
00327  * This function sets TCD registers for this channel to default values.
00328  *
00329  * @param base eDMA peripheral base address.
00330  * @param channel eDMA channel number.
00331  * @note This function must not be called while the channel transfer is ongoing
00332  *       or it causes unpredictable results.
00333  * @note This function enables the auto stop request feature.
00334  */
00335 void EDMA_ResetChannel(DMA_Type *base, uint32_t channel);
00336 
00337 /*!
00338  * @brief Configures the eDMA transfer attribute.
00339  *
00340  * This function configures the transfer attribute, including source address, destination address,
00341  * transfer size, address offset, and so on. It also configures the scatter gather feature if the
00342  * user supplies the TCD address.
00343  * Example:
00344  * @code
00345  *  edma_transfer_t config;
00346  *  edma_tcd_t tcd;
00347  *  config.srcAddr = ..;
00348  *  config.destAddr = ..;
00349  *  ...
00350  *  EDMA_SetTransferConfig(DMA0, channel, &config, &stcd);
00351  * @endcode
00352  *
00353  * @param base eDMA peripheral base address.
00354  * @param channel eDMA channel number.
00355  * @param config Pointer to eDMA transfer configuration structure.
00356  * @param nextTcd Point to TCD structure. It can be NULL if users
00357  *                do not want to enable scatter/gather feature.
00358  * @note If nextTcd is not NULL, it means scatter gather feature is enabled
00359  *       and DREQ bit is cleared in the previous transfer configuration, which
00360  *       is set in the eDMA_ResetChannel.
00361  */
00362 void EDMA_SetTransferConfig(DMA_Type *base,
00363                             uint32_t channel,
00364                             const edma_transfer_config_t *config,
00365                             edma_tcd_t *nextTcd);
00366 
00367 /*!
00368  * @brief Configures the eDMA minor offset feature.
00369  *
00370  * The minor offset means that the signed-extended value is added to the source address or destination
00371  * address after each minor loop.
00372  *
00373  * @param base eDMA peripheral base address.
00374  * @param channel eDMA channel number.
00375  * @param config A pointer to the minor offset configuration structure.
00376  */
00377 void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config);
00378 
00379 /*!
00380  * @brief Configures the eDMA channel preemption feature.
00381  *
00382  * This function configures the channel preemption attribute and the priority of the channel.
00383  *
00384  * @param base eDMA peripheral base address.
00385  * @param channel eDMA channel number
00386  * @param config A pointer to the channel preemption configuration structure.
00387  */
00388 static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base,
00389                                                    uint32_t channel,
00390                                                    const edma_channel_Preemption_config_t *config)
00391 {
00392     assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL);
00393     assert(config != NULL);
00394 
00395     DMA_DCHPRIn(base, channel) =
00396         (DMA_DCHPRI0_DPA(!config->enablePreemptAbility ) | DMA_DCHPRI0_ECP(config->enableChannelPreemption ) |
00397          DMA_DCHPRI0_CHPRI(config->channelPriority ));
00398 }
00399 
00400 /*!
00401  * @brief Sets the channel link for the eDMA transfer.
00402  *
00403  * This function configures either the minor link or the major link mode. The minor link means that the channel link is
00404  * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is
00405  * exhausted.
00406  *
00407  * @param base eDMA peripheral base address.
00408  * @param channel eDMA channel number.
00409  * @param type A channel link type, which can be one of the following:
00410  *   @arg kEDMA_LinkNone
00411  *   @arg kEDMA_MinorLink
00412  *   @arg kEDMA_MajorLink
00413  * @param linkedChannel The linked channel number.
00414  * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
00415  */
00416 void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel);
00417 
00418 /*!
00419  * @brief Sets the bandwidth for the eDMA transfer.
00420  *
00421  * Because the eDMA processes the minor loop, it continuously generates read/write sequences
00422  * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
00423  * each read/write access to control the bus request bandwidth seen by the crossbar switch.
00424  *
00425  * @param base eDMA peripheral base address.
00426  * @param channel eDMA channel number.
00427  * @param bandWidth A bandwidth setting, which can be one of the following:
00428  *     @arg kEDMABandwidthStallNone
00429  *     @arg kEDMABandwidthStall4Cycle
00430  *     @arg kEDMABandwidthStall8Cycle
00431  */
00432 void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth);
00433 
00434 /*!
00435  * @brief Sets the source modulo and the destination modulo for the eDMA transfer.
00436  *
00437  * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
00438  * calculation is performed or the original register value. It provides the ability to implement a circular data
00439  * queue easily.
00440  *
00441  * @param base eDMA peripheral base address.
00442  * @param channel eDMA channel number.
00443  * @param srcModulo A source modulo value.
00444  * @param destModulo A destination modulo value.
00445  */
00446 void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo);
00447 
00448 #if defined(FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT) && FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT
00449 /*!
00450  * @brief Enables an async request for the eDMA transfer.
00451  *
00452  * @param base eDMA peripheral base address.
00453  * @param channel eDMA channel number.
00454  * @param enable The command to enable (true) or disable (false).
00455  */
00456 static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable)
00457 {
00458     assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
00459 
00460     base->EARS = (base->EARS & (~(1U << channel))) | ((uint32_t)enable << channel);
00461 }
00462 #endif /* FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT */
00463 
00464 /*!
00465  * @brief Enables an auto stop request for the eDMA transfer.
00466  *
00467  * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
00468  *
00469  * @param base eDMA peripheral base address.
00470  * @param channel eDMA channel number.
00471  * @param enable The command to enable (true) or disable (false).
00472  */
00473 static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable)
00474 {
00475     assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
00476 
00477     base->TCD[channel].CSR = (base->TCD[channel].CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
00478 }
00479 
00480 /*!
00481  * @brief Enables the interrupt source for the eDMA transfer.
00482  *
00483  * @param base eDMA peripheral base address.
00484  * @param channel eDMA channel number.
00485  * @param mask The mask of interrupt source to be set. Users need to use
00486  *             the defined edma_interrupt_enable_t type.
00487  */
00488 void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
00489 
00490 /*!
00491  * @brief Disables the interrupt source for the eDMA transfer.
00492  *
00493  * @param base eDMA peripheral base address.
00494  * @param channel eDMA channel number.
00495  * @param mask The mask of the interrupt source to be set. Use
00496  *             the defined edma_interrupt_enable_t type.
00497  */
00498 void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
00499 
00500 /* @} */
00501 /*!
00502  * @name eDMA TCD Operation
00503  * @{
00504  */
00505 
00506 /*!
00507  * @brief Sets all fields to default values for the TCD structure.
00508  *
00509  * This function sets all fields for this TCD structure to default value.
00510  *
00511  * @param tcd Pointer to the TCD structure.
00512  * @note This function enables the auto stop request feature.
00513  */
00514 void EDMA_TcdReset(edma_tcd_t *tcd);
00515 
00516 /*!
00517  * @brief Configures the eDMA TCD transfer attribute.
00518  *
00519  * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers.
00520  * The STCD is used in the scatter-gather mode.
00521  * This function configures the TCD transfer attribute, including source address, destination address,
00522  * transfer size, address offset, and so on. It also configures the scatter gather feature if the
00523  * user supplies the next TCD address.
00524  * Example:
00525  * @code
00526  *   edma_transfer_t config = {
00527  *   ...
00528  *   }
00529  *   edma_tcd_t tcd __aligned(32);
00530  *   edma_tcd_t nextTcd __aligned(32);
00531  *   EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
00532  * @endcode
00533  *
00534  * @param tcd Pointer to the TCD structure.
00535  * @param config Pointer to eDMA transfer configuration structure.
00536  * @param nextTcd Pointer to the next TCD structure. It can be NULL if users
00537  *                do not want to enable scatter/gather feature.
00538  * @note TCD address should be 32 bytes aligned or it causes an eDMA error.
00539  * @note If the nextTcd is not NULL, the scatter gather feature is enabled
00540  *       and DREQ bit is cleared in the previous transfer configuration, which
00541  *       is set in the EDMA_TcdReset.
00542  */
00543 void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd);
00544 
00545 /*!
00546  * @brief Configures the eDMA TCD minor offset feature.
00547  *
00548  * A minor offset is a signed-extended value added to the source address or a destination
00549  * address after each minor loop.
00550  *
00551  * @param tcd A point to the TCD structure.
00552  * @param config A pointer to the minor offset configuration structure.
00553  */
00554 void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config);
00555 
00556 /*!
00557  * @brief Sets the channel link for the eDMA TCD.
00558  *
00559  * This function configures either a minor link or a major link. The minor link means the channel link is
00560  * triggered every time CITER decreases by 1. The major link means that the channel link  is triggered when the CITER is
00561  * exhausted.
00562  *
00563  * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
00564  * @param tcd Point to the TCD structure.
00565  * @param type Channel link type, it can be one of:
00566  *   @arg kEDMA_LinkNone
00567  *   @arg kEDMA_MinorLink
00568  *   @arg kEDMA_MajorLink
00569  * @param linkedChannel The linked channel number.
00570  */
00571 void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel);
00572 
00573 /*!
00574  * @brief Sets the bandwidth for the eDMA TCD.
00575  *
00576  * Because the eDMA processes the minor loop, it continuously generates read/write sequences
00577  * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
00578  * each read/write access to control the bus request bandwidth seen by the crossbar switch.
00579  * @param tcd A pointer to the TCD structure.
00580  * @param bandWidth A bandwidth setting, which can be one of the following:
00581  *     @arg kEDMABandwidthStallNone
00582  *     @arg kEDMABandwidthStall4Cycle
00583  *     @arg kEDMABandwidthStall8Cycle
00584  */
00585 static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWidth)
00586 {
00587     assert(tcd != NULL);
00588     assert(((uint32_t)tcd & 0x1FU) == 0);
00589 
00590     tcd->CSR  = (tcd->CSR  & (~DMA_CSR_BWC_MASK)) | DMA_CSR_BWC(bandWidth);
00591 }
00592 
00593 /*!
00594  * @brief Sets the source modulo and the destination modulo for the eDMA TCD.
00595  *
00596  * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
00597  * calculation is performed or the original register value. It provides the ability to implement a circular data
00598  * queue easily.
00599  *
00600  * @param tcd A pointer to the TCD structure.
00601  * @param srcModulo A source modulo value.
00602  * @param destModulo A destination modulo value.
00603  */
00604 void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo);
00605 
00606 /*!
00607  * @brief Sets the auto stop request for the eDMA TCD.
00608  *
00609  * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
00610  *
00611  * @param tcd A pointer to the TCD structure.
00612  * @param enable The command to enable (true) or disable (false).
00613  */
00614 static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable)
00615 {
00616     assert(tcd != NULL);
00617     assert(((uint32_t)tcd & 0x1FU) == 0);
00618 
00619     tcd->CSR  = (tcd->CSR  & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
00620 }
00621 
00622 /*!
00623  * @brief Enables the interrupt source for the eDMA TCD.
00624  *
00625  * @param tcd Point to the TCD structure.
00626  * @param mask The mask of interrupt source to be set. Users need to use
00627  *             the defined edma_interrupt_enable_t type.
00628  */
00629 void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask);
00630 
00631 /*!
00632  * @brief Disables the interrupt source for the eDMA TCD.
00633  *
00634  * @param tcd Point to the TCD structure.
00635  * @param mask The mask of interrupt source to be set. Users need to use
00636  *             the defined edma_interrupt_enable_t type.
00637  */
00638 void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask);
00639 
00640 /*! @} */
00641 /*!
00642  * @name eDMA Channel Transfer Operation
00643  * @{
00644  */
00645 
00646 /*!
00647  * @brief Enables the eDMA hardware channel request.
00648  *
00649  * This function enables the hardware channel request.
00650  *
00651  * @param base eDMA peripheral base address.
00652  * @param channel eDMA channel number.
00653  */
00654 static inline void EDMA_EnableChannelRequest(DMA_Type *base, uint32_t channel)
00655 {
00656     assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
00657 
00658     base->SERQ = DMA_SERQ_SERQ(channel);
00659 }
00660 
00661 /*!
00662  * @brief Disables the eDMA hardware channel request.
00663  *
00664  * This function disables the hardware channel request.
00665  *
00666  * @param base eDMA peripheral base address.
00667  * @param channel eDMA channel number.
00668  */
00669 static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel)
00670 {
00671     assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
00672 
00673     base->CERQ = DMA_CERQ_CERQ(channel);
00674 }
00675 
00676 /*!
00677  * @brief Starts the eDMA transfer by using the software trigger.
00678  *
00679  * This function starts a minor loop transfer.
00680  *
00681  * @param base eDMA peripheral base address.
00682  * @param channel eDMA channel number.
00683  */
00684 static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel)
00685 {
00686     assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
00687 
00688     base->SSRT = DMA_SSRT_SSRT(channel);
00689 }
00690 
00691 /*! @} */
00692 /*!
00693  * @name eDMA Channel Status Operation
00694  * @{
00695  */
00696 
00697 /*!
00698  * @brief Gets the remaining major loop count from the eDMA current channel TCD.
00699  *
00700  * This function checks the TCD (Task Control Descriptor) status for a specified
00701  * eDMA channel and returns the number of major loop count that has not finished.
00702  *
00703  * @param base eDMA peripheral base address.
00704  * @param channel eDMA channel number.
00705  * @return Major loop count which has not been transferred yet for the current TCD.
00706  * @note 1. This function can only be used to get unfinished major loop count of transfer without
00707  *          the next TCD, or it might be inaccuracy.
00708  *       2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while
00709  *          the channel is running.
00710  *          Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO
00711  *          register is needed while the eDMA IP does not support getting it while a channel is active.
00712  *          In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine
00713  *          is working with while a channel is running.
00714  *          Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example
00715  *          copied before enabling the channel) is needed. The formula to calculate it is shown below:
00716  *          RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
00717  */
00718 uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel);
00719 
00720 /*!
00721  * @brief Gets the eDMA channel error status flags.
00722  *
00723  * @param base eDMA peripheral base address.
00724  * @return The mask of error status flags. Users need to use the
00725 *         _edma_error_status_flags type to decode the return variables.
00726  */
00727 static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base)
00728 {
00729     return base->ES;
00730 }
00731 
00732 /*!
00733  * @brief Gets the eDMA channel status flags.
00734  *
00735  * @param base eDMA peripheral base address.
00736  * @param channel eDMA channel number.
00737  * @return The mask of channel status flags. Users need to use the
00738  *         _edma_channel_status_flags type to decode the return variables.
00739  */
00740 uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel);
00741 
00742 /*!
00743  * @brief Clears the eDMA channel status flags.
00744  *
00745  * @param base eDMA peripheral base address.
00746  * @param channel eDMA channel number.
00747  * @param mask The mask of channel status to be cleared. Users need to use
00748  *             the defined _edma_channel_status_flags type.
00749  */
00750 void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask);
00751 
00752 /*! @} */
00753 /*!
00754  * @name eDMA Transactional Operation
00755  */
00756 
00757 /*!
00758  * @brief Creates the eDMA handle.
00759  *
00760  * This function is called if using the transactional API for eDMA. This function
00761  * initializes the internal state of the eDMA handle.
00762  *
00763  * @param handle eDMA handle pointer. The eDMA handle stores callback function and
00764  *               parameters.
00765  * @param base eDMA peripheral base address.
00766  * @param channel eDMA channel number.
00767  */
00768 void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel);
00769 
00770 /*!
00771  * @brief Installs the TCDs memory pool into the eDMA handle.
00772  *
00773  * This function is called after the EDMA_CreateHandle to use scatter/gather feature. This function shall only be used
00774  * while users need to use scatter gather mode. Scatter gather mode enables EDMA to load a new transfer control block
00775  * (tcd) in hardware, and automatically reconfigure that DMA channel for a new transfer.
00776  * Users need to prepare tcd memory and also configure tcds using interface EDMA_SubmitTransfer.
00777  *
00778  * @param handle eDMA handle pointer.
00779  * @param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned.
00780  * @param tcdSize The number of TCD slots.
00781  */
00782 void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize);
00783 
00784 /*!
00785  * @brief Installs a callback function for the eDMA transfer.
00786  *
00787  * This callback is called in the eDMA IRQ handler. Use the callback to do something after
00788  * the current major loop transfer completes. This function will be called every time one tcd finished transfer.
00789  *
00790  * @param handle eDMA handle pointer.
00791  * @param callback eDMA callback function pointer.
00792  * @param userData A parameter for the callback function.
00793  */
00794 void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData);
00795 
00796 /*!
00797  * @brief Prepares the eDMA transfer structure.
00798  *
00799  * This function prepares the transfer configuration structure according to the user input.
00800  *
00801  * @param config The user configuration structure of type edma_transfer_t.
00802  * @param srcAddr eDMA transfer source address.
00803  * @param srcWidth eDMA transfer source address width(bytes).
00804  * @param destAddr eDMA transfer destination address.
00805  * @param destWidth eDMA transfer destination address width(bytes).
00806  * @param bytesEachRequest eDMA transfer bytes per channel request.
00807  * @param transferBytes eDMA transfer bytes to be transferred.
00808  * @param type eDMA transfer type.
00809  * @note The data address and the data width must be consistent. For example, if the SRC
00810  *       is 4 bytes, the source address must be 4 bytes aligned, or it results in
00811  *       source address error (SAE).
00812  */
00813 void EDMA_PrepareTransfer(edma_transfer_config_t *config,
00814                           void *srcAddr,
00815                           uint32_t srcWidth,
00816                           void *destAddr,
00817                           uint32_t destWidth,
00818                           uint32_t bytesEachRequest,
00819                           uint32_t transferBytes,
00820                           edma_transfer_type_t type);
00821 
00822 /*!
00823  * @brief Submits the eDMA transfer request.
00824  *
00825  * This function submits the eDMA transfer request according to the transfer configuration structure.
00826  * In scatter gather mode, call this function will add a configured tcd to the circular list of tcd pool.
00827  * The tcd pools is setup by call function EDMA_InstallTCDMemory before.
00828  *
00829  * @param handle eDMA handle pointer.
00830  * @param config Pointer to eDMA transfer configuration structure.
00831  * @retval kStatus_EDMA_Success It means submit transfer request succeed.
00832  * @retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
00833  * @retval kStatus_EDMA_Busy It means the given channel is busy, need to submit request later.
00834  */
00835 status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config);
00836 
00837 /*!
00838  * @brief eDMA starts transfer.
00839  *
00840  * This function enables the channel request. Users can call this function after submitting the transfer request
00841  * or before submitting the transfer request.
00842  *
00843  * @param handle eDMA handle pointer.
00844  */
00845 void EDMA_StartTransfer(edma_handle_t *handle);
00846 
00847 /*!
00848  * @brief eDMA stops transfer.
00849  *
00850  * This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer()
00851  * again to resume the transfer.
00852  *
00853  * @param handle eDMA handle pointer.
00854  */
00855 void EDMA_StopTransfer(edma_handle_t *handle);
00856 
00857 /*!
00858  * @brief eDMA aborts transfer.
00859  *
00860  * This function disables the channel request and clear transfer status bits.
00861  * Users can submit another transfer after calling this API.
00862  *
00863  * @param handle DMA handle pointer.
00864  */
00865 void EDMA_AbortTransfer(edma_handle_t *handle);
00866 
00867 /*!
00868  * @brief Get unused TCD slot number.
00869  *
00870  * This function gets current tcd index which is run. If the TCD pool pointer is NULL, it will return 0.
00871  *
00872  * @param handle DMA handle pointer.
00873  * @return The unused tcd slot number.
00874  */
00875 static inline uint32_t EDMA_GetUnusedTCDNumber(edma_handle_t *handle)
00876 {
00877     return (handle->tcdSize  - handle->tcdUsed );
00878 }
00879 
00880 /*!
00881  * @brief Get the next tcd address.
00882  *
00883  * This function gets the next tcd address. If this is last TCD, return 0.
00884  *
00885  * @param handle DMA handle pointer.
00886  * @return The next TCD address.
00887  */
00888 static inline uint32_t EDMA_GetNextTCDAddress(edma_handle_t *handle)
00889 {
00890     return (handle->base ->TCD[handle->channel ].DLAST_SGA);
00891 }
00892 
00893 /*!
00894  * @brief eDMA IRQ handler for the current major loop transfer completion.
00895  *
00896  * This function clears the channel major interrupt flag and calls
00897  * the callback function if it is not NULL.
00898  *
00899  * Note:
00900  * For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed.
00901  * These include the final address adjustments and reloading of the BITER field into the CITER.
00902  * Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from
00903  * memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled).
00904  *
00905  * For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine.
00906  * As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index
00907  * in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be
00908  * (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have
00909  * been loaded into the eDMA engine at this point already.).
00910  *
00911  * For the last two continuous ISRs in a scatter/gather process, they  both load the last TCD (The last ISR does not
00912  * load a new TCD) from the memory pool to the eDMA engine when major loop completes.
00913  * Therefore, ensure that the header and tcdUsed updated are identical for them.
00914  * tcdUsed are both 0 in this case as no TCD to be loaded.
00915  *
00916  * See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for
00917  * further details.
00918  *
00919  * @param handle eDMA handle pointer.
00920  */
00921 void EDMA_HandleIRQ(edma_handle_t *handle);
00922 
00923 /* @} */
00924 
00925 #if defined(__cplusplus)
00926 }
00927 #endif /* __cplusplus */
00928 
00929 /* @} */
00930 
00931 #endif /*_FSL_EDMA_H_*/