Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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_*/
Generated on Tue Jul 12 2022 15:37:17 by
