1 /*
2  * Copyright 2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_edma.h"
9 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
10 #include "fsl_memory.h"
11 #endif
12 
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.edma4"
20 #endif
21 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
22 #define CONVERT_TO_DMA_ADDRESS(addr) (MEMORY_ConvertMemoryMapAddress((uint32_t)(addr), kMEMORY_Local2DMA))
23 #else
24 #define CONVERT_TO_DMA_ADDRESS(addr) ((uint32_t)(addr))
25 #endif
26 #if defined(DMA_RSTS_N)
27 #define EDMA_RESETS_ARRAY DMA_RSTS_N
28 #endif
29 /*******************************************************************************
30  * Prototypes
31  ******************************************************************************/
32 /*!
33  * @brief Map transfer width.
34  *
35  * @param width transfer width.
36  */
37 static edma_transfer_size_t EDMA_TransferWidthMapping(uint32_t width);
38 
39 /*!
40  * @brief validate edma errata.
41  *
42  * @param base edma base address.
43  * @param tcd edma transfer content descriptor.
44  */
45 #if defined FSL_FEATURE_EDMA_HAS_ERRATA_51327
46 static inline status_t EDMA_CheckErrata(EDMA_Type *base, edma_tcd_t *tcd);
47 #endif
48 /*******************************************************************************
49  * Variables
50  ******************************************************************************/
51 /*! @brief Array to map EDMA instance number to base pointer. */
52 static EDMA_Type *const s_edmaBases[] = EDMA_BASE_PTRS;
53 
54 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
55 /*! @brief Array to map EDMA instance number to clock name. */
56 static const clock_ip_name_t s_edmaClockName[] = EDMA_CLOCKS;
57 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
58 
59 #if defined(EDMA_RESETS_ARRAY)
60 /* Reset array */
61 static const reset_ip_name_t s_edmaResets[] = EDMA_RESETS_ARRAY;
62 #endif
63 
64 /*! @brief Array to map EDMA instance number to IRQ number. */
65 static const IRQn_Type s_edmaIRQNumber[][FSL_FEATURE_EDMA_MODULE_CHANNEL] = EDMA_CHN_IRQS;
66 
67 /*! @brief Pointers to transfer handle for each EDMA channel. */
68 static edma_handle_t *s_EDMAHandle[FSL_FEATURE_SOC_EDMA_COUNT][FSL_FEATURE_EDMA_MODULE_CHANNEL];
69 /*******************************************************************************
70  * Code
71  ******************************************************************************/
EDMA_GetInstance(EDMA_Type * base)72 static uint32_t EDMA_GetInstance(EDMA_Type *base)
73 {
74     uint32_t instance;
75 
76     /* Find the instance index from base address mappings. */
77     for (instance = 0; instance < ARRAY_SIZE(s_edmaBases); instance++)
78     {
79         if (s_edmaBases[instance] == base)
80         {
81             break;
82         }
83     }
84 
85     assert(instance < ARRAY_SIZE(s_edmaBases));
86 
87     return instance;
88 }
89 
90 #if defined FSL_FEATURE_EDMA_HAS_ERRATA_51327
EDMA_CheckErrata(EDMA_Type * base,edma_tcd_t * tcd)91 static inline status_t EDMA_CheckErrata(EDMA_Type *base, edma_tcd_t *tcd)
92 {
93     status_t status = kStatus_Success;
94     /* errata 51327: to use scatter gather feature, NBYTES must be multiple of 8 */
95     if ((uint32_t)FSL_FEATURE_EDMA_INSTANCE_HAS_ERRATA_51327n(base) == 1U)
96     {
97         if ((EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base)) % 8U) != 0U)
98         {
99             assert(false);
100             status = kStatus_InvalidArgument;
101         }
102     }
103 
104     return status;
105 }
106 #endif
107 
108 /*!
109  * brief Push content of TCD structure into hardware TCD register.
110  *
111  * param base EDMA peripheral base address.
112  * param channel EDMA channel number.
113  * param tcd Point to TCD structure.
114  */
EDMA_InstallTCD(EDMA_Type * base,uint32_t channel,edma_tcd_t * tcd)115 void EDMA_InstallTCD(EDMA_Type *base, uint32_t channel, edma_tcd_t *tcd)
116 {
117     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
118     assert(tcd != NULL);
119 
120     edma_tcd_t *tcdRegs = EDMA_TCD_BASE(base, channel);
121 
122 #if defined FSL_FEATURE_EDMA_HAS_ERRATA_51327
123     if ((EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base)) != 0U) &&
124         ((EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) & (uint16_t)DMA_CSR_ESG_MASK) != 0U) &&
125         (EDMA_CheckErrata(base, tcd) != kStatus_Success))
126     {
127         assert(false);
128     }
129 #endif
130 
131     /* Clear DONE bit first, otherwise ESG cannot be set */
132     DMA_CLEAR_DONE_STATUS(base, channel);
133     /* Push tcd into hardware TCD register */
134     EDMA_TCD_SADDR(tcdRegs, EDMA_TCD_TYPE(base))     = EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE(base));
135     EDMA_TCD_SOFF(tcdRegs, EDMA_TCD_TYPE(base))      = EDMA_TCD_SOFF(tcd, EDMA_TCD_TYPE(base));
136     EDMA_TCD_ATTR(tcdRegs, EDMA_TCD_TYPE(base))      = EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base));
137     EDMA_TCD_NBYTES(tcdRegs, EDMA_TCD_TYPE(base))    = EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base));
138     EDMA_TCD_SLAST(tcdRegs, EDMA_TCD_TYPE(base))     = EDMA_TCD_SLAST(tcd, EDMA_TCD_TYPE(base));
139     EDMA_TCD_DADDR(tcdRegs, EDMA_TCD_TYPE(base))     = EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE(base));
140     EDMA_TCD_DOFF(tcdRegs, EDMA_TCD_TYPE(base))      = EDMA_TCD_DOFF(tcd, EDMA_TCD_TYPE(base));
141     EDMA_TCD_CITER(tcdRegs, EDMA_TCD_TYPE(base))     = EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base));
142     EDMA_TCD_DLAST_SGA(tcdRegs, EDMA_TCD_TYPE(base)) = EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base));
143     EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(base))       = EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base));
144     EDMA_TCD_BITER(tcdRegs, EDMA_TCD_TYPE(base))     = EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base));
145 }
146 
147 /*!
148  * brief Initializes the eDMA peripheral.
149  *
150  * This function ungates the eDMA clock and configures the eDMA peripheral according
151  * to the configuration structure.
152  *
153  * param base eDMA peripheral base address.
154  * param config A pointer to the configuration structure, see "edma_config_t".
155  * note This function enables the minor loop map feature.
156  */
EDMA_Init(EDMA_Type * base,const edma_config_t * config)157 void EDMA_Init(EDMA_Type *base, const edma_config_t *config)
158 {
159     assert(config != NULL);
160     assert(FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base) != -1);
161 
162     uint32_t tmpreg, i = 0U;
163 
164 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
165     /* Ungate EDMA peripheral clock */
166     CLOCK_EnableClock(s_edmaClockName[EDMA_GetInstance(base)]);
167 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
168 
169 #if defined(EDMA_RESETS_ARRAY)
170     RESET_ReleasePeripheralReset(s_edmaResets[EDMA_GetInstance(base)]);
171 #endif
172 
173 #if defined(FSL_EDMA_SOC_IP_EDMA) && FSL_EDMA_SOC_IP_EDMA
174     /* clear all the enabled request, status to make sure EDMA status is in normal condition */
175     EDMA_BASE(base)->ERQ = 0U;
176     EDMA_BASE(base)->INT = 0xFFFFFFFFU;
177     EDMA_BASE(base)->ERR = 0xFFFFFFFFU;
178     /* Configure EDMA peripheral according to the configuration structure. */
179     tmpreg = EDMA_BASE(base)->CR;
180     tmpreg &= ~(DMA_CR_ERCA_MASK | DMA_CR_HOE_MASK | DMA_CR_CLM_MASK | DMA_CR_EDBG_MASK);
181     tmpreg |= (DMA_CR_ERCA(config->enableRoundRobinArbitration) | DMA_CR_HOE(config->enableHaltOnError) |
182                DMA_CR_CLM(config->enableContinuousLinkMode) | DMA_CR_EDBG(config->enableDebugMode) | DMA_CR_EMLM(1U));
183     EDMA_BASE(base)->CR = tmpreg;
184 #else
185     tmpreg = EDMA_MP_BASE(base)->MP_CSR;
186 #if defined FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION && FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION
187     tmpreg = (tmpreg & ~(DMA_MP_CSR_HAE_MASK | DMA_MP_CSR_ERCA_MASK | DMA_MP_CSR_EDBG_MASK | DMA_MP_CSR_GCLC_MASK |
188                          DMA_MP_CSR_GMRC_MASK | DMA_MP_CSR_HALT_MASK)) |
189              DMA_MP_CSR_GMRC(config->enableMasterIdReplication) | DMA_MP_CSR_HAE(config->enableHaltOnError) |
190              DMA_MP_CSR_ERCA(config->enableRoundRobinArbitration) | DMA_MP_CSR_EDBG(config->enableDebugMode) |
191              DMA_MP_CSR_GCLC(config->enableGlobalChannelLink);
192 #else
193     tmpreg = (tmpreg & ~(DMA_MP_CSR_HAE_MASK | DMA_MP_CSR_ERCA_MASK | DMA_MP_CSR_EDBG_MASK | DMA_MP_CSR_GCLC_MASK |
194                          DMA_MP_CSR_HALT_MASK)) |
195              DMA_MP_CSR_HAE(config->enableHaltOnError) | DMA_MP_CSR_ERCA(config->enableRoundRobinArbitration) |
196              DMA_MP_CSR_EDBG(config->enableDebugMode) | DMA_MP_CSR_GCLC(config->enableGlobalChannelLink);
197 #endif
198     EDMA_MP_BASE(base)->MP_CSR = tmpreg;
199 
200 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG && FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG
201     /* channel transfer configuration */
202     for (i = 0U; i < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base); i++)
203     {
204         if (config->channelConfig[i] != NULL)
205         {
206             EDMA_InitChannel(base, i, config->channelConfig[i]);
207         }
208     }
209 #endif
210 #endif
211 }
212 
213 /*!
214  * brief Deinitializes the eDMA peripheral.
215  *
216  * This function gates the eDMA clock.
217  *
218  * param base eDMA peripheral base address.
219  */
EDMA_Deinit(EDMA_Type * base)220 void EDMA_Deinit(EDMA_Type *base)
221 {
222 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
223     /* Gate EDMA peripheral clock */
224     CLOCK_DisableClock(s_edmaClockName[EDMA_GetInstance(base)]);
225 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
226 }
227 
228 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG && FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG
229 /*!
230  * brief EDMA Channel initialization
231  *
232  * param base eDMA peripheral base address.
233  * param channel eDMA channel number.
234  * param channelConfig pointer to user's eDMA channel config structure, see edma_channel_config_t for detail.
235  */
EDMA_InitChannel(EDMA_Type * base,uint32_t channel,edma_channel_config_t * channelConfig)236 void EDMA_InitChannel(EDMA_Type *base, uint32_t channel, edma_channel_config_t *channelConfig)
237 {
238     assert(channelConfig != NULL);
239 
240     EDMA_SetChannelPreemptionConfig(base, channel, &channelConfig->channelPreemptionConfig);
241 
242 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_SWAP_SIZE && FSL_FEATURE_EDMA_HAS_CHANNEL_SWAP_SIZE
243     EDMA_SetChannelSwapSize(base, channel, channelConfig->channelSwapSize);
244 #endif
245 
246 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_MEMORY_ATTRIBUTE && FSL_FEATURE_EDMA_HAS_CHANNEL_MEMORY_ATTRIBUTE
247     EDMA_SetChannelMemoryAttribute(base, channel, channelConfig->channelWriteMemoryAttribute,
248                                    channelConfig->channelReadMemoryAttribute);
249 #endif
250 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_SIGN_EXTENSION && FSL_FEATURE_EDMA_HAS_CHANNEL_SIGN_EXTENSION
251     EDMA_SetChannelSignExtension(base, channel, channelConfig->channelDataSignExtensionBitPosition);
252 #endif
253 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_ACCESS_TYPE && FSL_FEATURE_EDMA_HAS_CHANNEL_ACCESS_TYPE
254     EDMA_SetChannelAccessType(base, channel, channelConfig->channelAccessType);
255 #endif
256 
257 #if (defined FSL_FEATURE_EDMA_HAS_CHANNEL_MUX && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) || \
258     (defined FSL_FEATURE_EDMA_HAS_MP_CHANNEL_MUX && FSL_FEATURE_EDMA_HAS_MP_CHANNEL_MUX)
259     if (0U != (uint32_t)channelConfig->channelRequestSource)
260     {
261         /* dma request source */
262         EDMA_SetChannelMux(base, channel, (int32_t)channelConfig->channelRequestSource);
263     }
264 #endif
265 
266     /* master ID replication */
267     EDMA_EnableChannelMasterIDReplication(base, channel, channelConfig->enableMasterIDReplication);
268 #if !(defined(FSL_FEATURE_EDMA_HAS_NO_CH_SBR_SEC) && FSL_FEATURE_EDMA_HAS_NO_CH_SBR_SEC)
269     /* dma transfer security level */
270     EDMA_SetChannelSecurityLevel(base, channel, channelConfig->securityLevel);
271 #endif
272     /* dma transfer protection level */
273     EDMA_SetChannelProtectionLevel(base, channel, channelConfig->protectionLevel);
274 }
275 #endif
276 
277 /*!
278  * brief Gets the eDMA default configuration structure.
279  *
280  * This function sets the configuration structure to default values.
281  * The default configuration is set to the following values.
282  * code
283  *   config.enableContinuousLinkMode = false;
284  *   config.enableHaltOnError = true;
285  *   config.enableRoundRobinArbitration = false;
286  *   config.enableDebugMode = false;
287  * endcode
288  *
289  * param config A pointer to the eDMA configuration structure.
290  */
EDMA_GetDefaultConfig(edma_config_t * config)291 void EDMA_GetDefaultConfig(edma_config_t *config)
292 {
293     assert(config != NULL);
294 
295     /* Initializes the configure structure to zero. */
296     (void)memset(config, 0, sizeof(*config));
297 
298     config->enableRoundRobinArbitration = false;
299 
300     config->enableHaltOnError = true;
301 
302 #if defined FSL_FEATURE_EDMA_HAS_CONTINUOUS_LINK_MODE && FSL_FEATURE_EDMA_HAS_CONTINUOUS_LINK_MODE
303     config->enableContinuousLinkMode = false;
304 #endif
305 
306 #if defined FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION && FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION
307     config->enableMasterIdReplication = false;
308 #endif
309 
310     config->enableDebugMode = false;
311 
312     config->enableGlobalChannelLink = true;
313 }
314 
315 /*!
316  * brief Sets all TCD registers to default values.
317  *
318  * This function sets TCD registers for this channel to default values.
319  *
320  * param base eDMA peripheral base address.
321  * param channel eDMA channel number.
322  * note This function must not be called while the channel transfer is ongoing
323  *       or it causes unpredictable results.
324  * note This function enables the auto stop request feature.
325  */
EDMA_ResetChannel(EDMA_Type * base,uint32_t channel)326 void EDMA_ResetChannel(EDMA_Type *base, uint32_t channel)
327 {
328     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
329 
330     /* reset channel CSR  */
331     EDMA_ClearChannelStatusFlags(base, channel, (uint32_t)kEDMA_DoneFlag | (uint32_t)kEDMA_ErrorFlag);
332     /* reset channel TCD  */
333     EDMA_TcdResetExt(base, EDMA_TCD_BASE(base, channel));
334 }
335 
336 /*!
337  * brief Configures the eDMA transfer attribute.
338  *
339  * This function configures the transfer attribute, including source address, destination address,
340  * transfer size, address offset, and so on. It also configures the scatter gather feature if the
341  * user supplies the TCD address.
342  * Example:
343  * code
344  *  edma_transfer_t config;
345  *  edma_tcd_t tcd;
346  *  config.srcAddr = ..;
347  *  config.destAddr = ..;
348  *  ...
349  *  EDMA_SetTransferConfig(DMA0, channel, &config, &stcd);
350  * endcode
351  *
352  * param base eDMA peripheral base address.
353  * param channel eDMA channel number.
354  * param config Pointer to eDMA transfer configuration structure.
355  * param nextTcd Point to TCD structure. It can be NULL if users
356  *                do not want to enable scatter/gather feature.
357  * note If nextTcd is not NULL, it means scatter gather feature is enabled
358  *       and DREQ bit is cleared in the previous transfer configuration, which
359  *       is set in the eDMA_ResetChannel.
360  */
EDMA_SetTransferConfig(EDMA_Type * base,uint32_t channel,const edma_transfer_config_t * config,edma_tcd_t * nextTcd)361 void EDMA_SetTransferConfig(EDMA_Type *base,
362                             uint32_t channel,
363                             const edma_transfer_config_t *config,
364                             edma_tcd_t *nextTcd)
365 {
366     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
367     assert(config != NULL);
368 
369     EDMA_TcdSetTransferConfigExt(base, EDMA_TCD_BASE(base, channel), config,
370                                  (edma_tcd_t *)CONVERT_TO_DMA_ADDRESS(nextTcd));
371 }
372 
373 /*!
374  * brief Configures the eDMA minor offset feature.
375  *
376  * The minor offset means that the signed-extended value is added to the source address or destination
377  * address after each minor loop.
378  *
379  * param base eDMA peripheral base address.
380  * param channel eDMA channel number.
381  * param config A pointer to the minor offset configuration structure.
382  */
EDMA_SetMinorOffsetConfig(EDMA_Type * base,uint32_t channel,const edma_minor_offset_config_t * config)383 void EDMA_SetMinorOffsetConfig(EDMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config)
384 {
385     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
386     assert(config != NULL);
387 
388     uint32_t tmpreg;
389 
390     tmpreg = EDMA_TCD_NBYTES(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base));
391     tmpreg &= ~(DMA_NBYTES_MLOFFYES_SMLOE_MASK | DMA_NBYTES_MLOFFYES_DMLOE_MASK | DMA_NBYTES_MLOFFYES_MLOFF_MASK);
392     tmpreg |=
393         (DMA_NBYTES_MLOFFYES_SMLOE(config->enableSrcMinorOffset) |
394          DMA_NBYTES_MLOFFYES_DMLOE(config->enableDestMinorOffset) | DMA_NBYTES_MLOFFYES_MLOFF(config->minorOffset));
395     EDMA_TCD_NBYTES(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) = tmpreg;
396 }
397 
398 /*!
399  * brief Configures the eDMA channel TCD major offset feature.
400  *
401  * Adjustment value added to the source address at the completion of the major iteration count
402  *
403  * param base eDMA peripheral base address.
404  * param channel edma channel number.
405  * param sourceOffset source address offset.
406  * param destOffset destination address offset.
407  */
EDMA_SetMajorOffsetConfig(EDMA_Type * base,uint32_t channel,int32_t sourceOffset,int32_t destOffset)408 void EDMA_SetMajorOffsetConfig(EDMA_Type *base, uint32_t channel, int32_t sourceOffset, int32_t destOffset)
409 {
410     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
411 
412     EDMA_TCD_SLAST(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base))     = (uint32_t)sourceOffset;
413     EDMA_TCD_DLAST_SGA(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) = (uint32_t)destOffset;
414 }
415 
416 /*!
417  * brief Configures the eDMA channel preemption feature.
418  *
419  * This function configures the channel preemption attribute and the priority of the channel.
420  *
421  * param base eDMA peripheral base address.
422  * param channel eDMA channel number
423  * param config A pointer to the channel preemption configuration structure.
424  */
EDMA_SetChannelPreemptionConfig(EDMA_Type * base,uint32_t channel,const edma_channel_Preemption_config_t * config)425 void EDMA_SetChannelPreemptionConfig(EDMA_Type *base, uint32_t channel, const edma_channel_Preemption_config_t *config)
426 {
427     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
428     assert(config != NULL);
429 
430     bool tmpEnablePreemptAbility   = config->enablePreemptAbility;
431     bool tmpEnablchannelPreemption = config->enableChannelPreemption;
432     uint8_t tmpChannelPriority     = config->channelPriority;
433 
434 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
435 
436     volatile uint8_t *tmpReg = &EDMA_BASE(base)->DCHPRI3;
437 
438     ((volatile uint8_t *)tmpReg)[DMA_DCHPRI_INDEX(channel)] =
439         (DMA_DCHPRI0_DPA((true == tmpEnablePreemptAbility ? 0U : 1U)) |
440          DMA_DCHPRI0_ECP((true == tmpEnablchannelPreemption ? 1U : 0U)) | DMA_DCHPRI0_CHPRI(tmpChannelPriority));
441 #else
442     EDMA_CHANNEL_BASE(base, channel)->CH_PRI = DMA_CH_PRI_ECP(tmpEnablchannelPreemption) |
443                                                DMA_CH_PRI_DPA(tmpEnablePreemptAbility) |
444                                                DMA_CH_PRI_APL(tmpChannelPriority);
445 #endif
446 }
447 
448 /*!
449  * brief Sets the channel link for the eDMA transfer.
450  *
451  * This function configures either the minor link or the major link mode. The minor link means that the channel link is
452  * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is
453  * exhausted.
454  *
455  * param base eDMA peripheral base address.
456  * param channel eDMA channel number.
457  * param type A channel link type, which can be one of the following:
458  *   arg kEDMA_LinkNone
459  *   arg kEDMA_MinorLink
460  *   arg kEDMA_MajorLink
461  * param linkedChannel The linked channel number.
462  * note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
463  */
EDMA_SetChannelLink(EDMA_Type * base,uint32_t channel,edma_channel_link_type_t type,uint32_t linkedChannel)464 void EDMA_SetChannelLink(EDMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel)
465 {
466     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
467     assert(linkedChannel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
468 
469     EDMA_TcdSetChannelLinkExt(base, EDMA_TCD_BASE(base, channel), type, linkedChannel);
470 }
471 
472 #if defined FSL_FEATURE_EDMA_HAS_BANDWIDTH && FSL_FEATURE_EDMA_HAS_BANDWIDTH
473 /*!
474  * brief Sets the bandwidth for the eDMA transfer.
475  *
476  * Because the eDMA processes the minor loop, it continuously generates read/write sequences
477  * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
478  * each read/write access to control the bus request bandwidth seen by the crossbar switch.
479  *
480  * param base eDMA peripheral base address.
481  * param channel eDMA channel number.
482  * param bandWidth A bandwidth setting, which can be one of the following:
483  *     arg kEDMABandwidthStallNone
484  *     arg kEDMABandwidthStall4Cycle
485  *     arg kEDMABandwidthStall8Cycle
486  */
EDMA_SetBandWidth(EDMA_Type * base,uint32_t channel,edma_bandwidth_t bandWidth)487 void EDMA_SetBandWidth(EDMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth)
488 {
489     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
490 
491     EDMA_TCD_CSR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) =
492         (uint16_t)((EDMA_TCD_CSR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) & (~DMA_CSR_BWC_MASK)) |
493                    DMA_CSR_BWC(bandWidth));
494 }
495 #endif
496 
497 /*!
498  * brief Sets the source modulo and the destination modulo for the eDMA transfer.
499  *
500  * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
501  * calculation is performed or the original register value. It provides the ability to implement a circular data
502  * queue easily.
503  *
504  * param base eDMA peripheral base address.
505  * param channel eDMA channel number.
506  * param srcModulo A source modulo value.
507  * param destModulo A destination modulo value.
508  */
EDMA_SetModulo(EDMA_Type * base,uint32_t channel,edma_modulo_t srcModulo,edma_modulo_t destModulo)509 void EDMA_SetModulo(EDMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo)
510 {
511     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
512 
513     uint16_t tmpreg = EDMA_TCD_ATTR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) &
514                       (~(uint16_t)(DMA_ATTR_SMOD_MASK | DMA_ATTR_DMOD_MASK));
515     EDMA_TCD_ATTR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) =
516         tmpreg | DMA_ATTR_DMOD(destModulo) | DMA_ATTR_SMOD(srcModulo);
517 }
518 
519 /*!
520  * brief Sets all fields to default values for the TCD structure.
521  *
522  * This function sets all fields for this TCD structure to default value.
523  *
524  * param base eDMA peripheral base address.
525  * param tcd Pointer to the TCD structure.
526  * note This function enables the auto stop request feature.
527  */
EDMA_TcdResetExt(EDMA_Type * base,edma_tcd_t * tcd)528 void EDMA_TcdResetExt(EDMA_Type *base, edma_tcd_t *tcd)
529 {
530     assert(tcd != NULL);
531     assert(((uint32_t)tcd & 0x1FU) == 0U);
532 
533     /* Reset channel TCD */
534     EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE(base))     = 0U;
535     EDMA_TCD_SOFF(tcd, EDMA_TCD_TYPE(base))      = 0U;
536     EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base))      = 0U;
537     EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base))    = 0U;
538     EDMA_TCD_SLAST(tcd, EDMA_TCD_TYPE(base))     = 0U;
539     EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE(base))     = 0U;
540     EDMA_TCD_DOFF(tcd, EDMA_TCD_TYPE(base))      = 0U;
541     EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base))     = 0U;
542     EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base)) = 0U;
543     /* Enable auto disable request feature */
544     EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base))   = DMA_CSR_DREQ(1U);
545     EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) = 0U;
546 }
547 
548 /*!
549  * brief Configures the eDMA TCD transfer attribute.
550  *
551  * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers.
552  * The TCD is used in the scatter-gather mode.
553  * This function configures the TCD transfer attribute, including source address, destination address,
554  * transfer size, address offset, and so on. It also configures the scatter gather feature if the
555  * user supplies the next TCD address.
556  * Example:
557  * code
558  *   edma_transfer_t config = {
559  *   ...
560  *   }
561  *   edma_tcd_t tcd __aligned(32);
562  *   edma_tcd_t nextTcd __aligned(32);
563  *   EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
564  * endcode
565  *
566  * param base eDMA peripheral base address.
567  * param tcd Pointer to the TCD structure.
568  * param config Pointer to eDMA transfer configuration structure.
569  * param nextTcd Pointer to the next TCD structure. It can be NULL if users
570  *                do not want to enable scatter/gather feature.
571  * note TCD address should be 32 bytes aligned or it causes an eDMA error.
572  * note If the nextTcd is not NULL, the scatter gather feature is enabled
573  *       and DREQ bit is cleared in the previous transfer configuration, which
574  *       is set in the EDMA_TcdReset.
575  */
EDMA_TcdSetTransferConfigExt(EDMA_Type * base,edma_tcd_t * tcd,const edma_transfer_config_t * config,edma_tcd_t * nextTcd)576 void EDMA_TcdSetTransferConfigExt(EDMA_Type *base,
577                                   edma_tcd_t *tcd,
578                                   const edma_transfer_config_t *config,
579                                   edma_tcd_t *nextTcd)
580 {
581     assert(tcd != NULL);
582     assert(((uint32_t)tcd & 0x1FU) == 0U);
583     assert(config != NULL);
584 
585     EDMA_ConfigChannelSoftwareTCDExt(base, tcd, config);
586 
587     if (nextTcd != NULL)
588     {
589         EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base)) = CONVERT_TO_DMA_ADDRESS(nextTcd);
590         /*
591             Before call EDMA_TcdSetTransferConfig or EDMA_SetTransferConfig,
592             user must call EDMA_TcdReset or EDMA_ResetChannel which will set
593             DREQ, so must use "|" or "&" rather than "=".
594 
595             Clear the DREQ bit because scatter gather has been enabled, so the
596             previous transfer is not the last transfer, and channel request should
597             be enabled at the next transfer(the next TCD).
598         */
599         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) =
600             (EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
601     }
602 }
603 
604 /*!
605  * brief Sets TCD fields according to the user's channel transfer configuration structure, see
606  * edma_transfer_config_t.
607  *
608  * Application should be careful about the TCD pool buffer storage class,
609  * - For the platform has cache, the software TCD should be put in non cache section
610  * - The TCD pool buffer should have a consistent storage class.
611  *
612  * param base eDMA peripheral base address.
613  * param tcd Pointer to the TCD structure.
614  * param transfer channel transfer configuration pointer.
615  *
616  */
EDMA_ConfigChannelSoftwareTCDExt(EDMA_Type * base,edma_tcd_t * tcd,const edma_transfer_config_t * transfer)617 void EDMA_ConfigChannelSoftwareTCDExt(EDMA_Type *base, edma_tcd_t *tcd, const edma_transfer_config_t *transfer)
618 {
619     assert(transfer != NULL);
620     assert((transfer->minorLoopBytes % (1UL << ((uint32_t)transfer->srcTransferSize))) == 0U);
621     assert((transfer->minorLoopBytes % (1UL << ((uint32_t)transfer->destTransferSize))) == 0U);
622     assert(((uint32_t)transfer->srcOffset % (1UL << ((uint32_t)transfer->srcTransferSize))) == 0U);
623     assert(((uint32_t)transfer->destOffset % (1UL << ((uint32_t)transfer->destTransferSize))) == 0U);
624     assert((transfer->srcAddr % (1UL << ((uint32_t)transfer->srcTransferSize))) == 0U);
625     assert((transfer->destAddr % (1UL << ((uint32_t)transfer->destTransferSize))) == 0U);
626     assert((transfer->srcAddr % (1UL << ((uint32_t)transfer->srcAddrModulo))) == 0U);
627     assert((transfer->destAddr % (1UL << ((uint32_t)transfer->dstAddrModulo))) == 0U);
628 
629     uint16_t tmpreg;
630 
631     EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE(base)) = CONVERT_TO_DMA_ADDRESS(transfer->srcAddr);
632     /* destination address */
633     EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE(base)) = CONVERT_TO_DMA_ADDRESS(transfer->destAddr);
634     /* Source data and destination data transfer size */
635     EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base)) =
636         DMA_ATTR_SSIZE(transfer->srcTransferSize) | DMA_ATTR_DSIZE(transfer->destTransferSize);
637 
638     /* Source address signed offset */
639     EDMA_TCD_SOFF(tcd, EDMA_TCD_TYPE(base)) = (uint16_t)(transfer->srcOffset);
640     /* Destination address signed offset */
641     EDMA_TCD_DOFF(tcd, EDMA_TCD_TYPE(base)) = (uint16_t)(transfer->destOffset);
642 
643     if (((transfer->enableSrcMinorLoopOffset) || (transfer->enableDstMinorLoopOffset)))
644     {
645         EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base)) = DMA_NBYTES_MLOFFYES_NBYTES(transfer->minorLoopBytes) |
646                                                    DMA_NBYTES_MLOFFYES_MLOFF(transfer->minorLoopOffset) |
647                                                    DMA_NBYTES_MLOFFYES_DMLOE(transfer->enableDstMinorLoopOffset) |
648                                                    DMA_NBYTES_MLOFFYES_SMLOE(transfer->enableSrcMinorLoopOffset);
649     }
650     else
651     {
652         EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base)) = DMA_NBYTES_MLOFFNO_NBYTES(transfer->minorLoopBytes);
653     }
654 
655     /* Current major iteration count */
656     EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) = (uint16_t)(transfer->majorLoopCounts);
657     /* Starting major iteration count */
658     EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) = (uint16_t)(transfer->majorLoopCounts);
659     /* reset CSR firstly */
660     EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) = DMA_CSR_DREQ(1U);
661     /* Enable scatter/gather processing */
662     if (transfer->linkTCD != NULL)
663     {
664         EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base)) = CONVERT_TO_DMA_ADDRESS((uint32_t)((uint8_t *)transfer->linkTCD));
665         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) =
666             (EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
667     }
668     else
669     {
670         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_ESG_MASK;
671         EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base)) = (uint32_t)transfer->dstMajorLoopOffset;
672     }
673 
674     /* configure interrupt/auto disable channel request */
675     EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) |= (transfer->enabledInterruptMask & (~(uint16_t)kEDMA_ErrorInterruptEnable));
676 
677     /* Minor link config */
678     if (transfer->enableChannelMinorLoopLink)
679     {
680         /* Enable minor link */
681         EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) |= DMA_CITER_ELINKYES_ELINK_MASK;
682         EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) |= DMA_BITER_ELINKYES_ELINK_MASK;
683         /* Set linked channel */
684         tmpreg = EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)DMA_CITER_ELINKYES_LINKCH_MASK);
685         tmpreg |= DMA_CITER_ELINKYES_LINKCH(transfer->minorLoopLinkChannel);
686         EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) = tmpreg;
687         tmpreg = EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)DMA_BITER_ELINKYES_LINKCH_MASK);
688         tmpreg |= DMA_BITER_ELINKYES_LINKCH(transfer->minorLoopLinkChannel);
689         EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) = tmpreg;
690     }
691     /* Major link config */
692     if (transfer->enableChannelMajorLoopLink)
693     {
694         /* Enable major link */
695         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) |= DMA_CSR_MAJORELINK_MASK;
696         /* Set major linked channel */
697         tmpreg = EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)DMA_CSR_MAJORLINKCH_MASK);
698         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) = tmpreg | DMA_CSR_MAJORLINKCH(transfer->majorLoopLinkChannel);
699     }
700 
701     /* clear link relate field if no channel link enabled */
702     if ((!transfer->enableChannelMajorLoopLink) && (!transfer->enableChannelMinorLoopLink))
703     {
704         EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CITER_ELINKYES_ELINK_MASK;
705         EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_BITER_ELINKYES_ELINK_MASK;
706         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_MAJORELINK_MASK;
707     }
708 
709     /* major loop offset */
710     EDMA_TCD_SLAST(tcd, EDMA_TCD_TYPE(base)) = (uint32_t)transfer->srcMajorLoopOffset;
711     /* modulo feature */
712     tmpreg = EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)(DMA_ATTR_SMOD_MASK | DMA_ATTR_DMOD_MASK));
713     EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base)) =
714         tmpreg | DMA_ATTR_DMOD(transfer->dstAddrModulo) | DMA_ATTR_SMOD(transfer->srcAddrModulo);
715 }
716 
717 /*!
718  * brief Configures the eDMA TCD minor offset feature.
719  *
720  * A minor offset is a signed-extended value added to the source address or a destination
721  * address after each minor loop.
722  *
723  * param base eDMA peripheral base address.
724  * param tcd A point to the TCD structure.
725  * param config A pointer to the minor offset configuration structure.
726  */
EDMA_TcdSetMinorOffsetConfigExt(EDMA_Type * base,edma_tcd_t * tcd,const edma_minor_offset_config_t * config)727 void EDMA_TcdSetMinorOffsetConfigExt(EDMA_Type *base, edma_tcd_t *tcd, const edma_minor_offset_config_t *config)
728 {
729     assert(tcd != NULL);
730     assert(((uint32_t)tcd & 0x1FU) == 0U);
731 
732     uint32_t tmpreg;
733 
734     tmpreg = EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base)) &
735              ~(DMA_NBYTES_MLOFFYES_SMLOE_MASK | DMA_NBYTES_MLOFFYES_DMLOE_MASK | DMA_NBYTES_MLOFFYES_MLOFF_MASK);
736     tmpreg |=
737         (DMA_NBYTES_MLOFFYES_SMLOE(config->enableSrcMinorOffset) |
738          DMA_NBYTES_MLOFFYES_DMLOE(config->enableDestMinorOffset) | DMA_NBYTES_MLOFFYES_MLOFF(config->minorOffset));
739     EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(base)) = tmpreg;
740 }
741 
742 /*!
743  * brief Configures the eDMA TCD major offset feature.
744  *
745  * Adjustment value added to the source address at the completion of the major iteration count
746  *
747  * param base eDMA peripheral base address.
748  * param tcd A point to the TCD structure.
749  * param sourceOffset source address offset.
750  * param destOffset destination address offset.
751  */
EDMA_TcdSetMajorOffsetConfigExt(EDMA_Type * base,edma_tcd_t * tcd,int32_t sourceOffset,int32_t destOffset)752 void EDMA_TcdSetMajorOffsetConfigExt(EDMA_Type *base, edma_tcd_t *tcd, int32_t sourceOffset, int32_t destOffset)
753 {
754     assert(tcd != NULL);
755     assert(((uint32_t)tcd & 0x1FU) == 0U);
756 
757     EDMA_TCD_SLAST(tcd, EDMA_TCD_TYPE(base))     = (uint32_t)sourceOffset;
758     EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(base)) = (uint32_t)destOffset;
759 }
760 
761 /*!
762  * brief Sets the channel link for the eDMA TCD.
763  *
764  * This function configures either a minor link or a major link. The minor link means the channel link is
765  * triggered every time CITER decreases by 1. The major link means that the channel link  is triggered when the CITER is
766  * exhausted.
767  *
768  * note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
769  * param base eDMA peripheral base address.
770  * param tcd Point to the TCD structure.
771  * param type Channel link type, it can be one of:
772  *   arg kEDMA_LinkNone
773  *   arg kEDMA_MinorLink
774  *   arg kEDMA_MajorLink
775  * param linkedChannel The linked channel number.
776  */
EDMA_TcdSetChannelLinkExt(EDMA_Type * base,edma_tcd_t * tcd,edma_channel_link_type_t type,uint32_t linkedChannel)777 void EDMA_TcdSetChannelLinkExt(EDMA_Type *base, edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel)
778 {
779     assert(tcd != NULL);
780     assert(((uint32_t)tcd & 0x1FU) == 0U);
781     assert(linkedChannel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
782 
783     if (type == kEDMA_MinorLink) /* Minor link config */
784     {
785         uint16_t tmpreg;
786 
787         /* Enable minor link */
788         EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) |= DMA_CITER_ELINKYES_ELINK_MASK;
789         EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) |= DMA_BITER_ELINKYES_ELINK_MASK;
790         /* Set linked channel */
791         tmpreg = EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)DMA_CITER_ELINKYES_LINKCH_MASK);
792         tmpreg |= DMA_CITER_ELINKYES_LINKCH(linkedChannel);
793         EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) = tmpreg;
794         tmpreg = EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)DMA_BITER_ELINKYES_LINKCH_MASK);
795         tmpreg |= DMA_BITER_ELINKYES_LINKCH(linkedChannel);
796         EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) = tmpreg;
797     }
798     else if (type == kEDMA_MajorLink) /* Major link config */
799     {
800         uint16_t tmpreg;
801 
802         /* Enable major link */
803         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) |= DMA_CSR_MAJORELINK_MASK;
804         /* Set major linked channel */
805         tmpreg = EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)DMA_CSR_MAJORLINKCH_MASK);
806         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) = tmpreg | DMA_CSR_MAJORLINKCH(linkedChannel);
807     }
808     else /* Link none */
809     {
810         EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CITER_ELINKYES_ELINK_MASK;
811         EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_BITER_ELINKYES_ELINK_MASK;
812         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_MAJORELINK_MASK;
813     }
814 }
815 
816 /*!
817  * brief Sets the source modulo and the destination modulo for the eDMA TCD.
818  *
819  * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
820  * calculation is performed or the original register value. It provides the ability to implement a circular data
821  * queue easily.
822  *
823  * param base eDMA peripheral base address.
824  * param tcd A pointer to the TCD structure.
825  * param srcModulo A source modulo value.
826  * param destModulo A destination modulo value.
827  */
EDMA_TcdSetModuloExt(EDMA_Type * base,edma_tcd_t * tcd,edma_modulo_t srcModulo,edma_modulo_t destModulo)828 void EDMA_TcdSetModuloExt(EDMA_Type *base, edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo)
829 {
830     assert(tcd != NULL);
831     assert(((uint32_t)tcd & 0x1FU) == 0U);
832 
833     uint16_t tmpreg;
834 
835     tmpreg = EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base)) & (~(uint16_t)(DMA_ATTR_SMOD_MASK | DMA_ATTR_DMOD_MASK));
836     EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(base)) = tmpreg | DMA_ATTR_DMOD(destModulo) | DMA_ATTR_SMOD(srcModulo);
837 }
838 
839 /*!
840  * brief Enables the interrupt source for the eDMA TCD.
841  *
842  * param base eDMA peripheral base address.
843  * param tcd Point to the TCD structure.
844  * param mask The mask of interrupt source to be set. Users need to use
845  *             the defined edma_interrupt_enable_t type.
846  */
EDMA_TcdEnableInterruptsExt(EDMA_Type * base,edma_tcd_t * tcd,uint32_t mask)847 void EDMA_TcdEnableInterruptsExt(EDMA_Type *base, edma_tcd_t *tcd, uint32_t mask)
848 {
849     assert(tcd != NULL);
850 
851     /* Enable Major interrupt */
852     if (0U != (mask & (uint32_t)kEDMA_MajorInterruptEnable))
853     {
854         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) |= DMA_CSR_INTMAJOR_MASK;
855     }
856 
857     /* Enable Half major interrupt */
858     if (0U != (mask & (uint32_t)kEDMA_HalfInterruptEnable))
859     {
860         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) |= DMA_CSR_INTHALF_MASK;
861     }
862 }
863 
864 /*!
865  * brief Disables the interrupt source for the eDMA TCD.
866  *
867  * param base eDMA peripheral base address.
868  * param tcd Point to the TCD structure.
869  * param mask The mask of interrupt source to be set. Users need to use
870  *             the defined edma_interrupt_enable_t type.
871  */
EDMA_TcdDisableInterruptsExt(EDMA_Type * base,edma_tcd_t * tcd,uint32_t mask)872 void EDMA_TcdDisableInterruptsExt(EDMA_Type *base, edma_tcd_t *tcd, uint32_t mask)
873 {
874     assert(tcd != NULL);
875 
876     /* Disable Major interrupt */
877     if (0U != (mask & (uint32_t)kEDMA_MajorInterruptEnable))
878     {
879         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_INTMAJOR_MASK;
880     }
881 
882     /* Disable Half major interrupt */
883     if (0U != (mask & (uint32_t)kEDMA_HalfInterruptEnable))
884     {
885         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_INTHALF_MASK;
886     }
887 }
888 
889 /*!
890  * brief Sets all fields to default values for the TCD structure.
891  *
892  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
893  * EDMA_TcdResetExt
894  *
895  * This function sets all fields for this TCD structure to default value.
896  *
897  * param tcd Pointer to the TCD structure.
898  * note This function enables the auto stop request feature.
899  */
EDMA_TcdReset(edma_tcd_t * tcd)900 void EDMA_TcdReset(edma_tcd_t *tcd)
901 {
902     assert(tcd != NULL);
903 
904     /* Reset channel TCD */
905     EDMA_TCD_SADDR(tcd, kEDMA_EDMA4Flag)     = 0U;
906     EDMA_TCD_SOFF(tcd, kEDMA_EDMA4Flag)      = 0U;
907     EDMA_TCD_ATTR(tcd, kEDMA_EDMA4Flag)      = 0U;
908     EDMA_TCD_NBYTES(tcd, kEDMA_EDMA4Flag)    = 0U;
909     EDMA_TCD_SLAST(tcd, kEDMA_EDMA4Flag)     = 0U;
910     EDMA_TCD_DADDR(tcd, kEDMA_EDMA4Flag)     = 0U;
911     EDMA_TCD_DOFF(tcd, kEDMA_EDMA4Flag)      = 0U;
912     EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag)     = 0U;
913     EDMA_TCD_DLAST_SGA(tcd, kEDMA_EDMA4Flag) = 0U;
914     /* Enable auto disable request feature */
915     EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag)   = DMA_CSR_DREQ(1U);
916     EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) = 0U;
917 }
918 
919 /*!
920  * brief Configures the eDMA TCD transfer attribute.
921  *
922  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
923  * EDMA_TcdSetTransferConfigExt
924  *
925  * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers.
926  * The TCD is used in the scatter-gather mode.
927  * This function configures the TCD transfer attribute, including source address, destination address,
928  * transfer size, address offset, and so on. It also configures the scatter gather feature if the
929  * user supplies the next TCD address.
930  * Example:
931  * code
932  *   edma_transfer_t config = {
933  *   ...
934  *   }
935  *   edma_tcd_t tcd __aligned(32);
936  *   edma_tcd_t nextTcd __aligned(32);
937  *   EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
938  * endcode
939  *
940  * param tcd Pointer to the TCD structure.
941  * param config Pointer to eDMA transfer configuration structure.
942  * param nextTcd Pointer to the next TCD structure. It can be NULL if users
943  *                do not want to enable scatter/gather feature.
944  * note TCD address should be 32 bytes aligned or it causes an eDMA error.
945  * note If the nextTcd is not NULL, the scatter gather feature is enabled
946  *       and DREQ bit is cleared in the previous transfer configuration, which
947  *       is set in the EDMA_TcdReset.
948  */
EDMA_TcdSetTransferConfig(edma_tcd_t * tcd,const edma_transfer_config_t * config,edma_tcd_t * nextTcd)949 void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd)
950 {
951     assert(tcd != NULL);
952     assert(config != NULL);
953 
954     EDMA_ConfigChannelSoftwareTCD(tcd, config);
955 
956     if (nextTcd != NULL)
957     {
958         EDMA_TCD_DLAST_SGA(tcd, kEDMA_EDMA4Flag) = CONVERT_TO_DMA_ADDRESS(nextTcd);
959         /*
960             Before call EDMA_TcdSetTransferConfig or EDMA_SetTransferConfig,
961             user must call EDMA_TcdReset or EDMA_ResetChannel which will set
962             DREQ, so must use "|" or "&" rather than "=".
963 
964             Clear the DREQ bit because scatter gather has been enabled, so the
965             previous transfer is not the last transfer, and channel request should
966             be enabled at the next transfer(the next TCD).
967         */
968         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) =
969             (EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
970     }
971 }
972 
973 /*!
974  * brief Sets TCD fields according to the user's channel transfer configuration structure, see
975  * edma_transfer_config_t.
976  *
977  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
978  * EDMA_ConfigChannelSoftwareTCDExt
979  *
980  * Application should be careful about the TCD pool buffer storage class,
981  * - For the platform has cache, the software TCD should be put in non cache section
982  * - The TCD pool buffer should have a consistent storage class.
983  *
984  * param tcd Pointer to the TCD structure.
985  * param transfer channel transfer configuration pointer.
986  *
987  */
EDMA_ConfigChannelSoftwareTCD(edma_tcd_t * tcd,const edma_transfer_config_t * transfer)988 void EDMA_ConfigChannelSoftwareTCD(edma_tcd_t *tcd, const edma_transfer_config_t *transfer)
989 {
990     assert(transfer != NULL);
991     assert((transfer->minorLoopBytes % (1UL << ((uint32_t)transfer->srcTransferSize))) == 0U);
992     assert((transfer->minorLoopBytes % (1UL << ((uint32_t)transfer->destTransferSize))) == 0U);
993     assert(((uint32_t)transfer->srcOffset % (1UL << ((uint32_t)transfer->srcTransferSize))) == 0U);
994     assert(((uint32_t)transfer->destOffset % (1UL << ((uint32_t)transfer->destTransferSize))) == 0U);
995     assert((transfer->srcAddr % (1UL << ((uint32_t)transfer->srcTransferSize))) == 0U);
996     assert((transfer->destAddr % (1UL << ((uint32_t)transfer->destTransferSize))) == 0U);
997     assert((transfer->srcAddr % (1UL << ((uint32_t)transfer->srcAddrModulo))) == 0U);
998     assert((transfer->destAddr % (1UL << ((uint32_t)transfer->dstAddrModulo))) == 0U);
999 
1000     uint16_t tmpreg;
1001 
1002     EDMA_TCD_SADDR(tcd, kEDMA_EDMA4Flag) = CONVERT_TO_DMA_ADDRESS(transfer->srcAddr);
1003     /* destination address */
1004     EDMA_TCD_DADDR(tcd, kEDMA_EDMA4Flag) = CONVERT_TO_DMA_ADDRESS(transfer->destAddr);
1005     /* Source data and destination data transfer size */
1006     EDMA_TCD_ATTR(tcd, kEDMA_EDMA4Flag) =
1007         DMA_ATTR_SSIZE(transfer->srcTransferSize) | DMA_ATTR_DSIZE(transfer->destTransferSize);
1008 
1009     /* Source address signed offset */
1010     EDMA_TCD_SOFF(tcd, kEDMA_EDMA4Flag) = (uint16_t)(transfer->srcOffset);
1011     /* Destination address signed offset */
1012     EDMA_TCD_DOFF(tcd, kEDMA_EDMA4Flag) = (uint16_t)(transfer->destOffset);
1013 
1014     if (((transfer->enableSrcMinorLoopOffset) || (transfer->enableDstMinorLoopOffset)))
1015     {
1016         EDMA_TCD_NBYTES(tcd, kEDMA_EDMA4Flag) = DMA_NBYTES_MLOFFYES_NBYTES(transfer->minorLoopBytes) |
1017                                                 DMA_NBYTES_MLOFFYES_MLOFF(transfer->minorLoopOffset) |
1018                                                 DMA_NBYTES_MLOFFYES_DMLOE(transfer->enableDstMinorLoopOffset) |
1019                                                 DMA_NBYTES_MLOFFYES_SMLOE(transfer->enableSrcMinorLoopOffset);
1020     }
1021     else
1022     {
1023         EDMA_TCD_NBYTES(tcd, kEDMA_EDMA4Flag) = DMA_NBYTES_MLOFFNO_NBYTES(transfer->minorLoopBytes);
1024     }
1025 
1026     /* Current major iteration count */
1027     EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) = (uint16_t)(transfer->majorLoopCounts);
1028     /* Starting major iteration count */
1029     EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) = (uint16_t)(transfer->majorLoopCounts);
1030     /* reset CSR firstly */
1031     EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) = DMA_CSR_DREQ(1U);
1032     /* Enable scatter/gather processing */
1033     if (transfer->linkTCD != NULL)
1034     {
1035         EDMA_TCD_DLAST_SGA(tcd, kEDMA_EDMA4Flag) = CONVERT_TO_DMA_ADDRESS((uint32_t)((uint8_t *)transfer->linkTCD));
1036         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) =
1037             (EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
1038     }
1039     else
1040     {
1041         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CSR_ESG_MASK;
1042         EDMA_TCD_DLAST_SGA(tcd, kEDMA_EDMA4Flag) = (uint32_t)transfer->dstMajorLoopOffset;
1043     }
1044 
1045     /* configure interrupt/auto disable channel request */
1046     EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= (transfer->enabledInterruptMask & (~(uint16_t)kEDMA_ErrorInterruptEnable));
1047 
1048     /* Minor link config */
1049     if (transfer->enableChannelMinorLoopLink)
1050     {
1051         /* Enable minor link */
1052         EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) |= DMA_CITER_ELINKYES_ELINK_MASK;
1053         EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) |= DMA_BITER_ELINKYES_ELINK_MASK;
1054         /* Set linked channel */
1055         tmpreg = EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)DMA_CITER_ELINKYES_LINKCH_MASK);
1056         tmpreg |= DMA_CITER_ELINKYES_LINKCH(transfer->minorLoopLinkChannel);
1057         EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) = tmpreg;
1058         tmpreg = EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)DMA_BITER_ELINKYES_LINKCH_MASK);
1059         tmpreg |= DMA_BITER_ELINKYES_LINKCH(transfer->minorLoopLinkChannel);
1060         EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) = tmpreg;
1061     }
1062     /* Major link config */
1063     if (transfer->enableChannelMajorLoopLink)
1064     {
1065         /* Enable major link */
1066         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= DMA_CSR_MAJORELINK_MASK;
1067         /* Set major linked channel */
1068         tmpreg                             = EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)DMA_CSR_MAJORLINKCH_MASK);
1069         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) = tmpreg | DMA_CSR_MAJORLINKCH(transfer->majorLoopLinkChannel);
1070     }
1071 
1072     /* clear link relate field if no channel link enabled */
1073     if ((!transfer->enableChannelMajorLoopLink) && (!transfer->enableChannelMinorLoopLink))
1074     {
1075         EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CITER_ELINKYES_ELINK_MASK;
1076         EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_BITER_ELINKYES_ELINK_MASK;
1077         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CSR_MAJORELINK_MASK;
1078     }
1079 
1080     /* major loop offset */
1081     EDMA_TCD_SLAST(tcd, kEDMA_EDMA4Flag) = (uint32_t)transfer->srcMajorLoopOffset;
1082     /* modulo feature */
1083     tmpreg = EDMA_TCD_ATTR(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)(DMA_ATTR_SMOD_MASK | DMA_ATTR_DMOD_MASK));
1084     EDMA_TCD_ATTR(tcd, kEDMA_EDMA4Flag) =
1085         tmpreg | DMA_ATTR_DMOD(transfer->dstAddrModulo) | DMA_ATTR_SMOD(transfer->srcAddrModulo);
1086 }
1087 
1088 /*!
1089  * brief Configures the eDMA TCD minor offset feature.
1090  *
1091  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
1092  * EDMA_TcdSetMinorOffsetConfigExt
1093  *
1094  * A minor offset is a signed-extended value added to the source address or a destination
1095  * address after each minor loop.
1096  *
1097  * param tcd A point to the TCD structure.
1098  * param config A pointer to the minor offset configuration structure.
1099  */
EDMA_TcdSetMinorOffsetConfig(edma_tcd_t * tcd,const edma_minor_offset_config_t * config)1100 void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config)
1101 {
1102     assert(tcd != NULL);
1103 
1104     uint32_t tmpreg;
1105 
1106     tmpreg = EDMA_TCD_NBYTES(tcd, kEDMA_EDMA4Flag) &
1107              ~(DMA_NBYTES_MLOFFYES_SMLOE_MASK | DMA_NBYTES_MLOFFYES_DMLOE_MASK | DMA_NBYTES_MLOFFYES_MLOFF_MASK);
1108     tmpreg |=
1109         (DMA_NBYTES_MLOFFYES_SMLOE(config->enableSrcMinorOffset) |
1110          DMA_NBYTES_MLOFFYES_DMLOE(config->enableDestMinorOffset) | DMA_NBYTES_MLOFFYES_MLOFF(config->minorOffset));
1111     EDMA_TCD_NBYTES(tcd, kEDMA_EDMA4Flag) = tmpreg;
1112 }
1113 
1114 /*!
1115  * brief Configures the eDMA TCD major offset feature.
1116  *
1117  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
1118  * EDMA_TcdSetMajorOffsetConfigExt
1119  *
1120  * Adjustment value added to the source address at the completion of the major iteration count
1121  *
1122  * param tcd A point to the TCD structure.
1123  * param sourceOffset source address offset.
1124  * param destOffset destination address offset.
1125  */
EDMA_TcdSetMajorOffsetConfig(edma_tcd_t * tcd,int32_t sourceOffset,int32_t destOffset)1126 void EDMA_TcdSetMajorOffsetConfig(edma_tcd_t *tcd, int32_t sourceOffset, int32_t destOffset)
1127 {
1128     assert(tcd != NULL);
1129 
1130     EDMA_TCD_SLAST(tcd, kEDMA_EDMA4Flag)     = (uint32_t)sourceOffset;
1131     EDMA_TCD_DLAST_SGA(tcd, kEDMA_EDMA4Flag) = (uint32_t)destOffset;
1132 }
1133 
1134 /*!
1135  * brief Sets the channel link for the eDMA TCD.
1136  *
1137  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
1138  * EDMA_TcdSetChannelLinkExt
1139  *
1140  * This function configures either a minor link or a major link. The minor link means the channel link is
1141  * triggered every time CITER decreases by 1. The major link means that the channel link  is triggered when the CITER is
1142  * exhausted.
1143  *
1144  * note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
1145  * param tcd Point to the TCD structure.
1146  * param type Channel link type, it can be one of:
1147  *   arg kEDMA_LinkNone
1148  *   arg kEDMA_MinorLink
1149  *   arg kEDMA_MajorLink
1150  * param linkedChannel The linked channel number.
1151  */
EDMA_TcdSetChannelLink(edma_tcd_t * tcd,edma_channel_link_type_t type,uint32_t linkedChannel)1152 void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel)
1153 {
1154     assert(tcd != NULL);
1155     assert(linkedChannel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
1156 
1157     if (type == kEDMA_MinorLink) /* Minor link config */
1158     {
1159         uint16_t tmpreg;
1160 
1161         /* Enable minor link */
1162         EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) |= DMA_CITER_ELINKYES_ELINK_MASK;
1163         EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) |= DMA_BITER_ELINKYES_ELINK_MASK;
1164         /* Set linked channel */
1165         tmpreg = EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)DMA_CITER_ELINKYES_LINKCH_MASK);
1166         tmpreg |= DMA_CITER_ELINKYES_LINKCH(linkedChannel);
1167         EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) = tmpreg;
1168         tmpreg = EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)DMA_BITER_ELINKYES_LINKCH_MASK);
1169         tmpreg |= DMA_BITER_ELINKYES_LINKCH(linkedChannel);
1170         EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) = tmpreg;
1171     }
1172     else if (type == kEDMA_MajorLink) /* Major link config */
1173     {
1174         uint16_t tmpreg;
1175 
1176         /* Enable major link */
1177         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= DMA_CSR_MAJORELINK_MASK;
1178         /* Set major linked channel */
1179         tmpreg                             = EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)DMA_CSR_MAJORLINKCH_MASK);
1180         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) = tmpreg | DMA_CSR_MAJORLINKCH(linkedChannel);
1181     }
1182     else /* Link none */
1183     {
1184         EDMA_TCD_CITER(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CITER_ELINKYES_ELINK_MASK;
1185         EDMA_TCD_BITER(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_BITER_ELINKYES_ELINK_MASK;
1186         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CSR_MAJORELINK_MASK;
1187     }
1188 }
1189 
1190 /*!
1191  * brief Sets the source modulo and the destination modulo for the eDMA TCD.
1192  *
1193  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
1194  * EDMA_TcdSetModuloExt
1195  *
1196  * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
1197  * calculation is performed or the original register value. It provides the ability to implement a circular data
1198  * queue easily.
1199  *
1200  * param tcd A pointer to the TCD structure.
1201  * param srcModulo A source modulo value.
1202  * param destModulo A destination modulo value.
1203  */
EDMA_TcdSetModulo(edma_tcd_t * tcd,edma_modulo_t srcModulo,edma_modulo_t destModulo)1204 void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo)
1205 {
1206     assert(tcd != NULL);
1207 
1208     uint16_t tmpreg;
1209 
1210     tmpreg = EDMA_TCD_ATTR(tcd, kEDMA_EDMA4Flag) & (~(uint16_t)(DMA_ATTR_SMOD_MASK | DMA_ATTR_DMOD_MASK));
1211     EDMA_TCD_ATTR(tcd, kEDMA_EDMA4Flag) = tmpreg | DMA_ATTR_DMOD(destModulo) | DMA_ATTR_SMOD(srcModulo);
1212 }
1213 
1214 /*!
1215  * brief Enables the interrupt source for the eDMA TCD.
1216  *
1217  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
1218  * EDMA_TcdEnableInterruptsExt
1219  *
1220  * param tcd Point to the TCD structure.
1221  * param mask The mask of interrupt source to be set. Users need to use
1222  *             the defined edma_interrupt_enable_t type.
1223  */
EDMA_TcdEnableInterrupts(edma_tcd_t * tcd,uint32_t mask)1224 void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask)
1225 {
1226     assert(tcd != NULL);
1227 
1228     /* Enable Major interrupt */
1229     if (0U != (mask & (uint32_t)kEDMA_MajorInterruptEnable))
1230     {
1231         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= DMA_CSR_INTMAJOR_MASK;
1232     }
1233 
1234     /* Enable Half major interrupt */
1235     if (0U != (mask & (uint32_t)kEDMA_HalfInterruptEnable))
1236     {
1237         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) |= DMA_CSR_INTHALF_MASK;
1238     }
1239 }
1240 
1241 /*!
1242  * brief Disables the interrupt source for the eDMA TCD.
1243  *
1244  * Note This API only supports EDMA4 TCD type. It can be used to support all types with extension API ref
1245  * EDMA_TcdDisableInterruptsExt
1246  *
1247  * param tcd Point to the TCD structure.
1248  * param mask The mask of interrupt source to be set. Users need to use
1249  *             the defined edma_interrupt_enable_t type.
1250  */
EDMA_TcdDisableInterrupts(edma_tcd_t * tcd,uint32_t mask)1251 void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask)
1252 {
1253     assert(tcd != NULL);
1254 
1255     /* Disable Major interrupt */
1256     if (0U != (mask & (uint32_t)kEDMA_MajorInterruptEnable))
1257     {
1258         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CSR_INTMAJOR_MASK;
1259     }
1260 
1261     /* Disable Half major interrupt */
1262     if (0U != (mask & (uint32_t)kEDMA_HalfInterruptEnable))
1263     {
1264         EDMA_TCD_CSR(tcd, kEDMA_EDMA4Flag) &= ~(uint16_t)DMA_CSR_INTHALF_MASK;
1265     }
1266 }
1267 
1268 /*!
1269  * brief Gets the remaining major loop count from the eDMA current channel TCD.
1270  *
1271  * This function checks the TCD (Task Control Descriptor) status for a specified
1272  * eDMA channel and returns the number of major loop count that has not finished.
1273  *
1274  * param base eDMA peripheral base address.
1275  * param channel eDMA channel number.
1276  * return Major loop count which has not been transferred yet for the current TCD.
1277  * note 1. This function can only be used to get unfinished major loop count of transfer without
1278  *          the next TCD, or it might be inaccuracy.
1279  *       2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while
1280  *          the channel is running.
1281  *          Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO
1282  *          register is needed while the eDMA IP does not support getting it while a channel is active.
1283  *          In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine
1284  *          is working with while a channel is running.
1285  *          Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example
1286  *          copied before enabling the channel) is needed. The formula to calculate it is shown below:
1287  *          RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
1288  */
EDMA_GetRemainingMajorLoopCount(EDMA_Type * base,uint32_t channel)1289 uint32_t EDMA_GetRemainingMajorLoopCount(EDMA_Type *base, uint32_t channel)
1290 {
1291     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
1292 
1293     uint32_t remainingCount = 0;
1294 
1295     if (0U != DMA_GET_DONE_STATUS(base, channel))
1296     {
1297         remainingCount = 0;
1298     }
1299     else
1300     {
1301         /* Calculate the unfinished bytes */
1302         if (0U != (EDMA_TCD_CITER(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) & DMA_CITER_ELINKNO_ELINK_MASK))
1303         {
1304             remainingCount = (((uint32_t)EDMA_TCD_CITER(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) &
1305                                DMA_CITER_ELINKYES_CITER_MASK) >>
1306                               DMA_CITER_ELINKYES_CITER_SHIFT);
1307         }
1308         else
1309         {
1310             remainingCount = (((uint32_t)EDMA_TCD_CITER(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) &
1311                                DMA_CITER_ELINKNO_CITER_MASK) >>
1312                               DMA_CITER_ELINKNO_CITER_SHIFT);
1313         }
1314     }
1315 
1316     return remainingCount;
1317 }
1318 
1319 /*!
1320  * brief Enables the interrupt source for the eDMA transfer.
1321  *
1322  * param base eDMA peripheral base address.
1323  * param channel eDMA channel number.
1324  * param mask The mask of interrupt source to be set. Users need to use
1325  *             the defined edma_interrupt_enable_t type.
1326  */
EDMA_EnableChannelInterrupts(EDMA_Type * base,uint32_t channel,uint32_t mask)1327 void EDMA_EnableChannelInterrupts(EDMA_Type *base, uint32_t channel, uint32_t mask)
1328 {
1329     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
1330 
1331     /* Enable error interrupt */
1332     if (0U != (mask & (uint32_t)kEDMA_ErrorInterruptEnable))
1333     {
1334         DMA_ENABLE_ERROR_INT(base, channel);
1335     }
1336 
1337     /* Enable Major interrupt */
1338     if (0U != (mask & (uint32_t)kEDMA_MajorInterruptEnable))
1339     {
1340         DMA_ENABLE_MAJOR_INT(base, channel);
1341     }
1342 
1343     /* Enable Half major interrupt */
1344     if (0U != (mask & (uint32_t)kEDMA_HalfInterruptEnable))
1345     {
1346         DMA_ENABLE_HALF_INT(base, channel);
1347     }
1348 }
1349 
1350 /*!
1351  * brief Disables the interrupt source for the eDMA transfer.
1352  *
1353  * param base eDMA peripheral base address.
1354  * param channel eDMA channel number.
1355  * param mask The mask of the interrupt source to be set. Use
1356  *             the defined edma_interrupt_enable_t type.
1357  */
EDMA_DisableChannelInterrupts(EDMA_Type * base,uint32_t channel,uint32_t mask)1358 void EDMA_DisableChannelInterrupts(EDMA_Type *base, uint32_t channel, uint32_t mask)
1359 {
1360     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
1361 
1362     /* Disable error interrupt */
1363     if (0U != (mask & (uint32_t)kEDMA_ErrorInterruptEnable))
1364     {
1365         DMA_DISABLE_ERROR_INT(base, channel);
1366     }
1367 
1368     /* Disable Major interrupt */
1369     if (0U != (mask & (uint32_t)kEDMA_MajorInterruptEnable))
1370     {
1371         DMA_DISABLE_MAJOR_INT(base, channel);
1372     }
1373 
1374     /* Disable Half major interrupt */
1375     if (0U != (mask & (uint32_t)kEDMA_HalfInterruptEnable))
1376     {
1377         DMA_DISABLE_HALF_INT(base, channel);
1378     }
1379 }
1380 
1381 /*!
1382  * brief Gets the eDMA channel status flags.
1383  *
1384  * param base eDMA peripheral base address.
1385  * param channel eDMA channel number.
1386  * return The mask of channel status flags. Users need to use the
1387  *         _edma_channel_status_flags type to decode the return variables.
1388  */
EDMA_GetChannelStatusFlags(EDMA_Type * base,uint32_t channel)1389 uint32_t EDMA_GetChannelStatusFlags(EDMA_Type *base, uint32_t channel)
1390 {
1391     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
1392 
1393     uint32_t retval = 0;
1394 
1395     /* Get DONE bit flag */
1396     retval |= DMA_GET_DONE_STATUS(base, channel);
1397     /* Get ERROR bit flag */
1398     retval |= (DMA_GET_ERROR_STATUS(base, channel) << 1U);
1399     /* Get INT bit flag */
1400     retval |= (DMA_GET_INT_STATUS(base, channel) << 2U);
1401 
1402     return retval;
1403 }
1404 
1405 /*!
1406  * brief Clears the eDMA channel status flags.
1407  *
1408  * param base eDMA peripheral base address.
1409  * param channel eDMA channel number.
1410  * param mask The mask of channel status to be cleared. Users need to use
1411  *             the defined _edma_channel_status_flags type.
1412  */
EDMA_ClearChannelStatusFlags(EDMA_Type * base,uint32_t channel,uint32_t mask)1413 void EDMA_ClearChannelStatusFlags(EDMA_Type *base, uint32_t channel, uint32_t mask)
1414 {
1415     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
1416 
1417     /* Clear DONE bit flag */
1418     if (0U != (mask & (uint32_t)kEDMA_DoneFlag))
1419     {
1420         DMA_CLEAR_DONE_STATUS(base, channel);
1421     }
1422     /* Clear ERROR bit flag */
1423     if (0U != (mask & (uint32_t)kEDMA_ErrorFlag))
1424     {
1425         DMA_CLEAR_ERROR_STATUS(base, channel);
1426     }
1427     /* Clear INT bit flag */
1428     if (0U != (mask & (uint32_t)kEDMA_InterruptFlag))
1429     {
1430         DMA_CLEAR_INT_STATUS(base, channel);
1431     }
1432 }
1433 
1434 /*!
1435  * brief Creates the eDMA handle.
1436  *
1437  * This function is called if using the transactional API for eDMA. This function
1438  * initializes the internal state of the eDMA handle.
1439  *
1440  * param handle eDMA handle pointer. The eDMA handle stores callback function and
1441  *               parameters.
1442  * param base eDMA peripheral base address.
1443  * param channel eDMA channel number.
1444  */
EDMA_CreateHandle(edma_handle_t * handle,EDMA_Type * base,uint32_t channel)1445 void EDMA_CreateHandle(edma_handle_t *handle, EDMA_Type *base, uint32_t channel)
1446 {
1447     assert(handle != NULL);
1448     assert(FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base) != -1);
1449     assert(channel < (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base));
1450 
1451     uint32_t edmaInstance;
1452     edma_tcd_t *tcdRegs;
1453 
1454     /* Zero the handle */
1455     (void)memset(handle, 0, sizeof(*handle));
1456 
1457     handle->channel = channel;
1458 
1459     /* Get the DMA instance number */
1460     edmaInstance                        = EDMA_GetInstance(base);
1461     s_EDMAHandle[edmaInstance][channel] = handle;
1462     /* Enable NVIC interrupt */
1463     (void)EnableIRQ(s_edmaIRQNumber[edmaInstance][channel]);
1464 
1465     handle->tcdBase     = EDMA_TCD_BASE(base, channel);
1466     handle->channelBase = EDMA_CHANNEL_BASE(base, channel);
1467     handle->base        = base;
1468     /*
1469        Reset TCD registers to zero. Unlike the EDMA_TcdReset(DREQ will be set),
1470        CSR will be 0. Because in order to suit EDMA busy check mechanism in
1471        EDMA_SubmitTransfer, CSR must be set 0.
1472     */
1473     tcdRegs                                         = handle->tcdBase;
1474     EDMA_TCD_SADDR(tcdRegs, EDMA_TCD_TYPE(base))     = 0;
1475     EDMA_TCD_SOFF(tcdRegs, EDMA_TCD_TYPE(base))      = 0;
1476     EDMA_TCD_ATTR(tcdRegs, EDMA_TCD_TYPE(base))      = 0;
1477     EDMA_TCD_NBYTES(tcdRegs, EDMA_TCD_TYPE(base))    = 0;
1478     EDMA_TCD_SLAST(tcdRegs, EDMA_TCD_TYPE(base))     = 0;
1479     EDMA_TCD_DADDR(tcdRegs, EDMA_TCD_TYPE(base))     = 0;
1480     EDMA_TCD_DOFF(tcdRegs, EDMA_TCD_TYPE(base))      = 0;
1481     EDMA_TCD_CITER(tcdRegs, EDMA_TCD_TYPE(base))     = 0;
1482     EDMA_TCD_DLAST_SGA(tcdRegs, EDMA_TCD_TYPE(base)) = 0;
1483     EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(base))       = 0;
1484     EDMA_TCD_BITER(tcdRegs, EDMA_TCD_TYPE(base))     = 0;
1485 }
1486 
1487 /*!
1488  * brief Installs the TCDs memory pool into the eDMA handle.
1489  *
1490  * This function is called after the EDMA_CreateHandle to use scatter/gather feature. This function shall only be used
1491  * while users need to use scatter gather mode. Scatter gather mode enables EDMA to load a new transfer control block
1492  * (tcd) in hardware, and automatically reconfigure that DMA channel for a new transfer.
1493  * Users need to prepare tcd memory and also configure tcds using interface EDMA_SubmitTransfer.
1494  *
1495  * param handle eDMA handle pointer.
1496  * param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned.
1497  * param tcdSize The number of TCD slots.
1498  */
EDMA_InstallTCDMemory(edma_handle_t * handle,edma_tcd_t * tcdPool,uint32_t tcdSize)1499 void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize)
1500 {
1501     assert(handle != NULL);
1502     assert(((uint32_t)tcdPool & 0x1FU) == 0U);
1503 
1504     /* Initialize tcd queue attribute. */
1505     /* header should initial as 1, since that it is used to point to the next TCD to be loaded into TCD memory,
1506      * In EDMA driver IRQ handler, header will be used to calculate how many tcd has done, for example,
1507      * If application submit 4 transfer request, A->B->C->D,
1508      * when A finshed, the header is 0, C is the next TCD to be load, since B is already loaded,
1509      * according to EDMA driver IRQ handler, tcdDone = C - A - header = 2 - header = 2, but actually only 1 TCD done,
1510      * so the issue will be the wrong TCD done count will pass to application in first TCD interrupt.
1511      * During first submit, the header should be assigned to 1, since 0 is current one and 1 is next TCD to be loaded,
1512      * but software cannot know which submission is the first one, so assign 1 to header here.
1513      */
1514     handle->header  = 1;
1515     handle->tcdUsed = 0;
1516     handle->tcdSize = (int8_t)tcdSize;
1517     handle->tcdPool = tcdPool;
1518 }
1519 
1520 /*!
1521  * brief Installs a callback function for the eDMA transfer.
1522  *
1523  * This callback is called in the eDMA IRQ handler. Use the callback to do something after
1524  * the current major loop transfer completes. This function will be called every time one tcd finished transfer.
1525  *
1526  * param handle eDMA handle pointer.
1527  * param callback eDMA callback function pointer.
1528  * param userData A parameter for the callback function.
1529  */
EDMA_SetCallback(edma_handle_t * handle,edma_callback callback,void * userData)1530 void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData)
1531 {
1532     assert(handle != NULL);
1533 
1534     handle->callback = callback;
1535     handle->userData = userData;
1536 }
1537 
EDMA_TransferWidthMapping(uint32_t width)1538 static edma_transfer_size_t EDMA_TransferWidthMapping(uint32_t width)
1539 {
1540     edma_transfer_size_t transferSize = kEDMA_TransferSize1Bytes;
1541 
1542     /* map width to register value */
1543     switch (width)
1544     {
1545         /* width 8bit */
1546         case 1U:
1547             transferSize = kEDMA_TransferSize1Bytes;
1548             break;
1549         /* width 16bit */
1550         case 2U:
1551             transferSize = kEDMA_TransferSize2Bytes;
1552             break;
1553         /* width 32bit */
1554         case 4U:
1555             transferSize = kEDMA_TransferSize4Bytes;
1556             break;
1557 #if (defined(FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER)
1558         /* width 64bit */
1559         case 8U:
1560             transferSize = kEDMA_TransferSize8Bytes;
1561             break;
1562 #endif
1563 #if (defined(FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER)
1564         /* width 128bit */
1565         case 16U:
1566             transferSize = kEDMA_TransferSize16Bytes;
1567             break;
1568 #endif
1569         /* width 256bit */
1570         case 32U:
1571             transferSize = kEDMA_TransferSize32Bytes;
1572             break;
1573 #if (defined(FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER)
1574         /* width 512bit */
1575         case 64U:
1576             transferSize = kEDMA_TransferSize64Bytes;
1577             break;
1578 #endif
1579 #if (defined(FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER)
1580         /* width 1024bit */
1581         case 128U:
1582             transferSize = kEDMA_TransferSize128Bytes;
1583             break;
1584 #endif
1585         default:
1586             /* All the cases have been listed above, the default clause should not be reached. */
1587             assert(false);
1588             break;
1589     }
1590 
1591     return transferSize;
1592 }
1593 
1594 /*!
1595  * brief Prepares the eDMA transfer structure configurations.
1596  *
1597  * This function prepares the transfer configuration structure according to the user input.
1598  *
1599  * param config The user configuration structure of type edma_transfer_t.
1600  * param srcAddr eDMA transfer source address.
1601  * param srcWidth eDMA transfer source address width(bytes).
1602  * param srcOffset source address offset.
1603  * param destAddr eDMA transfer destination address.
1604  * param destWidth eDMA transfer destination address width(bytes).
1605  * param destOffset destination address offset.
1606  * param bytesEachRequest eDMA transfer bytes per channel request.
1607  * param transferBytes eDMA transfer bytes to be transferred.
1608  * note The data address and the data width must be consistent. For example, if the SRC
1609  *       is 4 bytes, the source address must be 4 bytes aligned, or it results in
1610  *       source address error (SAE).
1611  *       User can check if 128 bytes support is available for specific instance by
1612  *       FSL_FEATURE_EDMA_INSTANCE_SUPPORT_128_BYTES_TRANSFERn.
1613  */
EDMA_PrepareTransferConfig(edma_transfer_config_t * config,void * srcAddr,uint32_t srcWidth,int16_t srcOffset,void * destAddr,uint32_t destWidth,int16_t destOffset,uint32_t bytesEachRequest,uint32_t transferBytes)1614 void EDMA_PrepareTransferConfig(edma_transfer_config_t *config,
1615                                 void *srcAddr,
1616                                 uint32_t srcWidth,
1617                                 int16_t srcOffset,
1618                                 void *destAddr,
1619                                 uint32_t destWidth,
1620                                 int16_t destOffset,
1621                                 uint32_t bytesEachRequest,
1622                                 uint32_t transferBytes)
1623 {
1624     assert(config != NULL);
1625     assert(srcAddr != NULL);
1626     assert(destAddr != NULL);
1627 #if (defined(FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER)
1628     assert((srcWidth != 0U) && (srcWidth <= 128U) && ((srcWidth & (srcWidth - 1U)) == 0U));
1629     assert((destWidth != 0U) && (destWidth <= 128U) && ((destWidth & (destWidth - 1U)) == 0U));
1630 #elif (defined(FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER)
1631     assert((srcWidth != 0U) && (srcWidth <= 64U) && ((srcWidth & (srcWidth - 1U)) == 0U));
1632     assert((destWidth != 0U) && (destWidth <= 64U) && ((destWidth & (destWidth - 1U)) == 0U));
1633 #else
1634     assert((srcWidth != 0U) && (srcWidth <= 32U) && ((srcWidth & (srcWidth - 1U)) == 0U));
1635     assert((destWidth != 0U) && (destWidth <= 32U) && ((destWidth & (destWidth - 1U)) == 0U));
1636 #endif
1637 #if (!defined(FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER) || !FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER)
1638     assert(srcWidth != 8U);
1639     assert(srcWidth != 8U);
1640 #endif
1641 #if (!defined(FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER) || !FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER)
1642     assert(srcWidth != 16U);
1643     assert(srcWidth != 16U);
1644 #endif
1645 #if (!defined(FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER) || !FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER)
1646     assert(srcWidth != 64U);
1647     assert(srcWidth != 64U);
1648 #endif
1649     assert((transferBytes % bytesEachRequest) == 0U);
1650     assert((((uint32_t)(uint8_t *)srcAddr) % srcWidth) == 0U);
1651     assert((((uint32_t)(uint8_t *)destAddr) % destWidth) == 0U);
1652 
1653     /* Initializes the configure structure to zero. */
1654     (void)memset(config, 0, sizeof(*config));
1655 
1656     config->destAddr         = CONVERT_TO_DMA_ADDRESS((uint32_t)(uint32_t *)destAddr);
1657     config->srcAddr          = CONVERT_TO_DMA_ADDRESS((uint32_t)(uint32_t *)srcAddr);
1658     config->minorLoopBytes   = bytesEachRequest;
1659     config->majorLoopCounts  = transferBytes / bytesEachRequest;
1660     config->srcTransferSize  = EDMA_TransferWidthMapping(srcWidth);
1661     config->destTransferSize = EDMA_TransferWidthMapping(destWidth);
1662     config->destOffset       = destOffset;
1663     config->srcOffset        = srcOffset;
1664     /* enable major interrupt by default */
1665     config->enabledInterruptMask = (uint16_t)kEDMA_MajorInterruptEnable;
1666 }
1667 
1668 /*!
1669  * brief Prepares the eDMA transfer structure.
1670  *
1671  * This function prepares the transfer configuration structure according to the user input.
1672  *
1673  * param config The user configuration structure of type edma_transfer_t.
1674  * param srcAddr eDMA transfer source address.
1675  * param srcWidth eDMA transfer source address width(bytes).
1676  * param destAddr eDMA transfer destination address.
1677  * param destWidth eDMA transfer destination address width(bytes).
1678  * param bytesEachRequest eDMA transfer bytes per channel request.
1679  * param transferBytes eDMA transfer bytes to be transferred.
1680  * param type eDMA transfer type.
1681  * note The data address and the data width must be consistent. For example, if the SRC
1682  *       is 4 bytes, the source address must be 4 bytes aligned, or it results in
1683  *       source address error (SAE).
1684  */
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)1685 void EDMA_PrepareTransfer(edma_transfer_config_t *config,
1686                           void *srcAddr,
1687                           uint32_t srcWidth,
1688                           void *destAddr,
1689                           uint32_t destWidth,
1690                           uint32_t bytesEachRequest,
1691                           uint32_t transferBytes,
1692                           edma_transfer_type_t type)
1693 {
1694     assert(config != NULL);
1695 
1696     int16_t srcOffset = 0, destOffset = 0;
1697 
1698     switch (type)
1699     {
1700         case kEDMA_MemoryToMemory:
1701             destOffset = (int16_t)destWidth;
1702             srcOffset  = (int16_t)srcWidth;
1703             break;
1704         case kEDMA_MemoryToPeripheral:
1705             destOffset = 0;
1706             srcOffset  = (int16_t)srcWidth;
1707             break;
1708         case kEDMA_PeripheralToMemory:
1709             destOffset = (int16_t)destWidth;
1710             srcOffset  = 0;
1711             break;
1712         case kEDMA_PeripheralToPeripheral:
1713             destOffset = 0;
1714             srcOffset  = 0;
1715             break;
1716         default:
1717             /* All the cases have been listed above, the default clause should not be reached. */
1718             assert(false);
1719             break;
1720     }
1721 
1722     EDMA_PrepareTransferConfig(config, srcAddr, srcWidth, srcOffset, destAddr, destWidth, destOffset, bytesEachRequest,
1723                                transferBytes);
1724 }
1725 
1726 /*!
1727  * brief Prepares the eDMA transfer content descriptor.
1728  *
1729  * This function prepares the transfer content descriptor structure according to the user input.
1730  *
1731  * param handle eDMA handle pointer.
1732  * param tcd Pointer to eDMA transfer content descriptor structure.
1733  * param srcAddr eDMA transfer source address.
1734  * param srcWidth eDMA transfer source address width(bytes).
1735  * param srcOffset source address offset.
1736  * param destAddr eDMA transfer destination address.
1737  * param destWidth eDMA transfer destination address width(bytes).
1738  * param destOffset destination address offset.
1739  * param bytesEachRequest eDMA transfer bytes per channel request.
1740  * param transferBytes eDMA transfer bytes to be transferred.
1741  * param nextTcd eDMA transfer linked TCD address.
1742  *
1743  * note The data address and the data width must be consistent. For example, if the SRC
1744  *       is 4 bytes, the source address must be 4 bytes aligned, or it results in
1745  *       source address error (SAE).
1746  */
EDMA_PrepareTransferTCD(edma_handle_t * handle,edma_tcd_t * tcd,void * srcAddr,uint32_t srcWidth,int16_t srcOffset,void * destAddr,uint32_t destWidth,int16_t destOffset,uint32_t bytesEachRequest,uint32_t transferBytes,edma_tcd_t * nextTcd)1747 void EDMA_PrepareTransferTCD(edma_handle_t *handle,
1748                              edma_tcd_t *tcd,
1749                              void *srcAddr,
1750                              uint32_t srcWidth,
1751                              int16_t srcOffset,
1752                              void *destAddr,
1753                              uint32_t destWidth,
1754                              int16_t destOffset,
1755                              uint32_t bytesEachRequest,
1756                              uint32_t transferBytes,
1757                              edma_tcd_t *nextTcd)
1758 {
1759     assert(tcd != NULL);
1760     assert(srcAddr != NULL);
1761     assert(destAddr != NULL);
1762 #if (defined(FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER)
1763     assert((srcWidth != 0U) && (srcWidth <= 128U) && ((srcWidth & (srcWidth - 1U)) == 0U) &&
1764            (FSL_FEATURE_EDMA_INSTANCE_SUPPORT_128_BYTES_TRANSFERn(handle->base) == 1));
1765     assert((destWidth != 0U) && (destWidth <= 128U) && ((destWidth & (destWidth - 1U)) == 0U) &&
1766            (FSL_FEATURE_EDMA_INSTANCE_SUPPORT_128_BYTES_TRANSFERn(handle->base) == 1));
1767 #elif (defined(FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER)
1768     assert((srcWidth != 0U) && (srcWidth <= 64U) && ((srcWidth & (srcWidth - 1U)) == 0U));
1769     assert((destWidth != 0U) && (destWidth <= 64U) && ((destWidth & (destWidth - 1U)) == 0U));
1770 #else
1771     assert((srcWidth != 0U) && (srcWidth <= 32U) && ((srcWidth & (srcWidth - 1U)) == 0U));
1772     assert((destWidth != 0U) && (destWidth <= 32U) && ((destWidth & (destWidth - 1U)) == 0U));
1773 #endif
1774 #if (!defined(FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER) || !FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER)
1775     assert(srcWidth != 8U);
1776     assert(srcWidth != 8U);
1777 #endif
1778 #if (!defined(FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER) || !FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER)
1779     assert(srcWidth != 16U);
1780     assert(srcWidth != 16U);
1781 #endif
1782 #if (!defined(FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER) || !FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER)
1783     assert(srcWidth != 64U);
1784     assert(srcWidth != 64U);
1785 #endif
1786     assert((transferBytes % bytesEachRequest) == 0U);
1787     assert((((uint32_t)(uint32_t *)srcAddr) % srcWidth) == 0U);
1788     assert((((uint32_t)(uint32_t *)destAddr) % destWidth) == 0U);
1789 
1790     edma_transfer_size_t srcTransferSize  = EDMA_TransferWidthMapping(srcWidth),
1791                          destTransferSize = EDMA_TransferWidthMapping(srcWidth);
1792 
1793     /* Initializes the configure structure to zero. */
1794     EDMA_TcdResetExt(handle->base, tcd);
1795     assert((bytesEachRequest % (1UL << ((uint32_t)srcTransferSize))) == 0U);
1796     assert((bytesEachRequest % (1UL << ((uint32_t)destTransferSize))) == 0U);
1797     assert(((uint32_t)srcOffset % (1UL << ((uint32_t)srcTransferSize))) == 0U);
1798     assert(((uint32_t)destOffset % (1UL << ((uint32_t)destTransferSize))) == 0U);
1799     assert(((uint32_t)(uint32_t *)srcAddr % (1UL << ((uint32_t)srcTransferSize))) == 0U);
1800     assert(((uint32_t)(uint32_t *)destAddr % (1UL << ((uint32_t)destTransferSize))) == 0U);
1801 
1802     EDMA_TCD_SADDR(tcd, EDMA_TCD_TYPE(handle->base)) = CONVERT_TO_DMA_ADDRESS((uint32_t *)srcAddr);
1803     /* destination address */
1804     EDMA_TCD_DADDR(tcd, EDMA_TCD_TYPE(handle->base)) = CONVERT_TO_DMA_ADDRESS((uint32_t *)destAddr);
1805     /* Source data and destination data transfer size */
1806     EDMA_TCD_ATTR(tcd, EDMA_TCD_TYPE(handle->base)) = DMA_ATTR_SSIZE(srcTransferSize) | DMA_ATTR_DSIZE(destTransferSize);
1807 
1808     /* Source address signed offset */
1809     EDMA_TCD_SOFF(tcd, EDMA_TCD_TYPE(handle->base)) = (uint16_t)(srcOffset);
1810     /* Destination address signed offset */
1811     EDMA_TCD_DOFF(tcd, EDMA_TCD_TYPE(handle->base)) = (uint16_t)(destOffset);
1812 
1813     EDMA_TCD_NBYTES(tcd, EDMA_TCD_TYPE(handle->base)) = DMA_NBYTES_MLOFFNO_NBYTES(bytesEachRequest);
1814 
1815     /* Current major iteration count */
1816     EDMA_TCD_CITER(tcd, EDMA_TCD_TYPE(handle->base)) = (uint16_t)(transferBytes / bytesEachRequest);
1817     /* Starting major iteration count */
1818     EDMA_TCD_BITER(tcd, EDMA_TCD_TYPE(handle->base)) = (uint16_t)(transferBytes / bytesEachRequest);
1819     /* reset CSR firstly */
1820     EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(handle->base)) = DMA_CSR_DREQ(1U);
1821     /* Enable scatter/gather processing */
1822     if (nextTcd != NULL)
1823     {
1824         EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(handle->base)) = CONVERT_TO_DMA_ADDRESS(nextTcd);
1825         /*
1826             Before call EDMA_TcdSetTransferConfig or EDMA_SetTransferConfig,
1827             user must call EDMA_TcdReset or EDMA_ResetChannel which will set
1828             DREQ, so must use "|" or "&" rather than "=".
1829 
1830             Clear the DREQ bit because scatter gather has been enabled, so the
1831             previous transfer is not the last transfer, and channel request should
1832             be enabled at the next transfer(the next TCD).
1833         */
1834         EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(handle->base)) =
1835             (EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(handle->base)) | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
1836     }
1837 
1838     /* configure interrupt/auto disable channel request, enable major interrupt by default */
1839     EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(handle->base)) |=
1840         (EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(handle->base)) & (~(uint16_t)kEDMA_ErrorInterruptEnable)) |
1841         (uint16_t)kEDMA_MajorInterruptEnable;
1842 }
1843 
1844 /*!
1845  * brief Submits the eDMA transfer content descriptor.
1846  *
1847  * This function submits the eDMA transfer request according to the transfer content descriptor.
1848  * In scatter gather mode, call this function will add a configured tcd to the circular list of tcd pool.
1849  * The tcd pools is setup by call function EDMA_InstallTCDMemory before.
1850  *
1851  * Typical user case:
1852  * 1. submit single transfer
1853  * code
1854  * edma_tcd_t tcd;
1855  * EDMA_PrepareTransferTCD(handle, tcd, ....)
1856  * EDMA_SubmitTransferTCD(handle, tcd)
1857  * EDMA_StartTransfer(handle)
1858  * endcode
1859  *
1860  * 2. submit static link transfer,
1861  * code
1862  * edma_tcd_t tcd[2];
1863  * EDMA_PrepareTransferTCD(handle, &tcd[0], ....)
1864  * EDMA_PrepareTransferTCD(handle, &tcd[1], ....)
1865  * EDMA_SubmitTransferTCD(handle, &tcd[0])
1866  * EDMA_StartTransfer(handle)
1867  * endcode
1868  *
1869  * 3. submit dynamic link transfer
1870  * code
1871  * edma_tcd_t tcdpool[2];
1872  * EDMA_InstallTCDMemory(&g_DMA_Handle, tcdpool, 2);
1873  * edma_tcd_t tcd;
1874  * EDMA_PrepareTransferTCD(handle, tcd, ....)
1875  * EDMA_SubmitTransferTCD(handle, tcd)
1876  * EDMA_PrepareTransferTCD(handle, tcd, ....)
1877  * EDMA_SubmitTransferTCD(handle, tcd)
1878  * EDMA_StartTransfer(handle)
1879  * endcode
1880  *
1881  * 4. submit loop transfer
1882  * code
1883  * edma_tcd_t tcd[2];
1884  * EDMA_PrepareTransferTCD(handle, &tcd[0], ...,&tcd[1])
1885  * EDMA_PrepareTransferTCD(handle, &tcd[1], ..., &tcd[0])
1886  * EDMA_SubmitTransferTCD(handle, &tcd[0])
1887  * EDMA_StartTransfer(handle)
1888  * endcode
1889  *
1890  * param handle eDMA handle pointer.
1891  * param tcd Pointer to eDMA transfer content descriptor structure.
1892  *
1893  * retval kStatus_EDMA_Success It means submit transfer request succeed.
1894  * retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
1895  * retval kStatus_EDMA_Busy It means the given channel is busy, need to submit request later.
1896  */
EDMA_SubmitTransferTCD(edma_handle_t * handle,edma_tcd_t * tcd)1897 status_t EDMA_SubmitTransferTCD(edma_handle_t *handle, edma_tcd_t *tcd)
1898 {
1899     assert(handle != NULL);
1900     assert(handle->tcdBase != NULL);
1901 
1902     edma_tcd_t *tcdRegs = handle->tcdBase;
1903 
1904     if (handle->tcdPool == NULL)
1905     {
1906         /*
1907          *    Check if EDMA channel is busy:
1908          *    1. if channel active bit is set, it implies that minor loop is executing, then channel is busy
1909          *    2. if channel active bit is not set and BITER not equal to CITER, it implies that major loop is executing,
1910          * then channel is busy
1911          *
1912          *    There is one case can not be covered in below condition:
1913          *    When transfer request is submitted, but no request from peripheral, that is to say channel sevice doesn't
1914          *    begin, if application would like to submit another transfer , then the TCD will be overwritten, since the
1915          *    ACTIVE is 0 and BITER = CITER, for such case, it is a scatter gather(link TCD) case actually, so
1916          *    application should enabled TCD pool for dynamic scatter gather mode by calling EDMA_InstallTCDMemory.
1917          */
1918 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
1919         if (((tcdRegs->CSR & DMA_CSR_ACTIVE_MASK) != 0U) ||
1920 #else
1921         if (((handle->channelBase->CH_CSR & DMA_CH_CSR_ACTIVE_MASK) != 0U) ||
1922 #endif
1923             (((EDMA_TCD_CITER(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_CITER_ELINKNO_CITER_MASK) !=
1924               (EDMA_TCD_BITER(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_BITER_ELINKNO_BITER_MASK))))
1925         {
1926             return kStatus_EDMA_Busy;
1927         }
1928         else
1929         {
1930             EDMA_InstallTCD(handle->base, handle->channel, tcd);
1931             /* Enable auto disable request feature */
1932             EDMA_EnableAutoStopRequest(handle->base, handle->channel, true);
1933             /* Enable major interrupt */
1934             EDMA_EnableChannelInterrupts(handle->base, handle->channel, kEDMA_MajorInterruptEnable);
1935 
1936             return kStatus_Success;
1937         }
1938     }
1939     else /* Use the TCD queue. */
1940     {
1941         uint32_t primask;
1942         uint16_t csr;
1943         int8_t currentTcd;
1944         int8_t previousTcd;
1945         int8_t nextTcd;
1946         int8_t tmpTcdUsed;
1947         int8_t tmpTcdSize;
1948 
1949         /* Check if tcd pool is full. */
1950         primask    = DisableGlobalIRQ();
1951         tmpTcdUsed = handle->tcdUsed;
1952         tmpTcdSize = handle->tcdSize;
1953         if (tmpTcdUsed >= tmpTcdSize)
1954         {
1955             EnableGlobalIRQ(primask);
1956 
1957             return kStatus_EDMA_QueueFull;
1958         }
1959         currentTcd = handle->tail;
1960         handle->tcdUsed++;
1961         /* Calculate index of next TCD */
1962         nextTcd = currentTcd + 1;
1963         if (nextTcd == handle->tcdSize)
1964         {
1965             nextTcd = 0;
1966         }
1967         /* Advance queue tail index */
1968         handle->tail = nextTcd;
1969         EnableGlobalIRQ(primask);
1970         /* Calculate index of previous TCD */
1971         previousTcd = currentTcd != 0 ? currentTcd - 1 : (handle->tcdSize - 1);
1972 
1973         /* Configure current TCD block. */
1974         EDMA_TcdResetExt(handle->base, &handle->tcdPool[currentTcd]);
1975         (void)memcpy(&handle->tcdPool[currentTcd], tcd, sizeof(edma_tcd_t));
1976 
1977         /* Enable major interrupt */
1978         EDMA_TCD_CSR((&handle->tcdPool[currentTcd]), EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_INTMAJOR_MASK;
1979 
1980         if ((EDMA_TCD_DLAST_SGA(tcd, EDMA_TCD_TYPE(handle->base)) == 0U) ||
1981             ((EDMA_TCD_CSR(tcd, EDMA_TCD_TYPE(handle->base)) & DMA_CSR_ESG_MASK) == 0U))
1982         {
1983             /* Link current TCD with next TCD for identification of current TCD */
1984             EDMA_TCD_DLAST_SGA((&handle->tcdPool[currentTcd]), EDMA_TCD_TYPE(handle->base)) =
1985                 CONVERT_TO_DMA_ADDRESS((uint32_t)&handle->tcdPool[nextTcd]);
1986         }
1987 
1988         /* Chain from previous descriptor unless tcd pool size is 1(this descriptor is its own predecessor). */
1989         if (currentTcd != previousTcd)
1990         {
1991 #if defined FSL_FEATURE_EDMA_HAS_ERRATA_51327
1992             if (EDMA_CheckErrata(handle->base, &handle->tcdPool[previousTcd]) != kStatus_Success)
1993             {
1994                 return kStatus_InvalidArgument;
1995             }
1996 #endif
1997             /* Enable scatter/gather feature in the previous TCD block. */
1998             csr = EDMA_TCD_CSR((&handle->tcdPool[previousTcd]), EDMA_TCD_TYPE(handle->base)) |
1999                   ((uint16_t)DMA_CSR_ESG_MASK);
2000             csr &= ~((uint16_t)DMA_CSR_DREQ_MASK);
2001             EDMA_TCD_CSR((&handle->tcdPool[previousTcd]), EDMA_TCD_TYPE(handle->base)) = csr;
2002             /*
2003                 Check if the TCD block in the registers is the previous one (points to current TCD block). It
2004                 is used to check if the previous TCD linked has been loaded in TCD register. If so, it need to
2005                 link the TCD register in case link the current TCD with the dead chain when TCD loading occurs
2006                 before link the previous TCD block.
2007             */
2008             if (EDMA_TCD_DLAST_SGA(tcdRegs, EDMA_TCD_TYPE(handle->base)) ==
2009                 CONVERT_TO_DMA_ADDRESS((uint32_t)&handle->tcdPool[currentTcd]))
2010             {
2011                 /* Clear the DREQ bits for the dynamic scatter gather */
2012                 EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_DREQ_MASK;
2013                 /* Enable scatter/gather also in the TCD registers. */
2014                 csr = EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) | DMA_CSR_ESG_MASK;
2015                 /* Must write the CSR register one-time, because the transfer maybe finished anytime. */
2016                 EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) = csr;
2017                 /*
2018                     It is very important to check the ESG bit!
2019                     Because this hardware design: if DONE bit is set, the ESG bit can not be set. So it can
2020                     be used to check if the dynamic TCD link operation is successful. If ESG bit is not set
2021                     and the DLAST_SGA is not the next TCD address(it means the dynamic TCD link succeed and
2022                     the current TCD block has been loaded into TCD registers), it means transfer finished
2023                     and TCD link operation fail, so must install TCD content into TCD registers and enable
2024                     transfer again. And if ESG is set, it means transfer has not finished, so TCD dynamic
2025                     link succeed.
2026                 */
2027                 if (0U != (EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_CSR_ESG_MASK))
2028                 {
2029                     EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) &= ~(uint16_t)DMA_CSR_DREQ_MASK;
2030                     return kStatus_Success;
2031                 }
2032                 /*
2033                     Check whether the current TCD block is already loaded in the TCD registers. It is another
2034                     condition when ESG bit is not set: it means the dynamic TCD link succeed and the current
2035                     TCD block has been loaded into TCD registers.
2036                 */
2037                 if (EDMA_TCD_DLAST_SGA(tcdRegs, EDMA_TCD_TYPE(handle->base)) ==
2038                     CONVERT_TO_DMA_ADDRESS((uint32_t)&handle->tcdPool[nextTcd]))
2039                 {
2040                     return kStatus_Success;
2041                 }
2042                 /*
2043                     If go to this, means the previous transfer finished, and the DONE bit is set.
2044                     So shall configure TCD registers.
2045                 */
2046             }
2047             else if (EDMA_TCD_DLAST_SGA(tcdRegs, EDMA_TCD_TYPE(handle->base)) != 0UL)
2048             {
2049                 /* The current TCD block has been linked successfully. */
2050                 return kStatus_Success;
2051             }
2052             else
2053             {
2054                 /*
2055                     DLAST_SGA is 0 and it means the first submit transfer, so shall configure
2056                     TCD registers.
2057                 */
2058             }
2059         }
2060         /* There is no live chain, TCD block need to be installed in TCD registers. */
2061         EDMA_InstallTCD(handle->base, handle->channel, &handle->tcdPool[currentTcd]);
2062 
2063         return kStatus_Success;
2064     }
2065 }
2066 
2067 /*!
2068  * brief Submits the eDMA transfer request.
2069  *
2070  * This function submits the eDMA transfer request according to the transfer configuration structure.
2071  * In scatter gather mode, call this function will add a configured tcd to the circular list of tcd pool.
2072  * The tcd pools is setup by call function EDMA_InstallTCDMemory before.
2073  *
2074  * param handle eDMA handle pointer.
2075  * param config Pointer to eDMA transfer configuration structure.
2076  * retval kStatus_EDMA_Success It means submit transfer request succeed.
2077  * retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
2078  * retval kStatus_EDMA_Busy It means the given channel is busy, need to submit request later.
2079  */
EDMA_SubmitTransfer(edma_handle_t * handle,const edma_transfer_config_t * config)2080 status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config)
2081 {
2082     assert(handle != NULL);
2083     assert(config != NULL);
2084     assert(handle->tcdBase != NULL);
2085 #if (defined(FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER)
2086     assert(((config->srcTransferSize != kEDMA_TransferSize128Bytes) &&
2087             (config->destTransferSize != kEDMA_TransferSize128Bytes)) ||
2088            (FSL_FEATURE_EDMA_INSTANCE_SUPPORT_128_BYTES_TRANSFERn(handle->base) == 1));
2089 #endif
2090     edma_tcd_t *tcdRegs = handle->tcdBase;
2091 
2092     if (handle->tcdPool == NULL)
2093     {
2094         /*
2095          *    Check if EDMA channel is busy:
2096          *    1. if channel active bit is set, it implies that minor loop is executing, then channel is busy
2097          *    2. if channel active bit is not set and BITER not equal to CITER, it implies that major loop is executing,
2098          * then channel is busy
2099          *
2100          *    There is one case can not be covered in below condition:
2101          *    When transfer request is submitted, but no request from peripheral, that is to say channel sevice doesn't
2102          *    begin, if application would like to submit another transfer , then the TCD will be overwritten, since the
2103          *    ACTIVE is 0 and BITER = CITER, for such case, it is a scatter gather(link TCD) case actually, so
2104          *    application should enabled TCD pool for dynamic scatter gather mode by calling EDMA_InstallTCDMemory.
2105          */
2106 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2107         if (((tcdRegs->CSR & DMA_CSR_ACTIVE_MASK) != 0U) ||
2108 #else
2109         if (((handle->channelBase->CH_CSR & DMA_CH_CSR_ACTIVE_MASK) != 0U) ||
2110 #endif
2111             (((EDMA_TCD_CITER(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_CITER_ELINKNO_CITER_MASK) !=
2112               (EDMA_TCD_BITER(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_BITER_ELINKNO_BITER_MASK))))
2113         {
2114             return kStatus_EDMA_Busy;
2115         }
2116         else
2117         {
2118             EDMA_TcdSetTransferConfigExt(handle->base, tcdRegs, config, NULL);
2119             /* Enable auto disable request feature */
2120             EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_DREQ_MASK;
2121             /* Enable major interrupt */
2122             EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_INTMAJOR_MASK;
2123 
2124             return kStatus_Success;
2125         }
2126     }
2127     else /* Use the TCD queue. */
2128     {
2129         uint32_t primask;
2130         uint16_t csr;
2131         int8_t currentTcd;
2132         int8_t previousTcd;
2133         int8_t nextTcd;
2134         int8_t tmpTcdUsed;
2135         int8_t tmpTcdSize;
2136 
2137         /* Check if tcd pool is full. */
2138         primask    = DisableGlobalIRQ();
2139         tmpTcdUsed = handle->tcdUsed;
2140         tmpTcdSize = handle->tcdSize;
2141         if (tmpTcdUsed >= tmpTcdSize)
2142         {
2143             EnableGlobalIRQ(primask);
2144 
2145             return kStatus_EDMA_QueueFull;
2146         }
2147         currentTcd = handle->tail;
2148         handle->tcdUsed++;
2149         /* Calculate index of next TCD */
2150         nextTcd = currentTcd + 1;
2151         if (nextTcd == handle->tcdSize)
2152         {
2153             nextTcd = 0;
2154         }
2155         /* Advance queue tail index */
2156         handle->tail = nextTcd;
2157         EnableGlobalIRQ(primask);
2158         /* Calculate index of previous TCD */
2159         previousTcd = currentTcd != 0 ? currentTcd - 1 : (handle->tcdSize - 1);
2160         /* Configure current TCD block. */
2161         EDMA_TcdResetExt(handle->base, &handle->tcdPool[currentTcd]);
2162         EDMA_TcdSetTransferConfigExt(handle->base, &handle->tcdPool[currentTcd], config, NULL);
2163         /* Enable major interrupt */
2164         EDMA_TCD_CSR((&handle->tcdPool[currentTcd]), EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_INTMAJOR_MASK;
2165         /* Link current TCD with next TCD for identification of current TCD */
2166         EDMA_TCD_DLAST_SGA((&handle->tcdPool[currentTcd]), EDMA_TCD_TYPE(handle->base)) =
2167             CONVERT_TO_DMA_ADDRESS((uint32_t)&handle->tcdPool[nextTcd]);
2168         /* Chain from previous descriptor unless tcd pool size is 1(this descriptor is its own predecessor). */
2169         if (currentTcd != previousTcd)
2170         {
2171 #if defined FSL_FEATURE_EDMA_HAS_ERRATA_51327
2172             if (EDMA_CheckErrata(handle->base, &handle->tcdPool[previousTcd]) != kStatus_Success)
2173             {
2174                 return kStatus_InvalidArgument;
2175             }
2176 #endif
2177             /* Enable scatter/gather feature in the previous TCD block. */
2178             csr = EDMA_TCD_CSR((&handle->tcdPool[previousTcd]), EDMA_TCD_TYPE(handle->base)) |
2179                   ((uint16_t)DMA_CSR_ESG_MASK);
2180             csr &= ~((uint16_t)DMA_CSR_DREQ_MASK);
2181             EDMA_TCD_CSR((&handle->tcdPool[previousTcd]), EDMA_TCD_TYPE(handle->base)) = csr;
2182             /*
2183                 Check if the TCD block in the registers is the previous one (points to current TCD block). It
2184                 is used to check if the previous TCD linked has been loaded in TCD register. If so, it need to
2185                 link the TCD register in case link the current TCD with the dead chain when TCD loading occurs
2186                 before link the previous TCD block.
2187             */
2188             if (EDMA_TCD_DLAST_SGA(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) ==
2189                 CONVERT_TO_DMA_ADDRESS((uint32_t)&handle->tcdPool[currentTcd]))
2190             {
2191                 /* Clear the DREQ bits for the dynamic scatter gather */
2192                 EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_DREQ_MASK;
2193                 /* Enable scatter/gather also in the TCD registers. */
2194                 csr = EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) | DMA_CSR_ESG_MASK;
2195                 /* Must write the CSR register one-time, because the transfer maybe finished anytime. */
2196                 EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) = csr;
2197                 /*
2198                     It is very important to check the ESG bit!
2199                     Because this hardware design: if DONE bit is set, the ESG bit can not be set. So it can
2200                     be used to check if the dynamic TCD link operation is successful. If ESG bit is not set
2201                     and the DLAST_SGA is not the next TCD address(it means the dynamic TCD link succeed and
2202                     the current TCD block has been loaded into TCD registers), it means transfer finished
2203                     and TCD link operation fail, so must install TCD content into TCD registers and enable
2204                     transfer again. And if ESG is set, it means transfer has not finished, so TCD dynamic
2205                     link succeed.
2206                 */
2207                 if (0U != (EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_CSR_ESG_MASK))
2208                 {
2209                     EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) &= ~(uint16_t)DMA_CSR_DREQ_MASK;
2210                     return kStatus_Success;
2211                 }
2212                 /*
2213                     Check whether the current TCD block is already loaded in the TCD registers. It is another
2214                     condition when ESG bit is not set: it means the dynamic TCD link succeed and the current
2215                     TCD block has been loaded into TCD registers.
2216                 */
2217                 if (EDMA_TCD_DLAST_SGA(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) ==
2218                     CONVERT_TO_DMA_ADDRESS((uint32_t)&handle->tcdPool[nextTcd]))
2219                 {
2220                     return kStatus_Success;
2221                 }
2222                 /*
2223                     If go to this, means the previous transfer finished, and the DONE bit is set.
2224                     So shall configure TCD registers.
2225                 */
2226             }
2227             else if (EDMA_TCD_DLAST_SGA(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) != 0UL)
2228             {
2229                 /* The current TCD block has been linked successfully. */
2230                 return kStatus_Success;
2231             }
2232             else
2233             {
2234                 /*
2235                     DLAST_SGA is 0 and it means the first submit transfer, so shall configure
2236                     TCD registers.
2237                 */
2238             }
2239         }
2240         /* There is no live chain, TCD block need to be installed in TCD registers. */
2241         EDMA_InstallTCD(handle->base, handle->channel, &handle->tcdPool[currentTcd]);
2242 
2243         return kStatus_Success;
2244     }
2245 }
2246 
2247 /*!
2248  * brief Submits the eDMA scatter gather transfer configurations.
2249  *
2250  * The function is target for submit loop transfer request,
2251  * the ring transfer request means that the transfer request TAIL is link to HEAD, such as,
2252  * A->B->C->D->A, or A->A
2253  *
2254  * To use the ring transfer feature, the application should allocate several transfer object, such as
2255  * @code
2256  * edma_channel_transfer_config_t transfer[2];
2257  * EDMA_TransferSubmitLoopTransfer(handle, &transfer, 2U);
2258  * @endcode
2259  * Then eDMA driver will link transfer[0] and transfer[1] to each other
2260  *
2261  * note Application should check the return value of this function to avoid transfer request
2262  * submit failed
2263  *
2264  * param handle eDMA handle pointer
2265  * param transfer pointer to user's eDMA channel configure structure, see edma_channel_transfer_config_t for detail
2266  * param transferLoopCount the count of the transfer ring, if loop count is 1, that means that the one will link to
2267  * itself.
2268  *
2269  * retval #kStatus_Success It means submit transfer request succeed
2270  * retval #kStatus_EDMA_Busy channel is in busy status
2271  * retval #kStatus_InvalidArgument Invalid Argument
2272  */
EDMA_SubmitLoopTransfer(edma_handle_t * handle,edma_transfer_config_t * transfer,uint32_t transferLoopCount)2273 status_t EDMA_SubmitLoopTransfer(edma_handle_t *handle, edma_transfer_config_t *transfer, uint32_t transferLoopCount)
2274 {
2275     assert(transfer != NULL);
2276     assert(handle != NULL);
2277     assert(handle->tcdPool != NULL);
2278 
2279     uint32_t i = 0U;
2280 
2281     if (handle->tcdSize < (int8_t)transferLoopCount)
2282     {
2283         return kStatus_InvalidArgument;
2284     }
2285 
2286     /*
2287      *    Check if EDMA channel is busy:
2288      *    1. if channel active bit is set, it implies that minor loop is executing, then channel is busy
2289      *    2. if channel active bit is not set and BITER not equal to CITER, it implies that major loop is executing,
2290      *       then channel is busy
2291      *
2292      *    There is one case can not be covered in below condition:
2293      *    When transfer request is submitted, but no request from peripheral, that is to say channel service doesn't
2294      *    begin, if application would like to submit another transfer , then the TCD will be overwritten, since the
2295      *    ACTIVE is 0 and BITER = CITER, for such case, it is a scatter gather(link TCD) case actually, so
2296      *    application should enabled TCD pool for dynamic scatter gather mode by calling EDMA_InstallTCDMemory.
2297      */
2298 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2299     if (((handle->tcdBase->CSR & DMA_CSR_ACTIVE_MASK) != 0U) ||
2300 #else
2301     if (((handle->channelBase->CH_CSR & DMA_CH_CSR_ACTIVE_MASK) != 0U) ||
2302 #endif
2303         (((EDMA_TCD_CITER(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) & DMA_CITER_ELINKNO_CITER_MASK) !=
2304           (EDMA_TCD_BITER(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) & DMA_BITER_ELINKNO_BITER_MASK))))
2305     {
2306         return kStatus_EDMA_Busy;
2307     }
2308 
2309     (void)memset(handle->tcdPool, 0, (uint32_t)handle->tcdSize * sizeof(edma_tcd_t));
2310     for (i = 0U; i < transferLoopCount - 1UL; i++)
2311     {
2312         transfer[i].linkTCD = &handle->tcdPool[i + 1UL];
2313         EDMA_ConfigChannelSoftwareTCDExt(handle->base, &(handle->tcdPool[i]), &transfer[i]);
2314 #if defined FSL_FEATURE_EDMA_HAS_ERRATA_51327
2315         if (EDMA_CheckErrata(handle->base, &(handle->tcdPool[i])) != kStatus_Success)
2316         {
2317             return kStatus_InvalidArgument;
2318         }
2319 #endif
2320     }
2321 
2322     /* prepare last one in the ring and link it to the HEAD of the ring */
2323     transfer[i].linkTCD = &handle->tcdPool[0];
2324     EDMA_ConfigChannelSoftwareTCDExt(handle->base, &(handle->tcdPool[i]), &transfer[i]);
2325 
2326 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2327     if (((transfer->enableSrcMinorLoopOffset) || (transfer->enableDstMinorLoopOffset)))
2328     {
2329         EDMA_EnableMinorLoopMapping(handle->psBase, true);
2330     }
2331 #endif
2332     /* There is no live chain, TCD block need to be installed in TCD registers. */
2333     EDMA_InstallTCD(handle->base, handle->channel, &handle->tcdPool[0U]);
2334 
2335     /* enable interrupt */
2336     EDMA_EnableChannelInterrupts(handle->base, handle->channel,
2337                                  ((uint32_t)transfer->enabledInterruptMask & ~((uint32_t)kEDMA_ErrorInterruptEnable)));
2338 
2339     return kStatus_Success;
2340 }
2341 
2342 /*!
2343  * brief eDMA starts transfer.
2344  *
2345  * This function enables the channel request. Users can call this function after submitting the transfer request
2346  * or before submitting the transfer request.
2347  *
2348  * param handle eDMA handle pointer.
2349  */
EDMA_StartTransfer(edma_handle_t * handle)2350 void EDMA_StartTransfer(edma_handle_t *handle)
2351 {
2352     assert(handle != NULL);
2353 
2354     edma_tcd_t *tcdRegs = handle->tcdBase;
2355 
2356 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2357     if (handle->tcdPool == NULL)
2358     {
2359         handle->base->SERQ = DMA_SERQ_SERQ(handle->channel);
2360     }
2361     else /* Use the TCD queue. */
2362     {
2363         uint32_t primask;
2364 
2365         /* Check if there was at least one descriptor submitted since reset (TCD in registers is valid) */
2366         if (tcdRegs->DLAST_SGA != 0U)
2367         {
2368             primask = DisableGlobalIRQ();
2369             /* Check if channel request is actually disable. */
2370             if ((handle->base->ERQ & ((uint32_t)1U << handle->channel)) == 0U)
2371             {
2372                 /* Check if transfer is paused. */
2373                 tmpCSR = tcdRegs->CSR;
2374                 if ((0U == (tmpCSR & DMA_CSR_DONE_MASK)) || (0U != (tmpCSR & DMA_CSR_ESG_MASK)))
2375                 {
2376                     /*
2377                         Re-enable channel request must be as soon as possible, so must put it into
2378                         critical section to avoid task switching or interrupt service routine.
2379                     */
2380                     handle->base->SERQ = DMA_SERQ_SERQ(handle->channel);
2381                 }
2382             }
2383             EnableGlobalIRQ(primask);
2384         }
2385     }
2386 #else
2387 #if defined FSL_FEATURE_EDMA_HAS_CHANNEL_MUX && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
2388 #if defined FSL_FEATURE_EDMA_HAS_MP_CHANNEL_MUX && FSL_FEATURE_EDMA_HAS_MP_CHANNEL_MUX
2389     if (((uint32_t)FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_MUXn(handle->base) == 1U) &&
2390         (EDMA_MP_BASE(handle->base)->MP_REGS.EDMA5_REG.CH_MUX[handle->channel] == 0U) &&
2391         (FSL_FEATURE_EDMA_INSTANCE_HAS_MP_CHANNEL_MUXn(handle->base) == 1U))
2392     {
2393         EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_START_MASK;
2394     }
2395     else if (((uint32_t)FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_MUXn(handle->base) == 1U) &&
2396              handle->channelBase->CH_REGS.EDMA4_REG.CH_MUX == 0U &&
2397              !(FSL_FEATURE_EDMA_INSTANCE_HAS_MP_CHANNEL_MUXn(handle->base) == 1U))
2398     {
2399         EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_START_MASK;
2400     }
2401     else
2402 #else
2403     if (((uint32_t)FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_MUXn(handle->base) == 1U) &&
2404         handle->channelBase->CH_REGS.EDMA4_REG.CH_MUX == 0U)
2405     {
2406         EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) |= DMA_CSR_START_MASK;
2407     }
2408     else
2409 #endif
2410 #endif
2411         if (handle->tcdPool == NULL)
2412     {
2413         handle->channelBase->CH_CSR |= DMA_CH_CSR_ERQ_MASK;
2414     }
2415     else
2416     {
2417         /* Check if channel request is actually disable. */
2418         if ((handle->channelBase->CH_CSR & DMA_CH_CSR_ERQ_MASK) == 0U)
2419         {
2420             /* Check if transfer is paused. */
2421             if ((!((handle->channelBase->CH_CSR & DMA_CH_CSR_DONE_MASK) != 0U)) ||
2422                 ((EDMA_TCD_CSR(tcdRegs, EDMA_TCD_TYPE(handle->base)) & DMA_CSR_ESG_MASK) != 0U))
2423             {
2424                 /*
2425                     Re-enable channel request must be as soon as possible, so must put it into
2426                     critical section to avoid task switching or interrupt service routine.
2427                 */
2428                 handle->channelBase->CH_CSR |= DMA_CH_CSR_ERQ_MASK;
2429             }
2430         }
2431     }
2432 #endif
2433 }
2434 
2435 /*!
2436  * brief eDMA stops transfer.
2437  *
2438  * This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer()
2439  * again to resume the transfer.
2440  *
2441  * param handle eDMA handle pointer.
2442  */
EDMA_StopTransfer(edma_handle_t * handle)2443 void EDMA_StopTransfer(edma_handle_t *handle)
2444 {
2445     assert(handle != NULL);
2446 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2447     handle->base->CERQ = DMA_CERQ_CERQ(handle->channel);
2448 #else
2449     handle->channelBase->CH_CSR = handle->channelBase->CH_CSR & (~(DMA_CH_CSR_DONE_MASK | DMA_CH_CSR_ERQ_MASK));
2450 #endif
2451 }
2452 
2453 /*!
2454  * brief eDMA aborts transfer.
2455  *
2456  * This function disables the channel request and clear transfer status bits.
2457  * Users can submit another transfer after calling this API.
2458  *
2459  * param handle DMA handle pointer.
2460  */
EDMA_AbortTransfer(edma_handle_t * handle)2461 void EDMA_AbortTransfer(edma_handle_t *handle)
2462 {
2463     EDMA_StopTransfer(handle);
2464     /*
2465         Clear CSR to release channel. Because if the given channel started transfer,
2466         CSR will be not zero. Because if it is the last transfer, DREQ will be set.
2467         If not, ESG will be set.
2468     */
2469     EDMA_TcdResetExt(handle->base, handle->tcdBase);
2470 
2471     /* Handle the tcd */
2472     if (handle->tcdPool != NULL)
2473     {
2474         handle->header  = 1;
2475         handle->tail    = 0;
2476         handle->tcdUsed = 0;
2477     }
2478 }
2479 
2480 /*!
2481  * brief eDMA IRQ handler for the current major loop transfer completion.
2482  *
2483  * This function clears the channel major interrupt flag and calls
2484  * the callback function if it is not NULL.
2485  *
2486  * Note:
2487  * For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed.
2488  * These include the final address adjustments and reloading of the BITER field into the CITER.
2489  * Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from
2490  * memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled).
2491  *
2492  * For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine.
2493  * As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index
2494  * in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be
2495  * (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have
2496  * been loaded into the eDMA engine at this point already.).
2497  *
2498  * For the last two continuous ISRs in a scatter/gather process, they  both load the last TCD (The last ISR does not
2499  * load a new TCD) from the memory pool to the eDMA engine when major loop completes.
2500  * Therefore, ensure that the header and tcdUsed updated are identical for them.
2501  * tcdUsed are both 0 in this case as no TCD to be loaded.
2502  *
2503  * See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for
2504  * further details.
2505  *
2506  * param handle eDMA handle pointer.
2507  */
EDMA_HandleIRQ(edma_handle_t * handle)2508 void EDMA_HandleIRQ(edma_handle_t *handle)
2509 {
2510     assert(handle != NULL);
2511 
2512     bool transfer_done;
2513 
2514 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2515     /* Check if transfer is already finished. */
2516     transfer_done = ((handle->tcdBase->CSR & DMA_CSR_DONE_MASK) != 0U);
2517 #else
2518     transfer_done               = (bool)(handle->channelBase->CH_CSR & DMA_CH_CSR_DONE_MASK);
2519 #endif
2520 
2521 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2522     if ((handle->base->INT >> channel) != 0U)
2523     {
2524         handle->base->CINT = channel;
2525     }
2526 #else
2527     if ((handle->channelBase->CH_INT & DMA_CH_INT_INT_MASK) != 0U)
2528     {
2529         handle->channelBase->CH_INT |= DMA_CH_INT_INT_MASK;
2530     }
2531 #endif
2532 
2533     if (handle->tcdPool == NULL)
2534     {
2535         if (handle->callback != NULL)
2536         {
2537             (handle->callback)(handle, handle->userData, transfer_done, 0);
2538         }
2539     }
2540     else /* Use the TCD queue. Please refer to the API descriptions in the eDMA header file for detailed information. */
2541     {
2542         uint32_t sga = (uint32_t)EDMA_TCD_DLAST_SGA(handle->tcdBase, EDMA_TCD_TYPE(handle->base));
2543         uint32_t sga_index;
2544         int32_t tcds_done;
2545         uint8_t new_header;
2546         bool esg = ((EDMA_TCD_CSR(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) & DMA_CSR_ESG_MASK) != 0U);
2547 
2548         /* Get the offset of the next transfer TCD blocks to be loaded into the eDMA engine. */
2549         sga -= CONVERT_TO_DMA_ADDRESS((uint32_t)handle->tcdPool);
2550         /* Get the index of the next transfer TCD blocks to be loaded into the eDMA engine. */
2551         sga_index = sga / sizeof(edma_tcd_t);
2552         /* Adjust header positions. */
2553         if (transfer_done)
2554         {
2555             /* New header shall point to the next TCD to be loaded (current one is already finished) */
2556             new_header = (uint8_t)sga_index;
2557         }
2558         else
2559         {
2560             /* New header shall point to this descriptor currently loaded (not finished yet) */
2561             new_header = sga_index != 0U ? (uint8_t)sga_index - 1U : (uint8_t)handle->tcdSize - 1U;
2562         }
2563         /* Calculate the number of finished TCDs */
2564         if (new_header == (uint8_t)handle->header)
2565         {
2566             int8_t tmpTcdUsed = handle->tcdUsed;
2567             int8_t tmpTcdSize = handle->tcdSize;
2568 
2569             /* check esg here for the case that application submit only one request, once the request complete:
2570              * new_header(1) = handle->header(1)
2571              * tcdUsed(1) != tcdSize(>1)
2572              * As the application submit only once, so scatter gather must not enabled, then tcds_done should be 1
2573              */
2574             if ((tmpTcdUsed == tmpTcdSize) || (!esg))
2575             {
2576                 tcds_done = handle->tcdUsed;
2577             }
2578             else
2579             {
2580                 /* No TCD in the memory are going to be loaded or internal error occurs. */
2581                 tcds_done = 0;
2582             }
2583         }
2584         else
2585         {
2586             tcds_done = (int32_t)new_header - (int32_t)handle->header;
2587             if (tcds_done < 0)
2588             {
2589                 tcds_done += handle->tcdSize;
2590             }
2591             /*
2592              * While code run to here, it means a TCD transfer Done and a new TCD has loaded to the hardware
2593              * so clear DONE here to allow submit scatter gather transfer request in the callback to avoid TCD
2594              * overwritten.
2595              */
2596             if (transfer_done)
2597             {
2598 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2599                 handle->base->CDNE = handle->channel;
2600 #else
2601                 handle->channelBase->CH_CSR |= DMA_CH_CSR_DONE_MASK;
2602 #endif
2603             }
2604         }
2605         /* Advance header which points to the TCD to be loaded into the eDMA engine from memory. */
2606         handle->header = (int8_t)new_header;
2607         /* Release TCD blocks. tcdUsed is the TCD number which can be used/loaded in the memory pool. */
2608         handle->tcdUsed -= (int8_t)tcds_done;
2609         /* Invoke callback function. */
2610         if (NULL != handle->callback)
2611         {
2612             (handle->callback)(handle, handle->userData, transfer_done, tcds_done);
2613         }
2614 
2615         /*
2616          * 1.clear the DONE bit here is meaningful for below cases:
2617          * A new TCD has been loaded to EDMA already:
2618          * need to clear the DONE bit in the IRQ handler to avoid TCD in EDMA been overwritten
2619          * if peripheral request isn't coming before next transfer request.
2620          * 2. Don't clear DONE bit for below case,
2621          * for the case that transfer request submitted in the privious edma callback, this is a case that doesn't
2622          * need scatter gather, so keep DONE bit during the next transfer request submission will re-install the TCD and
2623          * the DONE bit will be cleared together with TCD re-installation.
2624          */
2625         if (transfer_done)
2626         {
2627             if ((EDMA_TCD_CSR(handle->tcdBase, EDMA_TCD_TYPE(handle->base)) & DMA_CSR_ESG_MASK) != 0U)
2628             {
2629 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2630                 handle->base->CDNE = handle->channel;
2631 #else
2632                 handle->channelBase->CH_CSR |= DMA_CH_CSR_DONE_MASK;
2633 #endif
2634             }
2635         }
2636     }
2637 }
2638 
2639 void EDMA_DriverIRQHandler(uint32_t instance, uint32_t channel);
EDMA_DriverIRQHandler(uint32_t instance,uint32_t channel)2640 void EDMA_DriverIRQHandler(uint32_t instance, uint32_t channel)
2641 {
2642 #if defined FSL_EDMA_SOC_IP_EDMA && FSL_EDMA_SOC_IP_EDMA
2643     if ((s_edmaBases[instance]->INT >> channel) != 0U)
2644     {
2645         EDMA_HandleIRQ(s_EDMAHandle[instance][channel]);
2646     }
2647 #else
2648     if ((EDMA_CHANNEL_BASE(s_edmaBases[instance], channel)->CH_INT & DMA_CH_INT_INT_MASK) != 0U)
2649     {
2650         EDMA_HandleIRQ(s_EDMAHandle[instance][channel]);
2651     }
2652 #endif
2653     SDK_ISR_EXIT_BARRIER;
2654 }
2655