MCUXpresso SDK API Reference Manual  Rev. 0
NXP Semiconductors
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
EDMA Peripheral and Driver Overview

Peripheral features

The enhanced direct memory access (eDMA) controller is a second-generation module Capable of performing complex data transfers with minimal intervention from a host processor.

How this peripheral works

Once the eDMA channel is activated through software/peripheral, the eDMA request input signal will be registered internally and then routed through the eDMA engine: first through the control module, then into the program model and channel arbitration. In the next cycle, the channel arbitration performs, using the fixed-priority or round-robin algorithm. After arbitration completes, the activated channel TCD will be loaded into the eDMA engine.

The modules associated with the data transfer sequence through the required source reads and destination write to perform the actual data movement continues until the minor byte count has transferred.

After the minor bytes count has transferred, the eDMA engine performs the required updates to certain fields in the appropriate TCD, for example,

  1. offset applied to SADDR(source address)/DADDR(destination address)
  2. major loop count in CITER decrement. If the major loop count is exhausted, additional operations are performed. These include:
  1. Final address adjustments and reloading of the BITER field into the CITER.
  2. The assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled).

How this driver is designed to make this peripheral works.

The eDMA peripheral is powerful with complex transfer features supported. To satisfy different user getting different demands for the feature sets/optimization level/flexibility/abstraction level, 2 parallel layers are provided in this driver (DO NOT MIX THE USAGE OF THESE 2 LAYERS!!!):

Below introduce the detail data structure/API for the two layers.

How to use this driver

Functional Layer

Transactional Layer

Typical Use Cases

  1. Single transfer(using edma channel functional layer) For a single one shot transfer,
    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    * EDMA_EnableChannelRequest(base, channel, true);
    *
    For advance transfer case with modulo feature
    * psTransfer.pSrcAddr = xxx;
    * psTransfer.pDstAddr = xxx;
    * psTransfer.eSrcWidthOfEachTransfer = kEDMA_TransferWidth32Bits;
    * psTransfer.eDstWidthOfEachTransfer = kEDMA_TransferWidth32Bits;
    * psTransfer.i16SrcOffsetOfEachTransfer = 4U;
    * psTransfer.i16DstOffsetOfEachTransfer = 4U;
    * psTransfer.u32BytesEachRequest = 4;
    * psTransfer.u32TotalBytes = 256;
    * psTransfer.eSrcAddrModulo = kEDMA_ChannelModulo256bytes;
    * psTransfer.u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    * EDMA_EnableChannelRequest(base, channel, true);
    *
  2. Scatter gather transfer(using edma channel functional layer)
    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * EDMA_ConfigChannelSoftwareTCD(tcd, &transferConfig);
    * psTransfer->psLinkTCD = tcd;
    *
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    * EDMA_EnableChannelRequest(base, channel, true);
    *
  3. Loop transfer(using edma software TCD interfaces)
    * EDMA_Init(DMA, channel, &config);
    * EDMA_GetChannelDefaultTransferConfig(psTransfer0, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer0->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * EDMA_GetChannelDefaultTransferConfig(psTransfer1, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer1->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * psTransfer0->psLinkTCD = tcd[1];
    * psTransfer1->psLinkTCD = tcd[0];
    * EDMA_ConfigChannelSoftwareTCD(&tcd[0], &psTransfer0);
    * EDMA_ConfigChannelSoftwareTCD(&tcd[1], &psTransfer1);
    * EDMA_InstallChannelSoftwareTCD(base, channel, tcd0);
    * EDMA_EnableChannelRequest(base, channel, true);
    *
  4. Channel link(using edma initialization and de-initialization interface)
    * EDMA_GetChannelDefaultTransferConfig(psTransfer0, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer0->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * EDMA_GetChannelDefaultTransferConfig(psTransfer1, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer1->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * psTransfer0->bEnableChannelMinorLoopLink = true;
    * psTransfer0->eMinorLoopLinkChannel = 1;
    *
    * config.psChannelTransferConfig[0] = &psTransfer0;
    * config.psChannelTransferConfig[1] = &psTransfer1;
    *
    * EDMA_Init(DMA, &config);
    * EDMA_EnableChannelRequest(base, channel, true);
    *
    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferMemoryToMemory);
    * config.bEnableChannelMinorLoopLink = true;
    * config.eMinorLoopLinkChannel = channel1;
    * config.u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    *
    * EDMA_EnableChannelRequest(base, channel, true);
    *
  5. Single transfer (using edma transactional layer)
    *
    * EDMA_TransferCreateHandle(handle, base, channel, tcdPool, tcdPoolCount, callback, userdata)
    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,bytesEachRequest,
    * totalBytes, eWidth, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * EDMA_TransferSubmitSingleTransfer(handle, psTransfer0);
    *
  6. Continuous single transfer request(using transactional layer dynamic scatter gather feature)
    * EDMA_TransferCreateHandle(handle, base, channel, tcdPool, tcdPoolCount, callback, userdata)
    * EDMA_GetChannelDefaultTransferConfig(psTransfer0, srcAddr, dstAddr,bytesEachRequest,
    * totalBytes, eWidth, kEDMA_ChannelTransferMemoryToMemory);
    * psTransfer->u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * psTransfer->srcAddrModulo = xxx;
    * EDMA_TransferSubmitSingleTransfer(handle, psTransfer0);
    *
    * EDMA_TransferSubmitSingleTransfer(handle, psTransfer1);
    * EDMA_TransferSubmitSingleTransfer(handle, psTransfer2);
    * .....
    *
  7. Loop transfer request(using transactional layer)
    * EDMA_TransferCreateHandle(handle, base, channel, tcdPool, tcdPoolCount, callback, userdata);
    *
    * EDMA_GetChannelDefaultTransferConfig(&scatterGather[0],srcAddr,dstAddr,bytesEachRequest,totalBytes,eWidth,
    * scatterGather[0].u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    * EDMA_GetChannelDefaultTransferConfig(&scatterGather[1],srcAddr,dstAddr,bytesEachRequest,totalBytes,eWidth,
    * scatterGather[0].u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * EDMA_TransferSubmitLoopTransfer(handle, &scatterGather[0], 2U);
    *
  8. Transfer between peripheral(one fifo only) and memory (using edma channel functional layer)
    Peripheral to memory:

    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferPeripheralToMemory);
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    * EDMA_EnableChannelRequest(base, channel, true);
    *

    Memory to peripheral:

    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannrlTransferMemoryToPeripheral);
    * psTransfer.u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    * EDMA_EnableChannelRequest(base, channel, true);
    *
    *
  9. Transfer between peripheral(multi fifo, assume fifo number 4, fifo address offset 4) and memory.
    Peripheral to memory, reading 4 fifo data from peripheral and write to continuous memory block(using edma channel functional layer)

    * EDMA_GetChannelDefaultTransferConfig(psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannelTransferPeripheralToMemory);
    * psTransfer.i16SrcReadOffset = 4U;
    * psTransfer.bEnableSrcMinorLoopOffset = true;
    * psTransfer.i32MinorLoopOffset = -16U;
    * psTransfer.u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    *
    * EDMA_EnableChannelRequest(base, channel, true);
    *

    Memory to peripheral, writing data from continuous memory block to 4 fifo

    * EDMA_GetChannelDefaultTransferConfig(&psTransfer, srcAddr, dstAddr,4,
    * 256, kEDMA_TransferWidth32Bits, kEDMA_ChannrlTransferMemoryToPeripheral);
    * psTransfer.i16DstOffsetOfEachTransfer = 4U;
    * psTransfer.bEnableDstMinorLoopOffset = true;
    * psTransfer.i32MinorLoopOffset = -16U;
    * psTransfer.u16EnabledInterruptMask = kEDMA_ChannelMajorLoopCompleteInterruptEnable;
    *
    * config.psChannelTransferConfig[0]= &psTransfer;
    * EDMA_Init(DMA, channel, &config);
    *
    * EDMA_EnableChannelRequest(base, channel, true);
    *