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