1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_edma.h"
10 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
11 #include "fsl_memory.h"
12 #endif
13 /*******************************************************************************
14  * Definitions
15  ******************************************************************************/
16 
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.dma3"
20 #endif
21 
22 #define EDMA_TRANSFER_ENABLED_MASK 0x80U
23 
24 /*******************************************************************************
25  * Prototypes
26  ******************************************************************************/
27 
28 /*!
29  * @brief Get instance number for EDMA.
30  *
31  * @param base EDMA peripheral base address.
32  */
33 static uint32_t EDMA_GetInstance(DMA_Type *base);
34 
35 /*!
36  * @brief Configure tcd contents accroding to the configure.
37  *
38  * @param handle edma handle pointer.
39  * @param channel EDMA channel number.
40  * @param config EDMA configure pointer.
41  * @param nextTcd Point to next TCD structure if there is.
42  */
43 static void EDMA_HandleTransferConfig(edma_handle_t *handle,
44                                       uint32_t channel,
45                                       const edma_transfer_config_t *config,
46                                       edma_tcd_t *nextTcd);
47 
48 /*******************************************************************************
49  * Variables
50  ******************************************************************************/
51 
52 /*! @brief Array to map EDMA instance number to base pointer. */
53 static DMA_Type *const s_edmaBases[] = DMA_BASE_PTRS;
54 
55 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
56 #if !(defined(FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE) && (FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE))
57 /*! @brief Array to map EDMA instance number to clock name. */
58 static const clock_ip_name_t s_edmaClockName[] = EDMA_CLOCKS;
59 #endif /* FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE */
60 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
61 
62 static const IRQn_Type s_edmaIRQNumber[][FSL_FEATURE_EDMA_MODULE_CHANNEL] = DMA_IRQS;
63 
64 /*! @brief Pointers to transfer handle for each EDMA channel. */
65 static edma_handle_t *s_EDMAHandle[FSL_FEATURE_EDMA_MODULE_CHANNEL * FSL_FEATURE_SOC_EDMA_COUNT];
66 
67 /*! @brief EDMA enabled channel. */
68 static bool s_EDMAEnabledChannel[FSL_FEATURE_SOC_EDMA_COUNT][FSL_FEATURE_EDMA_MODULE_CHANNEL];
69 /*******************************************************************************
70  * Code
71  ******************************************************************************/
72 
EDMA_GetInstance(DMA_Type * base)73 static uint32_t EDMA_GetInstance(DMA_Type *base)
74 {
75     uint32_t instance;
76 
77     /* Find the instance index from base address mappings. */
78     for (instance = 0; instance < ARRAY_SIZE(s_edmaBases); instance++)
79     {
80         if (s_edmaBases[instance] == base)
81         {
82             break;
83         }
84     }
85 
86     assert(instance < ARRAY_SIZE(s_edmaBases));
87 
88     return instance;
89 }
90 
EDMA_InstallTCD(DMA_Type * base,uint32_t channel,edma_tcd_t * tcd)91 void EDMA_InstallTCD(DMA_Type *base, uint32_t channel, edma_tcd_t *tcd)
92 {
93     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
94     assert(tcd != NULL);
95     assert(((uint32_t)tcd & 0x1FU) == 0U);
96 
97     /* Push tcd into hardware TCD register */
98     base->CH[channel].TCD_SADDR          = tcd->SADDR;
99     base->CH[channel].TCD_SOFF           = tcd->SOFF;
100     base->CH[channel].TCD_ATTR           = tcd->ATTR;
101     base->CH[channel].TCD_NBYTES_MLOFFNO = tcd->NBYTES;
102     base->CH[channel].TCD_SLAST_SDA      = tcd->SLAST;
103     base->CH[channel].TCD_DADDR          = tcd->DADDR;
104     base->CH[channel].TCD_DOFF           = tcd->DOFF;
105     base->CH[channel].TCD_CITER_ELINKNO  = tcd->CITER;
106     base->CH[channel].TCD_DLAST_SGA      = tcd->DLAST_SGA;
107     /* Clear DONE bit first, otherwise ESG cannot be set */
108     base->CH[channel].TCD_CSR           = 0;
109     base->CH[channel].TCD_CSR           = tcd->CSR;
110     base->CH[channel].TCD_BITER_ELINKNO = tcd->BITER;
111 }
112 
EDMA_HandleTransferConfig(edma_handle_t * handle,uint32_t channel,const edma_transfer_config_t * config,edma_tcd_t * nextTcd)113 static void EDMA_HandleTransferConfig(edma_handle_t *handle,
114                                       uint32_t channel,
115                                       const edma_transfer_config_t *config,
116                                       edma_tcd_t *nextTcd)
117 {
118     assert((handle != NULL) && (config != NULL));
119 
120 /* If there is address offset, convert the address */
121 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
122     nextTcd = (edma_tcd_t *)(MEMORY_ConvertMemoryMapAddress((uint32_t)nextTcd, kMEMORY_Local2DMA));
123 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
124     EDMA_SetTransferConfig(handle->base, channel, config, nextTcd);
125 }
126 
127 /*!
128  * brief Initializes the eDMA peripheral.
129  *
130  * This function ungates the eDMA clock and configures the eDMA peripheral
131  * according
132  * to the configuration structure.
133  *
134  * param base eDMA peripheral base address.
135  * param config A pointer to the configuration structure, see "edma_config_t".
136  * note This function enables the minor loop map feature.
137  */
EDMA_Init(DMA_Type * base,const edma_config_t * config)138 void EDMA_Init(DMA_Type *base, const edma_config_t *config)
139 {
140     assert(config != NULL);
141 
142 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
143 #if !(defined(FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE) && (FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE))
144     CLOCK_EnableClock(s_edmaClockName[EDMA_GetInstance(base)]);
145 #endif /* FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE */
146 #endif /* FSL_FEATURE_EDMA_HAS_CLOCK_GATE */
147 
148 #if defined(FSL_FEATURE_HAVE_DMA_CONTROL_REGISTER_ACCESS_PERMISSION) && \
149     FSL_FEATURE_HAVE_DMA_CONTROL_REGISTER_ACCESS_PERMISSION
150     uint32_t tmpreg;
151     /* Configure EDMA peripheral according to the configuration structure. */
152     tmpreg = base->MP_CSR;
153     tmpreg &= ~(DMA_MP_CSR_HAE_MASK | DMA_MP_CSR_ERCA_MASK | DMA_MP_CSR_EDBG_MASK);
154 
155     tmpreg = (tmpreg & (~DMA_MP_CSR_GMRC_MASK)) | DMA_MP_CSR_GMRC(config->enableMasterIdReplication);
156 
157 #if !(defined FSL_FEATURE_EDMA_HAS_NO_MP_CSR_EBW && FSL_FEATURE_EDMA_HAS_NO_MP_CSR_EBW)
158     tmpreg = (tmpreg & (~DMA_MP_CSR_EBW_MASK)) | DMA_MP_CSR_EBW(config->enableBufferedWrites);
159 #endif
160 
161     tmpreg |= (DMA_MP_CSR_HAE(config->enableHaltOnError) | DMA_MP_CSR_ERCA(config->enableRoundRobinArbitration) |
162                DMA_MP_CSR_EDBG(config->enableDebugMode));
163 
164     base->MP_CSR = tmpreg;
165     base->MP_CSR &= (~DMA_MP_CSR_HALT_MASK);
166 #endif /* FSL_FETURE_HAVE_DMA_CONTROL_REGISTER_ACCESS_PERMISSION */
167 }
168 
169 /*!
170  * brief Deinitializes the eDMA peripheral.
171  *
172  * This function gates the eDMA clock.
173  *
174  * param base eDMA peripheral base address.
175  */
EDMA_Deinit(DMA_Type * base)176 void EDMA_Deinit(DMA_Type *base)
177 {
178 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
179 #if !(defined(FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE) && (FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE))
180     /* Gate EDMA periphral clock */
181     CLOCK_DisableClock(s_edmaClockName[EDMA_GetInstance(base)]);
182 #endif /* FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE */
183 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
184     /* reset all the enabled channel status */
185     (void)memset(s_EDMAEnabledChannel, 0, sizeof(s_EDMAEnabledChannel));
186 }
187 
188 /*!
189  * brief Gets the eDMA default configuration structure.
190  *
191  * This function sets the configuration structure to default values.
192  * The default configuration is set to the following values:
193  * code
194  *   config.enableMasterIdReplication = true;
195  *   config.enableHaltOnError = true;
196  *   config.enableRoundRobinArbitration = false;
197  *   config.enableDebugMode = false;
198  *   config.enableBufferedWrites = false;
199  * endcode
200  *
201  * param config A pointer to the eDMA configuration structure.
202  */
EDMA_GetDefaultConfig(edma_config_t * config)203 void EDMA_GetDefaultConfig(edma_config_t *config)
204 {
205     assert(config != NULL);
206 
207     /* Initializes the configure structure to zero. */
208     (void)memset(config, 0, sizeof(*config));
209 
210     config->enableMasterIdReplication = true;
211 
212     config->enableHaltOnError           = true;
213     config->enableRoundRobinArbitration = false;
214     config->enableDebugMode             = false;
215 
216 #if !(defined FSL_FEATURE_EDMA_HAS_NO_MP_CSR_EBW && FSL_FEATURE_EDMA_HAS_NO_MP_CSR_EBW)
217     config->enableBufferedWrites = false;
218 #endif
219 }
220 
221 /*!
222  * brief Sets all TCD registers to default values.
223  *
224  * This function sets TCD registers for this channel to default values.
225  *
226  * param base eDMA peripheral base address.
227  * param channel eDMA channel number.
228  * note This function must not be called while the channel transfer is ongoing
229  *       or it causes unpredictable results.
230  * note This function enables the auto stop request feature.
231  */
EDMA_ResetChannel(DMA_Type * base,uint32_t channel)232 void EDMA_ResetChannel(DMA_Type *base, uint32_t channel)
233 {
234     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
235 
236     /* Clear DONE bit and ERR bit */
237     base->CH[channel].CH_ES |= DMA_CH_ES_ERR_MASK;
238     base->CH[channel].CH_CSR |= DMA_CH_CSR_DONE_MASK;
239 
240     /* Reset channel TCD */
241     base->CH[channel].TCD_SADDR          = 0U;
242     base->CH[channel].TCD_SOFF           = 0U;
243     base->CH[channel].TCD_ATTR           = 0U;
244     base->CH[channel].TCD_NBYTES_MLOFFNO = 0U;
245     base->CH[channel].TCD_SLAST_SDA      = 0U;
246     base->CH[channel].TCD_DADDR          = 0U;
247     base->CH[channel].TCD_DOFF           = 0U;
248     base->CH[channel].TCD_CITER_ELINKNO  = 0U;
249     base->CH[channel].TCD_DLAST_SGA      = 0U;
250     base->CH[channel].TCD_CSR            = 0U;
251     base->CH[channel].TCD_BITER_ELINKNO  = 0U;
252 }
253 
254 /*!
255  * brief Configures the eDMA transfer attribute.
256  *
257  * This function configures the transfer attribute, including source address,
258  * destination address,
259  * transfer size, address offset, and so on. It also configures the scatter
260  * gather feature if the
261  * user supplies the TCD address.
262  * Example:
263  * code
264  *  edma_transfer_config_t config;
265  *  edma_tcd_t tcd;
266  *  config.srcAddr = ..;
267  *  config.destAddr = ..;
268  *  ...
269  *  EDMA_SetTransferConfig(DMA0, channel, &config, &stcd);
270  * endcode
271  *
272  * param base eDMA peripheral base address.
273  * param channel eDMA channel number.
274  * param config Pointer to eDMA transfer configuration structure.
275  * param nextTcd Point to TCD structure. It can be NULL if users
276  *                do not want to enable scatter/gather feature.
277  * note If nextTcd is not NULL, it means scatter gather feature is enabled
278  *       and DREQ bit is cleared in the previous transfer configuration, which
279  *       is set in the eDMA_ResetChannel.
280  */
EDMA_SetTransferConfig(DMA_Type * base,uint32_t channel,const edma_transfer_config_t * config,edma_tcd_t * nextTcd)281 void EDMA_SetTransferConfig(DMA_Type *base, uint32_t channel, const edma_transfer_config_t *config, edma_tcd_t *nextTcd)
282 {
283     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
284     assert(config != NULL);
285     assert(((uint32_t)nextTcd & 0x1FU) == 0U);
286 
287     EDMA_TcdSetTransferConfig((edma_tcd_t *)((uint32_t)&base->CH[channel] + 0x00000020U), config, nextTcd);
288 }
289 
290 /*!
291  * brief Configures the eDMA minor offset feature.
292  *
293  * The minor offset means that the signed-extended value is added to the source
294  * address or destination
295  * address after each minor loop.
296  *
297  * param base eDMA peripheral base address.
298  * param channel eDMA channel number.
299  * param config A pointer to the minor offset configuration structure.
300  */
EDMA_SetMinorOffsetConfig(DMA_Type * base,uint32_t channel,const edma_minor_offset_config_t * config)301 void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config)
302 {
303     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
304     assert(config != NULL);
305 
306     EDMA_TcdSetMinorOffsetConfig((edma_tcd_t *)((uint32_t)&base->CH[channel] + 0x00000020U), config);
307 }
308 
309 /*!
310  * brief Sets the channel link for the eDMA transfer.
311  *
312  * This function configures either the minor link or the major link mode. The
313  * minor link means that the channel link is
314  * triggered every time CITER decreases by 1. The major link means that the
315  * channel link is triggered when the CITER is
316  * exhausted.
317  *
318  * param base eDMA peripheral base address.
319  * param channel eDMA channel number.
320  * param type A channel link type, which can be one of the following:
321  *   arg kEDMA_LinkNone
322  *   arg kEDMA_MinorLink
323  *   arg kEDMA_MajorLink
324  * param linkedChannel The linked channel number.
325  * note Users should ensure that DONE flag is cleared before calling this
326  * interface, or the configuration is invalid.
327  */
EDMA_SetChannelLink(DMA_Type * base,uint32_t channel,edma_channel_link_type_t type,uint32_t linkedChannel)328 void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel)
329 {
330     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
331     assert(linkedChannel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
332 
333     EDMA_TcdSetChannelLink((edma_tcd_t *)((uint32_t)&base->CH[channel] + 0x00000020U), type, linkedChannel);
334 }
335 
336 /*!
337  * brief Sets the bandwidth for the eDMA transfer.
338  *
339  * Because the eDMA processes the minor loop, it continuously generates
340  * read/write sequences
341  * until the minor count is exhausted. The bandwidth forces the eDMA to stall
342  * after the completion of
343  * each read/write access to control the bus request bandwidth seen by the
344  * crossbar switch.
345  *
346  * param base eDMA peripheral base address.
347  * param channel eDMA channel number.
348  * param bandWidth A bandwidth setting, which can be one of the following:
349  *     arg kEDMABandwidthStallNone
350  *     arg kEDMABandwidthStall4Cycle
351  *     arg kEDMABandwidthStall8Cycle
352  */
EDMA_SetBandWidth(DMA_Type * base,uint32_t channel,edma_bandwidth_t bandWidth)353 void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth)
354 {
355     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
356 
357     base->CH[channel].TCD_CSR =
358         (uint16_t)((base->CH[channel].TCD_CSR & (~DMA_TCD_CSR_BWC_MASK)) | DMA_TCD_CSR_BWC(bandWidth));
359 }
360 
361 /*!
362  * brief Sets the source modulo and the destination modulo for the eDMA
363  * transfer.
364  *
365  * This function defines a specific address range specified to be the value
366  * after (SADDR + SOFF)/(DADDR + DOFF)
367  * calculation is performed or the original register value. It provides the
368  * ability to implement a circular data
369  * queue easily.
370  *
371  * param base eDMA peripheral base address.
372  * param channel eDMA channel number.
373  * param srcModulo A source modulo value.
374  * param destModulo A destination modulo value.
375  */
EDMA_SetModulo(DMA_Type * base,uint32_t channel,edma_modulo_t srcModulo,edma_modulo_t destModulo)376 void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo)
377 {
378     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
379 
380     EDMA_TcdSetModulo((edma_tcd_t *)((uint32_t)&base->CH[channel] + 0x00000020U), srcModulo, destModulo);
381 }
382 
383 /*!
384  * brief Enables the interrupt source for the eDMA transfer.
385  *
386  * param base eDMA peripheral base address.
387  * param channel eDMA channel number.
388  * param mask The mask of interrupt source to be set. Users need to use
389  *             the defined edma_interrupt_enable_t type.
390  */
EDMA_EnableChannelInterrupts(DMA_Type * base,uint32_t channel,uint32_t mask)391 void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask)
392 {
393     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
394 
395     /* Enable error interrupt */
396     if ((mask & (uint32_t)kEDMA_ErrorInterruptEnable) != 0U)
397     {
398         base->CH[channel].CH_CSR = (base->CH[channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) | DMA_CH_CSR_EEI_MASK;
399     }
400 
401     /* Enable Major interrupt or Half major interrupt */
402     else
403     {
404         EDMA_TcdEnableInterrupts((edma_tcd_t *)((uint32_t)&base->CH[channel] + 0x00000020U), mask);
405     }
406 }
407 
408 /*!
409  * brief Disables the interrupt source for the eDMA transfer.
410  *
411  * param base eDMA peripheral base address.
412  * param channel eDMA channel number.
413  * param mask The mask of the interrupt source to be set. Use
414  *             the defined edma_interrupt_enable_t type.
415  */
EDMA_DisableChannelInterrupts(DMA_Type * base,uint32_t channel,uint32_t mask)416 void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask)
417 {
418     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
419 
420     /* Disable error interrupt */
421     if ((mask & (uint32_t)kEDMA_ErrorInterruptEnable) != 0U)
422     {
423         base->CH[channel].CH_CSR = (base->CH[channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) & ~DMA_CH_CSR_EEI_MASK;
424     }
425 
426     /* Disable Major interrupt or Half major interrupt */
427     else
428     {
429         EDMA_TcdDisableInterrupts((edma_tcd_t *)((uint32_t)&base->CH[channel] + 0x00000020U), mask);
430     }
431 }
432 
433 /*!
434  * brief Sets all fields to default values for the TCD structure.
435  *
436  * This function sets all fields for this TCD structure to default value.
437  *
438  * param tcd Pointer to the TCD structure.
439  * note This function enables the auto stop request feature.
440  */
EDMA_TcdReset(edma_tcd_t * tcd)441 void EDMA_TcdReset(edma_tcd_t *tcd)
442 {
443     assert(tcd != NULL);
444     assert(((uint32_t)tcd & 0x1FU) == 0U);
445 
446     /* Reset channel TCD */
447     tcd->SADDR     = 0U;
448     tcd->SOFF      = 0U;
449     tcd->ATTR      = 0U;
450     tcd->NBYTES    = 0U;
451     tcd->SLAST     = 0U;
452     tcd->DADDR     = 0U;
453     tcd->DOFF      = 0U;
454     tcd->CITER     = 0U;
455     tcd->DLAST_SGA = 0U;
456     /* Enable auto disable request feature */
457     tcd->CSR   = DMA_TCD_CSR_DREQ(true);
458     tcd->BITER = 0U;
459 }
460 
461 /*!
462  * brief Configures the eDMA TCD transfer attribute.
463  *
464  * The TCD is a transfer control descriptor. The content of the TCD is the same
465  * as the hardware TCD registers.
466  * The STCD is used in the scatter-gather mode.
467  * This function configures the TCD transfer attribute, including source
468  * address, destination address,
469  * transfer size, address offset, and so on. It also configures the scatter
470  * gather feature if the
471  * user supplies the next TCD address.
472  * Example:
473  * code
474  *   edma_transfer_config_t config = {
475  *   ...
476  *   }
477  *   edma_tcd_t tcd __aligned(32);
478  *   edma_tcd_t nextTcd __aligned(32);
479  *   EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
480  * endcode
481  *
482  * param tcd Pointer to the TCD structure.
483  * param config Pointer to eDMA transfer configuration structure.
484  * param nextTcd Pointer to the next TCD structure. It can be NULL if users
485  *                do not want to enable scatter/gather feature.
486  * note TCD address should be 32 bytes aligned or it causes an eDMA error.
487  * note If the nextTcd is not NULL, the scatter gather feature is enabled
488  *       and DREQ bit is cleared in the previous transfer configuration, which
489  *       is set in the EDMA_TcdReset.
490  */
EDMA_TcdSetTransferConfig(edma_tcd_t * tcd,const edma_transfer_config_t * config,edma_tcd_t * nextTcd)491 void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd)
492 {
493     assert(tcd != NULL);
494     assert(((uint32_t)tcd & 0x1FU) == 0U);
495     assert(config != NULL);
496     assert(((uint32_t)nextTcd & 0x1FU) == 0U);
497     assert((config->srcAddr % (1UL << (uint32_t)config->srcTransferSize)) == 0U);
498     assert((config->destAddr % (1UL << (uint32_t)config->destTransferSize)) == 0U);
499 
500 /* source address */
501 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
502     tcd->SADDR = MEMORY_ConvertMemoryMapAddress(config->srcAddr, kMEMORY_Local2DMA);
503     /* destination address */
504     tcd->DADDR = MEMORY_ConvertMemoryMapAddress(config->destAddr, kMEMORY_Local2DMA);
505 #else
506     tcd->SADDR = config->srcAddr;
507     /* destination address */
508     tcd->DADDR = config->destAddr;
509 #endif
510     /* Source data and destination data transfer size */
511     tcd->ATTR = DMA_TCD_ATTR_SSIZE(config->srcTransferSize) | DMA_TCD_ATTR_DSIZE(config->destTransferSize);
512     /* Source address signed offset */
513     tcd->SOFF = (uint16_t)config->srcOffset;
514     /* Destination address signed offset */
515     tcd->DOFF = (uint16_t)config->destOffset;
516     /* Minor byte transfer count */
517     tcd->NBYTES = config->minorLoopBytes;
518     /* Current major iteration count */
519     tcd->CITER = (uint16_t)config->majorLoopCounts;
520     /* Starting major iteration count */
521     tcd->BITER = (uint16_t)config->majorLoopCounts;
522     /* Enable scatter/gather processing */
523     if (nextTcd != NULL)
524     {
525 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
526         tcd->DLAST_SGA = MEMORY_ConvertMemoryMapAddress((uint32_t)nextTcd, kMEMORY_Local2DMA);
527 #else
528         tcd->DLAST_SGA = (uint32_t)nextTcd;
529 #endif
530         /*
531             Before call EDMA_TcdSetTransferConfig or EDMA_SetTransferConfig,
532             user must call EDMA_TcdReset or EDMA_ResetChannel which will set
533             DREQ, so must use "|" or "&" rather than "=".
534 
535             Clear the DREQ bit because scatter gather has been enabled, so the
536             previous transfer is not the last transfer, and channel request should
537             be enabled at the next transfer(the next TCD).
538         */
539         tcd->CSR = (tcd->CSR | (uint16_t)DMA_TCD_CSR_ESG_MASK) & ~(uint16_t)DMA_TCD_CSR_DREQ_MASK;
540     }
541 }
542 
543 /*!
544  * brief Configures the eDMA TCD minor offset feature.
545  *
546  * A minor offset is a signed-extended value added to the source address or a
547  * destination
548  * address after each minor loop.
549  *
550  * param tcd A point to the TCD structure.
551  * param config A pointer to the minor offset configuration structure.
552  */
EDMA_TcdSetMinorOffsetConfig(edma_tcd_t * tcd,const edma_minor_offset_config_t * config)553 void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config)
554 {
555     assert(tcd != NULL);
556     assert(((uint32_t)tcd & 0x1FU) == 0U);
557 
558     uint32_t tmpreg;
559 
560     tmpreg = tcd->NBYTES;
561     tmpreg &=
562         ~(DMA_TCD_NBYTES_MLOFFYES_SMLOE_MASK | DMA_TCD_NBYTES_MLOFFYES_DMLOE_MASK | DMA_TCD_NBYTES_MLOFFYES_MLOFF_MASK);
563     tmpreg |= (DMA_TCD_NBYTES_MLOFFYES_SMLOE(config->enableSrcMinorOffset) |
564                DMA_TCD_NBYTES_MLOFFYES_DMLOE(config->enableDestMinorOffset) |
565                DMA_TCD_NBYTES_MLOFFYES_MLOFF(config->minorOffset));
566     tcd->NBYTES = tmpreg;
567 }
568 
569 /*!
570  * brief Sets the channel link for the eDMA TCD.
571  *
572  * This function configures either a minor link or a major link. The minor link
573  * means the channel link is
574  * triggered every time CITER decreases by 1. The major link means that the
575  * channel link  is triggered when the CITER is
576  * exhausted.
577  *
578  * note Users should ensure that DONE flag is cleared before calling this
579  * interface, or the configuration is invalid.
580  * param tcd Point to the TCD structure.
581  * param type Channel link type, it can be one of:
582  *   arg kEDMA_LinkNone
583  *   arg kEDMA_MinorLink
584  *   arg kEDMA_MajorLink
585  * param linkedChannel The linked channel number.
586  */
EDMA_TcdSetChannelLink(edma_tcd_t * tcd,edma_channel_link_type_t type,uint32_t linkedChannel)587 void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel)
588 {
589     assert(tcd != NULL);
590     assert(((uint32_t)tcd & 0x1FU) == 0U);
591     assert(linkedChannel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
592 
593     if (type == kEDMA_MinorLink) /* Minor link config */
594     {
595         uint16_t tmpreg;
596 
597         /* Enable minor link */
598         tcd->CITER |= DMA_TCD_CITER_ELINKYES_ELINK_MASK;
599         tcd->BITER |= DMA_TCD_BITER_ELINKYES_ELINK_MASK;
600         /* Set likned channel */
601         tmpreg = tcd->CITER & (~(uint16_t)DMA_TCD_CITER_ELINKYES_LINKCH_MASK);
602         tmpreg |= DMA_TCD_CITER_ELINKYES_LINKCH(linkedChannel);
603         tcd->CITER = tmpreg;
604         tmpreg     = tcd->BITER & (~(uint16_t)DMA_TCD_BITER_ELINKYES_LINKCH_MASK);
605         tmpreg |= DMA_TCD_BITER_ELINKYES_LINKCH(linkedChannel);
606         tcd->BITER = tmpreg;
607     }
608     else if (type == kEDMA_MajorLink) /* Major link config */
609     {
610         uint16_t tmpreg;
611 
612         /* Enable major link */
613         tcd->CSR |= DMA_TCD_CSR_MAJORELINK_MASK;
614         /* Set major linked channel */
615         tmpreg   = tcd->CSR & (~(uint16_t)DMA_TCD_CSR_MAJORLINKCH_MASK);
616         tcd->CSR = tmpreg | DMA_TCD_CSR_MAJORLINKCH(linkedChannel);
617     }
618     else /* Link none */
619     {
620         tcd->CITER &= ~(uint16_t)DMA_TCD_CITER_ELINKYES_ELINK_MASK;
621         tcd->BITER &= ~(uint16_t)DMA_TCD_BITER_ELINKYES_ELINK_MASK;
622         tcd->CSR &= ~(uint16_t)DMA_TCD_CSR_MAJORELINK_MASK;
623     }
624 }
625 
626 /*!
627  * brief Sets the source modulo and the destination modulo for the eDMA TCD.
628  *
629  * This function defines a specific address range specified to be the value
630  * after (SADDR + SOFF)/(DADDR + DOFF)
631  * calculation is performed or the original register value. It provides the
632  * ability to implement a circular data
633  * queue easily.
634  *
635  * param tcd A pointer to the TCD structure.
636  * param srcModulo A source modulo value.
637  * param destModulo A destination modulo value.
638  */
EDMA_TcdSetModulo(edma_tcd_t * tcd,edma_modulo_t srcModulo,edma_modulo_t destModulo)639 void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo)
640 {
641     assert(tcd != NULL);
642     assert(((uint32_t)tcd & 0x1FU) == 0U);
643 
644     uint16_t tmpreg;
645 
646     tmpreg    = tcd->ATTR & (~(uint16_t)(DMA_TCD_ATTR_SMOD_MASK | DMA_TCD_ATTR_DMOD_MASK));
647     tcd->ATTR = tmpreg | DMA_TCD_ATTR_DMOD(destModulo) | DMA_TCD_ATTR_SMOD(srcModulo);
648 }
649 
650 /*!
651  * brief Enables the interrupt source for the eDMA TCD.
652  *
653  * param tcd Point to the TCD structure.
654  * param mask The mask of interrupt source to be set. Users need to use
655  *             the defined edma_interrupt_enable_t type.
656  */
EDMA_TcdEnableInterrupts(edma_tcd_t * tcd,uint32_t mask)657 void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask)
658 {
659     assert(tcd != NULL);
660 
661     /* Enable Major interrupt */
662     if ((mask & (uint32_t)kEDMA_MajorInterruptEnable) != 0U)
663     {
664         tcd->CSR |= DMA_TCD_CSR_INTMAJOR_MASK;
665     }
666 
667     /* Enable Half major interrupt */
668     if ((mask & (uint32_t)kEDMA_HalfInterruptEnable) != 0U)
669     {
670         tcd->CSR |= DMA_TCD_CSR_INTHALF_MASK;
671     }
672 }
673 
674 /*!
675  * brief Disables the interrupt source for the eDMA TCD.
676  *
677  * param tcd Point to the TCD structure.
678  * param mask The mask of interrupt source to be set. Users need to use
679  *             the defined edma_interrupt_enable_t type.
680  */
EDMA_TcdDisableInterrupts(edma_tcd_t * tcd,uint32_t mask)681 void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask)
682 {
683     assert(tcd != NULL);
684 
685     /* Disable Major interrupt */
686     if ((mask & (uint32_t)kEDMA_MajorInterruptEnable) != 0U)
687     {
688         tcd->CSR &= ~(uint16_t)DMA_TCD_CSR_INTMAJOR_MASK;
689     }
690 
691     /* Disable Half major interrupt */
692     if ((mask & (uint32_t)kEDMA_HalfInterruptEnable) != 0U)
693     {
694         tcd->CSR &= ~(uint16_t)DMA_TCD_CSR_INTHALF_MASK;
695     }
696 }
697 
698 /*!
699  * brief Gets the Remaining major loop count from the eDMA current channel TCD.
700  *
701  * This function checks the TCD (Task Control Descriptor) status for a specified
702  * eDMA channel and returns the number of major loop count that has not
703  * finished.
704  *
705  * param base eDMA peripheral base address.
706  * param channel eDMA channel number.
707  * return Major loop count which has not been transferred yet for the current
708  * TCD.
709  * note 1. This function can only be used to get unfinished major loop count of
710  * transfer without
711  *          the next TCD, or it might be inaccuracy.
712  *       2. The unfinished/remaining transfer bytes cannot be obtained directly
713  * from registers while
714  *          the channel is running.
715  *          Because to calculate the remaining bytes, the initial NBYTES
716  * configured in DMA_TCDn_NBYTES_MLNO
717  *          register is needed while the eDMA IP does not support getting it
718  * while a channel is active.
719  *          In another word, the NBYTES value reading is always the actual
720  * (decrementing) NBYTES value the dma_engine
721  *          is working with while a channel is running.
722  *          Consequently, to get the remaining transfer bytes, a software-saved
723  * initial value of NBYTES (for example
724  *          copied before enabling the channel) is needed. The formula to
725  * calculate it is shown below:
726  *          RemainingBytes = RemainingMajorLoopCount * NBYTES(initially
727  * configured)
728  */
EDMA_GetRemainingMajorLoopCount(DMA_Type * base,uint32_t channel)729 uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel)
730 {
731     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
732 
733     uint32_t remainingCount = 0;
734 
735     if ((DMA_CH_CSR_DONE_MASK & base->CH[channel].CH_CSR) != 0U)
736     {
737         remainingCount = 0;
738     }
739     else
740     {
741         /* Calculate the unfinished bytes */
742         if ((base->CH[channel].TCD_CITER_ELINKNO & DMA_TCD_CITER_ELINKNO_ELINK_MASK) != 0U)
743         {
744             remainingCount = ((uint32_t)(base->CH[channel].TCD_CITER_ELINKNO) & DMA_TCD_CITER_ELINKYES_CITER_MASK) >>
745                              DMA_TCD_CITER_ELINKYES_CITER_SHIFT;
746         }
747         else
748         {
749             remainingCount = ((uint32_t)(base->CH[channel].TCD_CITER_ELINKNO) & DMA_TCD_CITER_ELINKNO_CITER_MASK) >>
750                              DMA_TCD_CITER_ELINKNO_CITER_SHIFT;
751         }
752     }
753 
754     return remainingCount;
755 }
756 
757 /*!
758  * brief Gets the eDMA channel status flags.
759  *
760  * param base eDMA peripheral base address.
761  * param channel eDMA channel number.
762  * return The mask of channel status flags. Users need to use the
763  *         _edma_channel_status_flags type to decode the return variables.
764  */
EDMA_GetChannelStatusFlags(DMA_Type * base,uint32_t channel)765 uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel)
766 {
767     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
768 
769     uint32_t retval = 0;
770 
771     /* Get DONE bit flag */
772     retval |= ((base->CH[channel].CH_CSR & DMA_CH_CSR_DONE_MASK) >> DMA_CH_CSR_DONE_SHIFT);
773     /* Get ERROR bit flag */
774     retval |= (((base->CH[channel].CH_ES & DMA_CH_ES_ERR_MASK) >> DMA_CH_ES_ERR_SHIFT) << 1U);
775     /* Get INT bit flag */
776     retval |= (((base->CH[channel].CH_INT & DMA_CH_INT_INT_MASK) >> DMA_CH_INT_INT_SHIFT) << 2U);
777 
778     return retval;
779 }
780 
781 /*!
782  * brief Clears the eDMA channel status flags.
783  *
784  * param base eDMA peripheral base address.
785  * param channel eDMA channel number.
786  * param mask The mask of channel status to be cleared. Users need to use
787  *             the defined _edma_channel_status_flags type.
788  */
EDMA_ClearChannelStatusFlags(DMA_Type * base,uint32_t channel,uint32_t mask)789 void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask)
790 {
791     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
792 
793     /* Clear DONE bit flag */
794     if ((mask & (uint32_t)kEDMA_DoneFlag) != 0U)
795     {
796         base->CH[channel].CH_CSR |= DMA_CH_CSR_DONE_MASK;
797     }
798     /* Clear ERROR bit flag */
799     if ((mask & (uint32_t)kEDMA_ErrorFlag) != 0U)
800     {
801         base->CH[channel].CH_ES |= DMA_CH_ES_ERR_MASK;
802     }
803     /* Clear INT bit flag */
804     if ((mask & (uint32_t)kEDMA_InterruptFlag) != 0U)
805     {
806         base->CH[channel].CH_INT |= DMA_CH_INT_INT_MASK;
807     }
808 }
809 
810 /*!
811  * brief Creates the eDMA handle.
812  *
813  * This function is called if using the transactional API for eDMA. This
814  * function
815  * initializes the internal state of the eDMA handle.
816  *
817  * param handle eDMA handle pointer. The eDMA handle stores callback function
818  * and
819  *               parameters.
820  * param base eDMA peripheral base address.
821  * param channel eDMA channel number.
822  */
EDMA_CreateHandle(edma_handle_t * handle,DMA_Type * base,uint32_t channel)823 void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel)
824 {
825     assert(handle != NULL);
826     assert(channel < (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL);
827 
828     uint32_t edmaInstance;
829     uint32_t channelIndex;
830 
831     handle->base    = base;
832     handle->channel = (uint8_t)channel;
833     /* Get the DMA instance number */
834     edmaInstance               = EDMA_GetInstance(base);
835     channelIndex               = (edmaInstance * (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL) + channel;
836     s_EDMAHandle[channelIndex] = handle;
837     /* record enabled channel */
838     s_EDMAEnabledChannel[edmaInstance][channel] = true;
839     /* Enable NVIC interrupt */
840     (void)EnableIRQ(s_edmaIRQNumber[edmaInstance][channel]);
841 
842     /*
843        Reset TCD registers to zero. Unlike the EDMA_TcdReset(DREQ will be set),
844        CSR will be 0. Because in order to suit EDMA busy check mechanism in
845        EDMA_SubmitTransfer, CSR must be set 0.
846     */
847     EDMA_ResetChannel(base, channel);
848 }
849 
850 /*!
851  * brief Installs the TCDs memory pool into the eDMA handle.
852  *
853  * This function is called after the EDMA_CreateHandle to use scatter/gather
854  * feature.
855  *
856  * param handle eDMA handle pointer.
857  * param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned.
858  * param tcdSize The number of TCD slots.
859  */
EDMA_InstallTCDMemory(edma_handle_t * handle,edma_tcd_t * tcdPool,uint32_t tcdSize)860 void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize)
861 {
862     assert(handle != NULL);
863     assert(((uint32_t)tcdPool & 0x1FU) == 0U);
864 
865     /* Initialize tcd queue attibute. */
866     handle->header  = 1;
867     handle->tail    = 0;
868     handle->tcdUsed = 0;
869     handle->tcdSize = (int8_t)tcdSize;
870     handle->flags   = 0;
871     handle->tcdPool = tcdPool;
872 }
873 
874 /*!
875  * brief Installs a callback function for the eDMA transfer.
876  *
877  * This callback is called in the eDMA IRQ handler. Use the callback to do
878  * something after
879  * the current major loop transfer completes.
880  *
881  * param handle eDMA handle pointer.
882  * param callback eDMA callback function pointer.
883  * param userData A parameter for the callback function.
884  */
EDMA_SetCallback(edma_handle_t * handle,edma_callback callback,void * userData)885 void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData)
886 {
887     assert(handle != NULL);
888 
889     handle->callback = callback;
890     handle->userData = userData;
891 }
892 
893 /*!
894  * brief Prepares the eDMA transfer structure configurations.
895  *
896  * This function prepares the transfer configuration structure according to the
897  * user input.
898  *
899  * param config The user configuration structure of type edma_transfer_config_t.
900  * param srcAddr eDMA transfer source address.
901  * param srcWidth eDMA transfer source address width(bytes).
902  * param srcOffset eDMA transfer source address offset
903  * param destAddr eDMA transfer destination address.
904  * param destWidth eDMA transfer destination address width(bytes).
905  * param destOffset eDMA transfer destination address offset
906  * param bytesEachRequest eDMA transfer bytes per channel request.
907  * param transferBytes eDMA transfer bytes to be transferred.
908  *
909  * note The data address and the data width must be consistent. For example, if
910  * the SRC is 4 bytes, the source address must be 4 bytes aligned, or it results
911  * in source address error (SAE).
912  */
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)913 void EDMA_PrepareTransferConfig(edma_transfer_config_t *config,
914                                 void *srcAddr,
915                                 uint32_t srcWidth,
916                                 int16_t srcOffset,
917                                 void *destAddr,
918                                 uint32_t destWidth,
919                                 int16_t destOffset,
920                                 uint32_t bytesEachRequest,
921                                 uint32_t transferBytes)
922 {
923     assert(config != NULL);
924     assert(srcAddr != NULL);
925     assert(destAddr != NULL);
926     assert((srcWidth == 1U) || (srcWidth == 2U) || (srcWidth == 4U) || (srcWidth == 8U) || (srcWidth == 16U) ||
927            (srcWidth == 32U) || srcWidth == 64U);
928     assert((destWidth == 1U) || (destWidth == 2U) || (destWidth == 4U) || (destWidth == 8U) || (destWidth == 16U) ||
929            (destWidth == 32U) || (destWidth == 64U));
930     assert(transferBytes % bytesEachRequest == 0U);
931     assert(((uint32_t)(uint32_t *)srcAddr % srcWidth) == 0U);
932     assert(((uint32_t)(uint32_t *)destAddr % destWidth) == 0U);
933 
934     /* Initializes the configure structure to zero. */
935     (void)memset(config, 0, sizeof(*config));
936 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
937     config->srcAddr  = MEMORY_ConvertMemoryMapAddress((uint32_t)(uint32_t *)srcAddr, kMEMORY_Local2DMA);
938     config->destAddr = MEMORY_ConvertMemoryMapAddress((uint32_t)(uint32_t *)destAddr, kMEMORY_Local2DMA);
939 #else
940     config->destAddr = (uint32_t)destAddr;
941     config->srcAddr  = (uint32_t)srcAddr;
942 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
943 
944     config->minorLoopBytes  = bytesEachRequest;
945     config->majorLoopCounts = transferBytes / bytesEachRequest;
946     switch (srcWidth)
947     {
948         case 1U:
949             config->srcTransferSize = kEDMA_TransferSize1Bytes;
950             break;
951         case 2U:
952             config->srcTransferSize = kEDMA_TransferSize2Bytes;
953             break;
954         case 4U:
955             config->srcTransferSize = kEDMA_TransferSize4Bytes;
956             break;
957         case 8U:
958             config->srcTransferSize = kEDMA_TransferSize8Bytes;
959             break;
960         case 16U:
961             config->srcTransferSize = kEDMA_TransferSize16Bytes;
962             break;
963         case 32U:
964             config->srcTransferSize = kEDMA_TransferSize32Bytes;
965             break;
966         case 64U:
967             config->srcTransferSize = kEDMA_TransferSize64Bytes;
968             break;
969         default:
970             assert(false);
971             break;
972     }
973     switch (destWidth)
974     {
975         case 1U:
976             config->destTransferSize = kEDMA_TransferSize1Bytes;
977             break;
978         case 2U:
979             config->destTransferSize = kEDMA_TransferSize2Bytes;
980             break;
981         case 8U:
982             config->destTransferSize = kEDMA_TransferSize8Bytes;
983             break;
984         case 4U:
985             config->destTransferSize = kEDMA_TransferSize4Bytes;
986             break;
987         case 16U:
988             config->destTransferSize = kEDMA_TransferSize16Bytes;
989             break;
990         case 32U:
991             config->destTransferSize = kEDMA_TransferSize32Bytes;
992             break;
993         case 64U:
994             config->destTransferSize = kEDMA_TransferSize64Bytes;
995             break;
996         default:
997             assert(false);
998             break;
999     }
1000 
1001     config->destOffset = destOffset;
1002     config->srcOffset  = srcOffset;
1003 }
1004 
1005 /*!
1006  * brief Prepares the eDMA transfer structure.
1007  *
1008  * This function prepares the transfer configuration structure according to the
1009  * user input.
1010  *
1011  * param config The user configuration structure of type edma_transfer_config_t.
1012  * param srcAddr eDMA transfer source address.
1013  * param srcWidth eDMA transfer source address width(bytes).
1014  * param destAddr eDMA transfer destination address.
1015  * param destWidth eDMA transfer destination address width(bytes).
1016  * param bytesEachRequest eDMA transfer bytes per channel request.
1017  * param transferBytes eDMA transfer bytes to be transferred.
1018  * param type eDMA transfer type.
1019  * note The data address and the data width must be consistent. For example, if
1020  * the SRC
1021  *       is 4 bytes, the source address must be 4 bytes aligned, or it results
1022  * in
1023  *       source address error (SAE).
1024  */
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)1025 void EDMA_PrepareTransfer(edma_transfer_config_t *config,
1026                           void *srcAddr,
1027                           uint32_t srcWidth,
1028                           void *destAddr,
1029                           uint32_t destWidth,
1030                           uint32_t bytesEachRequest,
1031                           uint32_t transferBytes,
1032                           edma_transfer_type_t type)
1033 {
1034     assert(config != NULL);
1035 
1036     int16_t srcOffset = 0, destOffset = 0;
1037 
1038     switch (type)
1039     {
1040         case kEDMA_MemoryToMemory:
1041             destOffset = (int16_t)destWidth;
1042             srcOffset  = (int16_t)srcWidth;
1043             break;
1044         case kEDMA_MemoryToPeripheral:
1045             destOffset = 0;
1046             srcOffset  = (int16_t)srcWidth;
1047             break;
1048         case kEDMA_PeripheralToMemory:
1049             destOffset = (int16_t)destWidth;
1050             srcOffset  = 0;
1051             break;
1052         case kEDMA_PeripheralToPeripheral:
1053             destOffset = 0;
1054             srcOffset  = 0;
1055             break;
1056         default:
1057             /* All the cases have been listed above, the default clause should not be reached. */
1058             assert(false);
1059             break;
1060     }
1061 
1062     EDMA_PrepareTransferConfig(config, srcAddr, srcWidth, srcOffset, destAddr, destWidth, destOffset, bytesEachRequest,
1063                                transferBytes);
1064 }
1065 
1066 /*!
1067  * brief Submits the eDMA transfer request.
1068  *
1069  * This function submits the eDMA transfer request according to the transfer
1070  * configuration structure.
1071  * If submitting the transfer request repeatedly, this function packs an
1072  * unprocessed request as
1073  * a TCD and enables scatter/gather feature to process it in the next time.
1074  *
1075  * param handle eDMA handle pointer.
1076  * param config Pointer to eDMA transfer configuration structure.
1077  * retval kStatus_EDMA_Success It means submit transfer request succeed.
1078  * retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer
1079  * request is not allowed.
1080  * retval kStatus_EDMA_Busy It means the given channel is busy, need to submit
1081  * request later.
1082  */
EDMA_SubmitTransfer(edma_handle_t * handle,const edma_transfer_config_t * config)1083 status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config)
1084 {
1085     assert(handle != NULL);
1086     assert(config != NULL);
1087 
1088     edma_tcd_t *tcdRegs = (edma_tcd_t *)((uint32_t)&handle->base->CH[handle->channel] + 0x00000020U);
1089 
1090     if (handle->tcdPool == NULL)
1091     {
1092         /*
1093             Check if EDMA is busy: if major loop count is not zero, then the channel is busying transfer
1094         */
1095         if (EDMA_GetRemainingMajorLoopCount(handle->base, handle->channel) != 0U)
1096         {
1097             return kStatus_EDMA_Busy;
1098         }
1099         else
1100         {
1101             EDMA_HandleTransferConfig(handle, handle->channel, config, NULL);
1102             /* Enable auto disable request feature */
1103             handle->base->CH[handle->channel].TCD_CSR |= DMA_TCD_CSR_DREQ_MASK;
1104             /* Enable major interrupt */
1105             handle->base->CH[handle->channel].TCD_CSR |= DMA_TCD_CSR_INTMAJOR_MASK;
1106 
1107             return kStatus_Success;
1108         }
1109     }
1110     else /* Use the TCD queue. */
1111     {
1112         uint32_t primask;
1113         uint16_t csr;
1114         int8_t currentTcd;
1115         int8_t previousTcd;
1116         int8_t nextTcd;
1117         uint32_t temp = 0;
1118 
1119         /* Check if tcd pool is full. */
1120         primask = DisableGlobalIRQ();
1121         if (handle->tcdUsed >= handle->tcdSize)
1122         {
1123             EnableGlobalIRQ(primask);
1124 
1125             return kStatus_EDMA_QueueFull;
1126         }
1127         currentTcd = handle->tail;
1128         handle->tcdUsed++;
1129         /* Calculate index of next TCD */
1130         nextTcd = currentTcd + 1;
1131         if (nextTcd == handle->tcdSize)
1132         {
1133             nextTcd = 0;
1134         }
1135         /* Advance queue tail index */
1136         handle->tail = nextTcd;
1137         EnableGlobalIRQ(primask);
1138         /* Calculate index of previous TCD */
1139         previousTcd = currentTcd != 0 ? currentTcd - 1 : handle->tcdSize - 1;
1140         /* Configure current TCD block. */
1141         EDMA_TcdReset(&handle->tcdPool[currentTcd]);
1142 
1143         EDMA_TcdSetTransferConfig(&handle->tcdPool[currentTcd], config, NULL);
1144         /* Enable major interrupt */
1145         handle->tcdPool[currentTcd].CSR |= DMA_TCD_CSR_INTMAJOR_MASK;
1146 /* Link current TCD with next TCD for identification of current TCD */
1147 /* If defined TCM offet, do a offset to the address */
1148 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1149         temp = MEMORY_ConvertMemoryMapAddress((uint32_t)&handle->tcdPool[nextTcd], kMEMORY_Local2DMA);
1150 #else
1151         temp = (uint32_t)&handle->tcdPool[nextTcd];
1152 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
1153         handle->tcdPool[currentTcd].DLAST_SGA = temp;
1154         /* Chain from previous descriptor unless tcd pool size is 1(this descriptor
1155          * is its own predecessor). */
1156         if (currentTcd != previousTcd)
1157         {
1158             /* Enable scatter/gather feature in the previous TCD block. */
1159             csr =
1160                 (handle->tcdPool[previousTcd].CSR | (uint16_t)DMA_TCD_CSR_ESG_MASK) & ~(uint16_t)DMA_TCD_CSR_DREQ_MASK;
1161             handle->tcdPool[previousTcd].CSR = csr;
1162 /*
1163     Check if the TCD block in the registers is the previous one (points to
1164    current TCD block). It
1165     is used to check if the previous TCD linked has been loaded in TCD register.
1166    If so, it need to
1167     link the TCD register in case link the current TCD with the dead chain when
1168    TCD loading occurs
1169     before link the previous TCD block.
1170 */
1171 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1172             temp = MEMORY_ConvertMemoryMapAddress((uint32_t)&handle->tcdPool[currentTcd], kMEMORY_Local2DMA);
1173 #else
1174             temp = (uint32_t)&handle->tcdPool[currentTcd];
1175 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
1176             if (tcdRegs->DLAST_SGA == temp)
1177             {
1178                 /* Enable scatter/gather also in the TCD registers. */
1179                 csr = (tcdRegs->CSR | (uint16_t)DMA_TCD_CSR_ESG_MASK) & ~(uint16_t)DMA_TCD_CSR_DREQ_MASK;
1180                 /* Must write the CSR register one-time, because the transfer maybe
1181                  * finished anytime. */
1182                 tcdRegs->CSR = csr;
1183                 /*
1184                     It is very important to check the ESG bit!
1185                     Because this hardware design: if DONE bit is set, the ESG bit can
1186                    not be set. So it can
1187                     be used to check if the dynamic TCD link operation is successful. If
1188                    ESG bit is not set
1189                     and the DLAST_SGA is not the next TCD address(it means the dynamic
1190                    TCD link succeed and
1191                     the current TCD block has been loaded into TCD registers), it means
1192                    transfer finished
1193                     and TCD link operation fail, so must install TCD content into TCD
1194                    registers and enable
1195                     transfer again. And if ESG is set, it means transfer has
1196                    notfinished, so TCD dynamic
1197                     link succeed.
1198                 */
1199                 if ((tcdRegs->CSR & DMA_TCD_CSR_ESG_MASK) != 0U)
1200                 {
1201                     return kStatus_Success;
1202                 }
1203 /*
1204     Check whether the current TCD block is already loaded in the TCD registers.
1205    It is another
1206     condition when ESG bit is not set: it means the dynamic TCD link succeed and
1207    the current
1208     TCD block has been loaded into TCD registers.
1209 */
1210 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1211                 temp = MEMORY_ConvertMemoryMapAddress((uint32_t)&handle->tcdPool[nextTcd], kMEMORY_Local2DMA);
1212 #else
1213                 temp = (uint32_t)&handle->tcdPool[nextTcd];
1214 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
1215                 if (tcdRegs->DLAST_SGA == temp)
1216                 {
1217                     return kStatus_Success;
1218                 }
1219                 /*
1220                     If go to this, means the previous transfer finished, and the DONE
1221                    bit is set.
1222                     So shall configure TCD registers.
1223                 */
1224             }
1225             else if (tcdRegs->DLAST_SGA != 0U)
1226             {
1227                 /* The current TCD block has been linked successfully. */
1228                 return kStatus_Success;
1229             }
1230             else
1231             {
1232                 /*
1233                     DLAST_SGA is 0 and it means the first submit transfer, so shall
1234                    configure
1235                     TCD registers.
1236                 */
1237             }
1238         }
1239         /* There is no live chain, TCD block need to be installed in TCD registers.
1240          */
1241         EDMA_InstallTCD(handle->base, handle->channel, &handle->tcdPool[currentTcd]);
1242         /* Enable channel request again. */
1243         if ((handle->flags & EDMA_TRANSFER_ENABLED_MASK) != 0U)
1244         {
1245             handle->base->CH[handle->channel].CH_CSR =
1246                 (handle->base->CH[handle->channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) | DMA_CH_CSR_ERQ_MASK;
1247         }
1248 
1249         return kStatus_Success;
1250     }
1251 }
1252 
1253 /*!
1254  * brief eDMA starts transfer.
1255  *
1256  * This function enables the channel request. Users can call this function after
1257  * submitting the transfer request
1258  * or before submitting the transfer request.
1259  *
1260  * param handle eDMA handle pointer.
1261  */
EDMA_StartTransfer(edma_handle_t * handle)1262 void EDMA_StartTransfer(edma_handle_t *handle)
1263 {
1264     assert(handle != NULL);
1265 
1266     if (handle->tcdPool == NULL)
1267     {
1268         handle->base->CH[handle->channel].CH_CSR =
1269             (handle->base->CH[handle->channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) | DMA_CH_CSR_ERQ_MASK;
1270     }
1271     else /* Use the TCD queue. */
1272     {
1273         uint32_t primask;
1274         edma_tcd_t *tcdRegs = (edma_tcd_t *)((uint32_t)&handle->base->CH[handle->channel] + 0x00000020U);
1275 
1276         handle->flags |= EDMA_TRANSFER_ENABLED_MASK;
1277 
1278         /* Check if there was at least one descriptor submitted since reset (TCD in
1279          * registers is valid) */
1280         if (tcdRegs->DLAST_SGA != 0U)
1281         {
1282             primask = DisableGlobalIRQ();
1283             /* Check if channel request is actually disable. */
1284             if ((handle->base->CH[handle->channel].CH_CSR & DMA_CH_CSR_ERQ_MASK & (1U << handle->channel)) == 0U)
1285             {
1286                 /* Check if transfer is paused. */
1287                 if ((!((handle->base->CH[handle->channel].CH_CSR & DMA_CH_CSR_DONE_MASK) != 0U)) ||
1288                     ((tcdRegs->CSR & DMA_TCD_CSR_ESG_MASK) != 0u))
1289                 {
1290                     /*
1291                         Re-enable channel request must be as soon as possible, so must put
1292                        it into
1293                         critical section to avoid task switching or interrupt service
1294                        routine.
1295                     */
1296                     handle->base->CH[handle->channel].CH_CSR =
1297                         (handle->base->CH[handle->channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) | DMA_CH_CSR_ERQ_MASK;
1298                 }
1299             }
1300             EnableGlobalIRQ(primask);
1301         }
1302     }
1303 }
1304 
1305 /*!
1306  * brief eDMA stops transfer.
1307  *
1308  * This function disables the channel request to pause the transfer. Users can
1309  * call EDMA_StartTransfer()
1310  * again to resume the transfer.
1311  *
1312  * param handle eDMA handle pointer.
1313  */
EDMA_StopTransfer(edma_handle_t * handle)1314 void EDMA_StopTransfer(edma_handle_t *handle)
1315 {
1316     assert(handle != NULL);
1317 
1318     handle->flags &= (uint8_t)(~EDMA_TRANSFER_ENABLED_MASK);
1319     handle->base->CH[handle->channel].CH_CSR =
1320         (handle->base->CH[handle->channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) & ~DMA_CH_CSR_ERQ_MASK;
1321 }
1322 
1323 /*!
1324  * brief eDMA aborts transfer.
1325  *
1326  * This function disables the channel request and clear transfer status bits.
1327  * Users can submit another transfer after calling this API.
1328  *
1329  * param handle DMA handle pointer.
1330  */
EDMA_AbortTransfer(edma_handle_t * handle)1331 void EDMA_AbortTransfer(edma_handle_t *handle)
1332 {
1333     handle->base->CH[handle->channel].CH_CSR =
1334         (handle->base->CH[handle->channel].CH_CSR & (~DMA_CH_CSR_DONE_MASK)) & ~DMA_CH_CSR_ERQ_MASK;
1335     /*
1336         Clear CSR to release channel. Because if the given channel started
1337        transfer,
1338         CSR will be not zero. Because if it is the last transfer, DREQ will be
1339        set.
1340         If not, ESG will be set.
1341     */
1342     handle->base->CH[handle->channel].TCD_CSR = 0;
1343     /* Cancel all next TCD transfer. */
1344     handle->base->CH[handle->channel].TCD_DLAST_SGA = 0;
1345 
1346     /* Handle the tcd */
1347     if (handle->tcdPool != NULL)
1348     {
1349         handle->header  = 1;
1350         handle->tail    = 0;
1351         handle->tcdUsed = 0;
1352     }
1353 }
1354 
1355 /*!
1356  * brief eDMA IRQ handler for the current major loop transfer completion.
1357  *
1358  * This function clears the channel major interrupt flag and calls
1359  * the callback function if it is not NULL.
1360  *
1361  * param handle eDMA handle pointer.
1362  */
EDMA_HandleIRQ(edma_handle_t * handle)1363 void EDMA_HandleIRQ(edma_handle_t *handle)
1364 {
1365     assert(handle != NULL);
1366 
1367     bool transfer_done;
1368 
1369     /* Check if transfer is already finished. */
1370     transfer_done = ((handle->base->CH[handle->channel].CH_CSR & DMA_CH_CSR_DONE_MASK) != 0U);
1371 
1372     /* Clear EDMA interrupt flag */
1373     handle->base->CH[handle->channel].CH_INT |= DMA_CH_INT_INT_MASK;
1374 
1375     if (handle->tcdPool == NULL)
1376     {
1377         if (handle->callback != NULL)
1378         {
1379             (handle->callback)(handle, handle->userData, transfer_done, 0);
1380         }
1381     }
1382     else /* Use the TCD queue. */
1383     {
1384         uint32_t sga = handle->base->CH[handle->channel].TCD_DLAST_SGA;
1385         uint32_t sga_index;
1386         int32_t tcds_done;
1387         uint8_t new_header;
1388         uint32_t temp = 0;
1389 
1390 /* Get the offset of the current transfer TCD blocks. */
1391 #if defined FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1392         temp = MEMORY_ConvertMemoryMapAddress((uint32_t)handle->tcdPool, kMEMORY_Local2DMA);
1393 #else
1394         temp = (uint32_t)handle->tcdPool;
1395 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
1396         sga -= temp;
1397         /* Get the index of the current transfer TCD blocks. */
1398         sga_index = sga / sizeof(edma_tcd_t);
1399         /* Adjust header positions. */
1400         if (transfer_done)
1401         {
1402             /* New header shall point to the next TCD (current one is already
1403              * finished) */
1404             new_header = (uint8_t)sga_index;
1405         }
1406         else
1407         {
1408             /* New header shall point to this descriptor (not finished yet) */
1409             new_header = sga_index != 0U ? (uint8_t)sga_index - 1U : (uint8_t)handle->tcdSize - 1U;
1410         }
1411         /* Calculate the number of finished TCDs */
1412         if (new_header == (uint8_t)handle->header)
1413         {
1414             if (handle->tcdUsed == handle->tcdSize)
1415             {
1416                 tcds_done = handle->tcdUsed;
1417             }
1418             else
1419             {
1420                 /* Internal error occurs. */
1421                 tcds_done = 0;
1422             }
1423         }
1424         else
1425         {
1426             tcds_done = (int32_t)new_header - (int32_t)handle->header;
1427             if (tcds_done < 0)
1428             {
1429                 tcds_done += handle->tcdSize;
1430             }
1431             /*
1432              * While code run to here, it means a TCD transfer Done and a new TCD has loaded to the hardware
1433              * so clear DONE here to allow submit scatter gather transfer request in the callback to avoid TCD
1434              * overwritten.
1435              */
1436             if (transfer_done)
1437             {
1438                 handle->base->CH[handle->channel].CH_CSR |= DMA_CH_CSR_DONE_MASK;
1439             }
1440         }
1441         /* Advance header to the point beyond the last finished TCD block. */
1442         handle->header = (int8_t)new_header;
1443         /* Release TCD blocks. */
1444         handle->tcdUsed -= (int8_t)tcds_done;
1445         /* Invoke callback function. */
1446         if (handle->callback != NULL)
1447         {
1448             (handle->callback)(handle, handle->userData, transfer_done, tcds_done);
1449         }
1450 
1451         /* clear the DONE bit here is meaningful for below cases:
1452          *1.A new TCD has been loaded to EDMA already:
1453          * need to clear the DONE bit in the IRQ handler to avoid TCD in EDMA been overwritten
1454          * if peripheral request isn't coming before next transfer request.
1455          *2.A new TCD has not been loaded to EDMA:
1456          * for the case that transfer request occur in the privious edma callback, this is a case that doesn't
1457          * need scatter gather, so keep DONE bit during the next transfer request will re-install the TCD.
1458          */
1459         if (transfer_done)
1460         {
1461             handle->base->CH[handle->channel].CH_CSR |= DMA_CH_CSR_DONE_MASK;
1462         }
1463     }
1464 }
1465 
1466 #ifdef DMA0
1467 void DMA0_DriverIRQHandler(void);
DMA0_DriverIRQHandler(void)1468 void DMA0_DriverIRQHandler(void)
1469 {
1470     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1471     uint32_t i           = 0;
1472     uint32_t instance    = EDMA_GetInstance(DMA0);
1473     uint32_t prevChannel = FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1474 
1475 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1476     channel = FSL_FEATURE_EDMA_INSTANCE_CHANNELn(DMA0);
1477 #endif
1478 
1479     for (i = 0; i < channel; i++)
1480     {
1481         if (s_EDMAEnabledChannel[instance][i])
1482         {
1483             if ((EDMA_GetChannelStatusFlags(DMA0, i) & kEDMA_InterruptFlag) != 0U)
1484             {
1485                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1486             }
1487         }
1488     }
1489     SDK_ISR_EXIT_BARRIER;
1490 }
1491 #endif
1492 
1493 #ifdef ADMA__EDMA0
1494 void ADMA_EDMA0_INT_DriverIRQHandler(void);
ADMA_EDMA0_INT_DriverIRQHandler(void)1495 void ADMA_EDMA0_INT_DriverIRQHandler(void)
1496 {
1497     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1498     uint32_t i           = 0;
1499     DMA_Type *base       = ADMA__EDMA0;
1500     uint32_t instance    = EDMA_GetInstance(base);
1501     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1502 
1503 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1504     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1505 #endif
1506 
1507     for (i = 0; i < channel; i++)
1508     {
1509         if (s_EDMAEnabledChannel[instance][i])
1510         {
1511             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1512             {
1513                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1514             }
1515         }
1516     }
1517     SDK_ISR_EXIT_BARRIER;
1518 }
1519 #endif
1520 
1521 #ifdef ADMA__EDMA1
1522 void ADMA_EDMA1_INT_DriverIRQHandler(void);
ADMA_EDMA1_INT_DriverIRQHandler(void)1523 void ADMA_EDMA1_INT_DriverIRQHandler(void)
1524 {
1525     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1526     uint32_t i           = 0;
1527     DMA_Type *base       = ADMA__EDMA1;
1528     uint32_t instance    = EDMA_GetInstance(base);
1529     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1530 
1531 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1532     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1533 #endif
1534 
1535     for (i = 0; i < channel; i++)
1536     {
1537         if (s_EDMAEnabledChannel[instance][i])
1538         {
1539             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1540             {
1541                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1542             }
1543         }
1544     }
1545     SDK_ISR_EXIT_BARRIER;
1546 }
1547 #endif
1548 
1549 #ifdef ADMA__EDMA2
1550 void ADMA_EDMA2_INT_DriverIRQHandler(void);
ADMA_EDMA2_INT_DriverIRQHandler(void)1551 void ADMA_EDMA2_INT_DriverIRQHandler(void)
1552 {
1553     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1554     uint32_t i           = 0;
1555     DMA_Type *base       = ADMA__EDMA2;
1556     uint32_t instance    = EDMA_GetInstance(base);
1557     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1558 
1559 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1560     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1561 #endif
1562 
1563     for (i = 0; i < channel; i++)
1564     {
1565         if (s_EDMAEnabledChannel[instance][i])
1566         {
1567             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1568             {
1569                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1570             }
1571         }
1572     }
1573     SDK_ISR_EXIT_BARRIER;
1574 }
1575 #endif
1576 
1577 #ifdef ADMA__EDMA3
1578 void ADMA_EDMA3_INT_DriverIRQHandler(void);
ADMA_EDMA3_INT_DriverIRQHandler(void)1579 void ADMA_EDMA3_INT_DriverIRQHandler(void)
1580 {
1581     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1582     uint32_t i           = 0;
1583     DMA_Type *base       = ADMA__EDMA3;
1584     uint32_t instance    = EDMA_GetInstance(base);
1585     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1586 
1587 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1588     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1589 #endif
1590 
1591     for (i = 0; i < channel; i++)
1592     {
1593         if (s_EDMAEnabledChannel[instance][i])
1594         {
1595             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1596             {
1597                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1598             }
1599         }
1600     }
1601     SDK_ISR_EXIT_BARRIER;
1602 }
1603 #endif
1604 
1605 #ifdef AUDIO__EDMA0
1606 void AUDIO_EDMA0_INT_DriverIRQHandler(void);
AUDIO_EDMA0_INT_DriverIRQHandler(void)1607 void AUDIO_EDMA0_INT_DriverIRQHandler(void)
1608 {
1609     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1610     uint32_t i           = 0;
1611     DMA_Type *base       = AUDIO__EDMA0;
1612     uint32_t instance    = EDMA_GetInstance(base);
1613     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1614 
1615 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1616     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1617 #endif
1618     for (i = 0; i < channel; i++)
1619     {
1620         if (s_EDMAEnabledChannel[instance][i])
1621         {
1622             if ((EDMA_GetChannelStatusFlags(AUDIO__EDMA0, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1623             {
1624                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1625             }
1626         }
1627     }
1628     SDK_ISR_EXIT_BARRIER;
1629 }
1630 #endif
1631 
1632 #ifdef AUDIO__EDMA1
1633 void AUDIO_EDMA1_INT_DriverIRQHandler(void);
AUDIO_EDMA1_INT_DriverIRQHandler(void)1634 void AUDIO_EDMA1_INT_DriverIRQHandler(void)
1635 {
1636     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1637     uint32_t i           = 0;
1638     DMA_Type *base       = AUDIO__EDMA1;
1639     uint32_t instance    = EDMA_GetInstance(base);
1640     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1641 
1642 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1643     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1644 #endif
1645     for (i = 0; i < channel; i++)
1646     {
1647         if (s_EDMAEnabledChannel[instance][i])
1648         {
1649             if ((EDMA_GetChannelStatusFlags(AUDIO__EDMA1, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1650             {
1651                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1652             }
1653         }
1654     }
1655     SDK_ISR_EXIT_BARRIER;
1656 }
1657 #endif
1658 
1659 #ifdef DMA__EDMA0
1660 void DMA_EDMA0_INT_DriverIRQHandler(void);
DMA_EDMA0_INT_DriverIRQHandler(void)1661 void DMA_EDMA0_INT_DriverIRQHandler(void)
1662 {
1663     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1664     uint32_t i           = 0;
1665     DMA_Type *base       = DMA__EDMA0;
1666     uint32_t instance    = EDMA_GetInstance(base);
1667     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1668 
1669 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1670     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1671 #endif
1672     for (i = 0; i < channel; i++)
1673     {
1674         if (s_EDMAEnabledChannel[instance][i])
1675         {
1676             if ((EDMA_GetChannelStatusFlags(DMA__EDMA0, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1677             {
1678                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1679             }
1680         }
1681     }
1682     SDK_ISR_EXIT_BARRIER;
1683 }
1684 #endif
1685 
1686 #ifdef DMA__EDMA1
1687 void DMA_EDMA1_INT_DriverIRQHandler(void);
DMA_EDMA1_INT_DriverIRQHandler(void)1688 void DMA_EDMA1_INT_DriverIRQHandler(void)
1689 {
1690     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1691     uint32_t i           = 0;
1692     DMA_Type *base       = DMA__EDMA1;
1693     uint32_t instance    = EDMA_GetInstance(base);
1694     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1695 
1696 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1697     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1698 #endif
1699     for (i = 0; i < channel; i++)
1700     {
1701         if (s_EDMAEnabledChannel[instance][i])
1702         {
1703             if ((EDMA_GetChannelStatusFlags(DMA__EDMA1, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1704             {
1705                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1706             }
1707         }
1708     }
1709     SDK_ISR_EXIT_BARRIER;
1710 }
1711 #endif
1712 
1713 #ifdef CONNECTIVITY__EDMA
1714 void CONNECTIVITY__EDMA_INT_DriverIRQHandler(void);
CONNECTIVITY__EDMA_INT_DriverIRQHandler(void)1715 void CONNECTIVITY__EDMA_INT_DriverIRQHandler(void)
1716 {
1717     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1718     uint32_t i           = 0;
1719     DMA_Type *base       = CONNECTIVITY__EDMA;
1720     uint32_t instance    = EDMA_GetInstance(base);
1721     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1722 
1723 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1724     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1725 #endif
1726     for (i = 0; i < channel; i++)
1727     {
1728         if (s_EDMAEnabledChannel[instance][i])
1729         {
1730             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1731             {
1732                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1733             }
1734         }
1735     }
1736 }
1737 #endif
1738 
1739 #ifdef EDMA1
1740 void EDMA1_0_15_DriverIRQHandler(void);
EDMA1_0_15_DriverIRQHandler(void)1741 void EDMA1_0_15_DriverIRQHandler(void)
1742 {
1743     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1744     uint32_t i           = 0;
1745     DMA_Type *base       = EDMA1;
1746     uint32_t instance    = EDMA_GetInstance(base);
1747     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1748 
1749 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1750     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1751 #endif
1752 
1753     for (i = 0; i < channel; i++)
1754     {
1755         if (s_EDMAEnabledChannel[instance][i])
1756         {
1757             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1758             {
1759                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1760             }
1761         }
1762     }
1763 
1764 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate
1765   overlapping
1766   exception return operation might vector to incorrect interrupt */
1767 #if defined __CORTEX_M && (__CORTEX_M == 4U)
1768     __DSB();
1769 #endif
1770 }
1771 
1772 void EDMA1_16_31_DriverIRQHandler(void);
EDMA1_16_31_DriverIRQHandler(void)1773 void EDMA1_16_31_DriverIRQHandler(void)
1774 {
1775     uint32_t channel     = FSL_FEATURE_EDMA_MODULE_CHANNEL;
1776     uint32_t i           = 0;
1777     DMA_Type *base       = EDMA1;
1778     uint32_t instance    = EDMA_GetInstance(base);
1779     uint32_t prevChannel = (uint32_t)FSL_FEATURE_EDMA_MODULE_CHANNEL * instance;
1780 
1781 #if defined FSL_FEATURE_EDMA_INSTANCE_CHANNELn
1782     channel = (uint32_t)FSL_FEATURE_EDMA_INSTANCE_CHANNELn(base);
1783 #endif
1784 
1785     for (i = 0; i < channel; i++)
1786     {
1787         if (s_EDMAEnabledChannel[instance][i])
1788         {
1789             if ((EDMA_GetChannelStatusFlags(base, i) & (uint32_t)kEDMA_InterruptFlag) != 0U)
1790             {
1791                 EDMA_HandleIRQ(s_EDMAHandle[prevChannel + i]);
1792             }
1793         }
1794     }
1795 
1796 /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate
1797   overlapping
1798   exception return operation might vector to incorrect interrupt */
1799 #if defined __CORTEX_M && (__CORTEX_M == 4U)
1800     __DSB();
1801 #endif
1802 }
1803 #endif
1804