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