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