16.8.3.1.2 Code

Add to the main application source file, outside of any functions:
struct usart_module usart_instance;
struct dma_resource usart_dma_resource_rx;
struct dma_resource usart_dma_resource_tx;
#define BUFFER_LEN    8
static uint16_t string[BUFFER_LEN];
COMPILER_ALIGNED(16)
DmacDescriptor example_descriptor_rx;
DmacDescriptor example_descriptor_tx;
Copy-paste the following setup code to your user application:
static void transfer_done_rx(struct dma_resource* const resource )
{
    dma_start_transfer_job(&usart_dma_resource_tx);
}

static void transfer_done_tx(struct dma_resource* const resource )
{
    dma_start_transfer_job(&usart_dma_resource_rx);
}

static void configure_dma_resource_rx(struct dma_resource *resource)
{
    struct dma_resource_config config;

    dma_get_config_defaults(&config);

    config.peripheral_trigger = EDBG_CDC_SERCOM_DMAC_ID_RX;
    config.trigger_action = DMA_TRIGGER_ACTON_BEAT;

    dma_allocate(resource, &config);
}

static void setup_transfer_descriptor_rx(DmacDescriptor *descriptor)
{
    struct dma_descriptor_config descriptor_config;

    dma_descriptor_get_config_defaults(&descriptor_config);

    descriptor_config.beat_size = DMA_BEAT_SIZE_HWORD;
    descriptor_config.src_increment_enable = false;
    descriptor_config.block_transfer_count = BUFFER_LEN;
    descriptor_config.destination_address =
            (uint32_t)string + sizeof(string);
    descriptor_config.source_address =
            (uint32_t)(&usart_instance.hw->USART.DATA.reg);

    dma_descriptor_create(descriptor, &descriptor_config);
}

static void configure_dma_resource_tx(struct dma_resource *resource)
{
    struct dma_resource_config config;

    dma_get_config_defaults(&config);

    config.peripheral_trigger = EDBG_CDC_SERCOM_DMAC_ID_TX;
    config.trigger_action = DMA_TRIGGER_ACTON_BEAT;

    dma_allocate(resource, &config);
}

static void setup_transfer_descriptor_tx(DmacDescriptor *descriptor)
{
    struct dma_descriptor_config descriptor_config;

    dma_descriptor_get_config_defaults(&descriptor_config);

    descriptor_config.beat_size = DMA_BEAT_SIZE_HWORD;
    descriptor_config.dst_increment_enable = false;
    descriptor_config.block_transfer_count = BUFFER_LEN;
    descriptor_config.source_address = (uint32_t)string + sizeof(string);
    descriptor_config.destination_address =
        (uint32_t)(&usart_instance.hw->USART.DATA.reg);

    dma_descriptor_create(descriptor, &descriptor_config);
}

static void configure_usart(void)
{
    struct usart_config config_usart;
    usart_get_config_defaults(&config_usart);

    config_usart.baudrate    = 9600;
    config_usart.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
    config_usart.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
    config_usart.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
    config_usart.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
    config_usart.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;

    while (usart_init(&usart_instance,
            EDBG_CDC_MODULE, &config_usart) != STATUS_OK) {
    }

    usart_enable(&usart_instance);
}
Add to user application initialization (typically the start of main()):
configure_usart();

configure_dma_resource_rx(&usart_dma_resource_rx);
configure_dma_resource_tx(&usart_dma_resource_tx);

setup_transfer_descriptor_rx(&example_descriptor_rx);
setup_transfer_descriptor_tx(&example_descriptor_tx);

dma_add_descriptor(&usart_dma_resource_rx, &example_descriptor_rx);
dma_add_descriptor(&usart_dma_resource_tx, &example_descriptor_tx);

dma_register_callback(&usart_dma_resource_rx, transfer_done_rx,
        DMA_CALLBACK_TRANSFER_DONE);
dma_register_callback(&usart_dma_resource_tx, transfer_done_tx,
        DMA_CALLBACK_TRANSFER_DONE);

dma_enable_callback(&usart_dma_resource_rx,
        DMA_CALLBACK_TRANSFER_DONE);
dma_enable_callback(&usart_dma_resource_tx,
        DMA_CALLBACK_TRANSFER_DONE);