| Kinetis SDK API Reference Manual 1.0.0-beta Freescale Semiconductor, Inc.

- Introduction
- Related Pages
- API Usage

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Data Structures | Typedefs | Enumerations
eDMA Peripheral Driver
Enhanced Direct Memory Access (eDMA)

The section describes the programming interface of the eDMA Peripheral driver. More...

## Data Structures
struct | edma_scatter_list_t
| Data structure for configuring a discrete memory transfer. More...
struct | edma_channel_t
| Data structure for the DMA channel. More...

## Typedefs
typedef void(* | edma_callback_t )(void *parameter, edma_channel_status_t status)
| Definition for the DMA channel callback function. More...

## Enumerations
enum | edma_descriptor_internal_status_t { kEdmaDescriptorDone = 0U, kEdmaDescriptorPrepared = 0xFFFFFFFFU }
| Status of the DMA hardware descriptor. More...
enum | edma_tcd_alignment_t { kEdmaTcdAlignment = 0x20U, kEdmaTcdAlignmentMask = 0x1FU }
| Alignment for eDMA TCD start address. More...
enum | edma_channel_type_t { kEdmaInvalidChannel = 0xFFU, kEdmaAnyChannel = 0xFEU }
| A constant for the DMA allocation status. More...
enum | edma_channel_status_t { kEdmaIdle, kEdmaNormal, kEdmaError }
| Channel status for an eDMA channel. More...
enum | edma_transfer_type_t { kEdmaPeripheralToMemory, kEdmaMemoryToPeripheral, kEdmaMemoryToMemory, kEdmaPeripheralToPeripheral }
| A type for the DMA transfer. More...

## eDMA Peripheral Driver
edma_status_t | edma_init (void)
| Initializes eDMA.
edma_status_t | edma_shutdown (void)
| De-initilizes eDMA.
void | edma_register_callback (edma_channel_t *chn, edma_callback_t callback, void *para)
| Registers the callback function and a parameter. More...
edma_status_t | edma_get_descriptor_status (edma_channel_t *chn, uint32_t *descriptorStatus)
| Gets the status of the eDMA channel descriptor chain. More...
uint32_t | edma_request_channel (uint32_t channel, dma_request_source_t source, edma_channel_t *chan)
| Requests an eDMA channel. More...
edma_status_t | edma_free_channel (edma_channel_t *chn)
| Frees eDMA channel hardware and software resource. More...
edma_status_t | edma_start_channel (edma_channel_t *chn)
| Starts an eDMA channel. More...
edma_status_t | edma_stop_channel (edma_channel_t *chn)
| Stops an eDMA channel. More...
edma_status_t | edma_update_descriptor (edma_channel_t *chn)
| Updates the status of a particular descriptor in the eDMA. More...
edma_status_t | edma_config_loop (edma_software_tcd_t *stcd, edma_channel_t *chn, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, uint32_t size, uint32_t watermark, uint32_t length, uint8_t period)
| Configures the DMA transfer in a scatter-gather mode. More...
edma_status_t | edma_config_scatter_gather (edma_software_tcd_t *stcd, edma_channel_t *chn, edma_transfer_type_t type, uint32_t size, uint32_t watermark, edma_scatter_list_t *srcScatterList, edma_scatter_list_t *destScatterList, uint8_t number)
| Configures the DMA transfer in scatter-gather mode. More...
void | EDMA_IRQ_HANDLER (uint32_t channel)
| eDMA IRQ Handler More...
void | DMA_ERR_IRQHandler (uint32_t instance)
| eDMA ERROR IRQ Handler More...

### EDMA PERIPHERAL Driver

# Overview

The eDMA driver requests, configures, and uses eDMA hardware. It supports module initializations and DMA channel configurations.

# Initialization

To initialize the DMA module, call the edma_init() function. The user does not need to pass a configuration data structure. This function enables the eDMA module and clock automatically.

# Channel concept

The eDMA module has many channels. Additionally, the EDMA peripheral driver is designed based on a channel concept. All operations should be started by requesting an eDMA channel and ended by freeing an eDMA channel. The user can configure and run operations on the eDMA module by allocating a channel. If a channel is not allocated, a system error may occur.

# DMA request concept

A DMA request is used to trigger an eDMA transfer. The DMA request table is available in chip configuration chapters in each chip reference manual.

# Memory allocation and alignment

The eDMA peripheral driver does not allocate any memory dynamically. The user needs to provide the allocated memory pointer for the driver and ensure that the memory is valid. If this is not done, a system error may occur. The user needs to prepare three types of memory:

1. The handler memory: [edma_channel_t]. The driver must store the status data for each channel and the edma_channel_t is designed for this purpose.
2. The edma_software_tcd_t. The eDMA supports a TCD chain, which provides either the scatter-gather feature or the loop feature. The eDMA module loads the TCDCs from memory, where TCDs are stored. The user must provide the memory storing software TCDs and the edma_config_scatter_gather() function or the edma_config_loop() function configures the software TCDs.
3. The status memory. If the user wants to know the status of TCD chains, the user needs to provide the status memory and the driver will fill it with the chain status.
   The start address of the software TCDs must be 32 bytes.

   # Call diagram

To use the DMA driver, follow these steps:

1. Initialize the DMA module: edma_init().
2. Request a DMA channel: edma_request_channel().
3. Configure the TCD:
   - Configure the TCD chain in a scatter-gather list. UART transmit/receive is the common case.
   - Configure the TCD chain in a loop way. Audio playback/Record is the common case.
4. Register callback function: edma_register_callback.
5. Start the DMA channel: edma_start_channel.
6. [OPTION] Stop the DMA channel: edma_stop_channel.
7. Free the DMA channel: edma_free_channel.

This is an example code to initialize and configure the driver by configuring the descriptor:
edma_init();
stcd = (edma_software_tcd_t *)(((uint32_t)status + 32) & ~0x1F);
/* Prepare the memory space. */
for ( i = 0; i < kEdmaTestChainLength; i++)
{
/* Allocate the memory! */
srcAddr[i] = malloc(kEdmaTestBufferSize);
destAddr[i] = malloc(kEdmaTestBufferSize);
/* Check whether the allocation is successfully. */
if (((uint32_t)srcAddr[i] == 0x0U) & ((uint32_t)destAddr[i] == 0x0U))
{
printf("Fali to allocate memory for EDMA test! \r\n");
goto error;
}
/* Init the memory buffer. */
for (j = 0; j < kEdmaTestBufferSize; j++)
{
srcAddr[i][j] = j;
destAddr[i][j] = 0;
}
srcSG[i].address = (uint32_t)srcAddr[i];
destSG[i].address = (uint32_t)destAddr[i];
srcSG[i].length = kEdmaTestBufferSize;
destSG[i].length = kEdmaTestBufferSize;
}
if (edma_request_channel(channel, kDmaRequestMux0AlwaysOn62, &chan_handler) != channel)
{
printf("Failed to request channel %d !\r\n", channel);
goto error;
}
edma_config_scatter_gather(
stcd, &chan_handler, kDmaMemoryToMemory,
0x1U, kEdmaTestWatermarkLevel,
srcSG, destSG,
kEdmaTestChainLength);
edma_register_callback(&chan_handler, test_callback, &chan_handler);
edma_start_channel(&chan_handler);
For an example to configure the loop mode, see the SAI module driver.

# Extend the driver

The user can call the eDMA HAL driver to extend the application capability.

## Data Structure Documentation

struct edma_scatter_list_t

### Data Fields
uint32_t | address
| Address of buffer. More...
uint32_t | length
| Length of buffer. More...

#### Field Documentation

uint32_t edma_scatter_list_t::address

uint32_t edma_scatter_list_t::length

struct edma_channel_t

### Data Fields
uint8_t | module
| eDMA physical module indicator
uint8_t | channel
| eDMA physical channel indicator
uint8_t | dmamuxModule
| DMA Mux module indicator. More...
uint8_t | dmamuxChannel
| DMA Mux channel indicator. More...
edma_callback_t | callback
| Callback for the eDMA channel. More...
void * | parameter
| Parameter for the callback function. More...
volatile edma_channel_status_t | status
| Channel status. More...
uint8_t | tcdNumber
| Length of the hardware descriptor chain. More...
volatile uint8_t | tcdWrite
| Indicator for updates of the user descriptor. More...
volatile uint8_t | tcdRead
| Indicator for the consuming of the DMA controller. More...
uint32_t | tcdLeftBytes
| Left bytes to be transferred for a current TCD. More...
volatile bool | tcdUnderflow
         Flag indicating whether the user failed to feed a descriptor in
time. More...

#### Field Documentation

uint8_t edma_channel_t::dmamuxModule

uint8_t edma_channel_t::dmamuxChannel

edma_callback_t edma_channel_t::callback

void* edma_channel_t::parameter

volatile edma_channel_status_t edma_channel_t::status

uint8_t edma_channel_t::tcdNumber

volatile uint8_t edma_channel_t::tcdWrite

volatile uint8_t edma_channel_t::tcdRead

uint32_t edma_channel_t::tcdLeftBytes

volatile bool edma_channel_t::tcdUnderflow

## Typedef Documentation

typedef void(* edma_callback_t)(void *parameter, edma_channel_status_t status)

Prototype for the callback function registered in the DMA driver.

## Enumeration Type Documentation

enum edma_descriptor_internal_status_t

Defines the status of the DMA descriptor. The status of the descriptor is not limited to these two states. It can also be any the value between 0~0xFFFFFFFF for left bytes of a specified descriptor.

Enumerator
kEdmaDescriptorDone | The descriptor is finished.
kEdmaDescriptorPrepared | The descriptor is either consumed or not consumed.

enum edma_tcd_alignment_t

Enumerator
kEdmaTcdAlignment | Alignment of the eDMA TCD.
kEdmaTcdAlignmentMask | Alignment mask of the eDMA TCD.

enum edma_channel_type_t

A structure used for the dma_request_channel.

Enumerator
kEdmaInvalidChannel | Macros indicate the failure of the channel request.
kEdmaAnyChannel | Macros used when requesting channel. kEdmaAnyChannel means a request of a dynamic channel allocation.

enum edma_channel_status_t

A structure describing the DMA channel status. The user can get the status from the channel callback function.

Enumerator
kEdmaIdle | DMA channel is idle.
kEdmaNormal | DMA channel is occupied.
kEdmaError | An error occurs in the DMA channel.

enum edma_transfer_type_t

Enumerator
kEdmaPeripheralToMemory | Transfer from peripheral to memory.
kEdmaMemoryToPeripheral | Transfer from memory to peripheral.
kEdmaMemoryToMemory | Transfer from memory to memory.
kEdmaPeripheralToPeripheral | Transfer from peripheral to peripheral.

## Function Documentation

void edma_register_callback | ( | edma_channel_t * | chn,
|  | edma_callback_t | callback,
|  | void * | para
| ) |  |

The user register callback function and parameter for a specified eDMA channel. When channel interrupt or channel error occurs, the callback function is called and a parameter along with user parameter is provided to indicate the channel status.

Parameters

  chn | Handler for eDMA channel.
  callback | Callback function.
  para | A parameter for callback functions.

edma_status_t edma_get_descriptor_status | ( | edma_channel_t * | chn,
|  | uint32_t * | descriptorStatus
| ) |  |

This function indicates the status of descriptor chains. The user needs to provide the memory space to store the descriptor status. A parameter descriptorStatus is the pointer for the descriptorStatus. If the descriptorStaus can't point to a valid memory space and the length of the memory is not enough to store the descriptor status, an error occurs inside the DMA driver. Every descriptor needs a uint32_t to store the status. If the return descriptorStatus[n] is equal to the kEdmaDescriptorPrepared, the descriptor is either consuming or it is already prepared but not consumed. Any other value indicates the left bytes to be transferred for this descriptor. If the value is equal to 0, it means the descriptor is already finished. The user can update the memory for this descriptor safely. To get a precise status of the descriptor, the user can first stop the channel. The ongoing descriptor is updated with a value indicating bytes to be transferred for this descriptor. If not, it indicates that this descriptor is ongoing with a value of kEdmaDescriptorPrepared.

Parameters

  chn | Handler for eDMA channel.
  descriptorStatus | Status of descriptors.

uint32_t edma_request_channel | ( | uint32_t | channel,
|  | dma_request_source_t | source,
|  | edma_channel_t * | chan
| ) |  |

This function provides two ways to allocate a DMA channel: static allocation and dynamic allocation. To allocate a channel dynamically, the user should set the channel parameter with the value of kDmaAnyChannel. The driver searches all available channels and assigns the first channel to the user. To allocate the channel statically, the user should set the channel parameter with the value of a specified channel. If the channel is available, the driver assigns the channel to the user. Note that the user must provide the handler memory for the DMA channel. The driver initializes the handler and configures the handler memory.

Parameters

  channel | eDMA channel number. If a channel is assigned with a valid channel number, the DMA driver tries to assign a specified channel to the user. If a channel is assigned with a kDmaAnyChannel, the DMA driver searches all available channels and assigns the first channel to the user.
  source | eDMA hardware request.
  chan | Memory pointing to eDMA channel. The user must ensure that the handler memory is valid and that it will not be released or changed by another code before the channel is freed.

Returns
  If the channel allocation is successful, the return value indicates the requested channel. If not, the driver returns a kDmaInvalidChannel value to indicate that the requested operation has failed.

edma_status_t edma_free_channel | ( | edma_channel_t * | chn | ) |

This function frees the relevant software and hardware resources. The request and the freeing operation need to be called in a pair.

Parameters

  chn | Memory pointing to the eDMA channel

edma_status_t edma_start_channel | ( | edma_channel_t * | chn | ) |

Starts an eDMA channel. The driver starts an eDMA channel by enabling the DMA request. The software start bit is not used in the eDMA peripheral driver.

Parameters

  chn | Memory pointing to the eDMA channel.

edma_status_t edma_stop_channel | ( | edma_channel_t * | chn | ) |

This function stops an eDMA channel and updates the descriptor chain status. By calling the edma_get_descriptor_status() function, the ongoing left bytes of the descriptor are updated and the user can simultaneously get the status of all descriptors.

Parameters

  chn | Memory pointing to the eDMA channel

edma_status_t edma_update_descriptor | ( | edma_channel_t * | chn | ) |

This function is designed for the loop descriptor chain. When descriptor is chained in loop mode, the DMA constantly consumes descriptors. At the same time, the user may need to update the content belonging to a consumed descriptor. This function is used to update the descriptor state from "CONSUMED" to "TO BE CONSUMED". In this case, the DMA driver can work out whether the underflow happens on the loop descriptor chain. This function can only update descriptors one-by-one in a sequence but not a specified descriptor.

Parameters

  chn | Memory pointing to the eDMA channel

edma_status_t edma_config_loop | ( | edma_software_tcd_t * | stcd,
|  | edma_channel_t * | chn,
|  | edma_transfer_type_t | type,
|  | uint32_t | srcAddr,
|  | uint32_t | destAddr,
|  | uint32_t | size,
|  | uint32_t | watermark,
|  | uint32_t | length,
|  | uint8_t | period
| ) |  |

This function configures descriptors in a loop chain. The user passes a block of memory into this function. The memory is divided into "period" sub blocks. The DMA driver configures "period" descriptors. Each descriptor stands for a sub block. The DMA driver transfers data from the 1st descriptor to the last descriptor. Then, the DMA driver wraps to the first descriptor to continue the loop. The interrupt handler is called on every finish of a descriptor. The user can find out whether a descriptor is in the process of being transferred, is already transferred, or to be transferred by calling the edma_get_descriptor_status() function in the interrupt handler or any other task context. At the same time, the user can call the edma_update_descriptor() function to tell the DMA driver that the content belonging to a descriptor is already updated and the DMA needs to count it as and underflow next time it loops to this descriptor.

Parameters

  chn | Memory pointing to the eDMA channel
  stcd | Memory pointing to software TCDs. The user must prepare this memory block. The required memory size is equal to a "period" * size of(edma_software_tcd_t). At the same time, the "stcd" must align with 32 bytes. If not, an error occurs in the eDMA driver.
  srcAddr | A source register address or a start memory address.
  destAddr | A destination register address or a start memory address.
  size | Size to be transferred on every DMA write/read. Source/Dest share the same write/read size.
  watermark | size write/read for every trigger of the DMA request.
  length | Total length of Memory. A number of the descriptor that is configured for this transfer configuration.

edma_status_t edma_config_scatter_gather | ( | edma_software_tcd_t * | stcd,
|  | edma_channel_t * | chn,
|  | edma_transfer_type_t | type,
|  | uint32_t | size,
|  | uint32_t | watermark,
|  | edma_scatter_list_t * | srcScatterList,
|  | edma_scatter_list_t * | destScatterList,
|  | uint8_t | number
| ) |  |

This function configure descriptors into sing-end chain. User passed blocks of memory into this function. Interrupt will only be triggered on the last memory block is finished. The information of memory blocks are passed by edma_scatter_list_t data structure which can tell the memory address and length. DMA driver will configure descriptor for every memory block and transfer descriptor from the first one to the last one and then stop.

Parameters

  chn | Memory pointing to eDMA channel.
  stcd | Memory pointing to software TCDs. The user must prepare this memory block. The required memory size is equal to the "number" * size of(edma_software_tcd_t). At the same time, the "stcd" must align with 32 bytes. If not, an error occurs in the eDMA driver.
  type | Transfer type.
  srcScatterList | Data structure storing the address and length to be transferred for source memory blocks. If source memory is peripheral, the length is not used.
  destScatterList | Data structure storing the address and length to be transferred for dest memory blocks. If in the memory-to-memory transfer mode, the user must ensure that the length of the dest scatter gather list is equal to the source scatter gather list. If the dest memory is a peripheral register, the length is not used.
  size | Size to be transferred on each DMA write/read. Source/Dest share the same write/read size.
  watermark | Size write/read for each trigger of the DMA request. number A number of memory block contained in the scatter gather list.

void EDMA_IRQ_HANDLER | ( | uint32_t | channel | ) |

void DMA_ERR_IRQHandler | ( | uint32_t | instance | ) |