Microchip® Advanced Software Framework

Quick start guide for the XMEGA DMA driver

This is the quick start guide for the DMA driver, with step-by-step instructions on how to configure and use the driver in a selection of use cases.

The use cases contain several code fragments. The code fragments in the steps for setup can be copied into a custom initialization function, while the steps for usage can be copied into, e.g., the main application function.

Advanced use cases

For more advanced use of the DMA driver, see the following use cases:

Basic use case

In this basic use case, the DMA is configured for:

  • Burst length: 1 byte
  • Transfer count: 1024
  • Source: Buffer located in RAM
  • Destination: Buffer located in RAM
  • Source and destination address reload mode: End of transaction
  • Source and destination address direction mode: Increment

In this use case data is copied from the source buffer to the destination buffer in 1-byte bursts, until all data in the block is transferred. This example is analogus to a memcpy(destination, source, sizeof(source)) operation performed in hardware asynchronously to the CPU.

Setup steps

Prerequisites

For the setup code of this use case to work, the following must be added to the project:

  1. System Clock Manager Service (sysclk)

Example code

Add to application C-file:

#define DMA_CHANNEL 0
#define DMA_BUFFER_SIZE 1024
static uint8_t source[DMA_BUFFER_SIZE];
static uint8_t destination[DMA_BUFFER_SIZE];
static void dma_init(void)
{
struct dma_channel_config dmach_conf;
memset(&dmach_conf, 0, sizeof(dmach_conf));
dma_channel_set_burst_length(&dmach_conf, DMA_CH_BURSTLEN_1BYTE_gc);
DMA_CH_SRCRELOAD_TRANSACTION_gc);
DMA_CH_DESTRELOAD_TRANSACTION_gc);
dma_channel_set_src_dir_mode(&dmach_conf, DMA_CH_SRCDIR_INC_gc);
(uint16_t)(uintptr_t)source);
dma_channel_set_dest_dir_mode(&dmach_conf, DMA_CH_DESTDIR_INC_gc);
(uint16_t)(uintptr_t)destination);
}

Add to main():

dma_init();

Workflow

  1. Define the DMA channel that will be used for the transfer for convenience:
    • #define DMA_CHANNEL 0
  2. Define the array length that will be the used for the source and destination buffers located in RAM:
    • #define DMA_BUFFER_SIZE 1024
  3. Create a pair of global arrays that will hold the source and destination data copied by the DMA controller channel when it is triggered:
  4. Create a function dma_init() to intialize the DMA:
    • static void dma_init(void)
      {
      // ...
      }
  5. Create config struct for DMA channel:
  6. Make sure the configuration structure is zeroed out to ensure that all values are reset to their defaults before writing new values:
    • memset(&dmach_conf, 0, sizeof(dmach_conf));
  7. Configure the DMA channel for single byte bursts, with a transfer length equal to the size of the source and destination buffers:
  8. Configure the DMA channel to reset the source and destination addresses at the end of the complete transaction (i.e. after DMA_BUFFER_SIZE bytes copied):
  9. Configure the DMA channel to increment the source and destination addresses after each byte transferred:
  10. Configure the DMA channel source and destination addresses:
  11. Enable the DMA module so that channels can be configured in it:
    • Attention
      Calling dma_enable() will result in a soft-reset of the entire DMA module, clearing all channel configurations. If more than one DMA channel is to be configured, this function should be called only once in the application initialization procedure only.
  12. Write the DMA channel configuration to the DMA and enable it so that it can be triggered to start the transfer:
  13. Initialize the clock system:
  14. Call our DMA init function:
    • dma_init();

Usage steps

Example code

Add to, e.g., main loop in application C-file:

Workflow

  1. Start the DMA transfer:
  2. Wait for the transfer to complete: