Microchip® Advanced Software Framework

Use case #2

In this use case, the CRC module is configured for:

  • Performing CRC on data passing through a DMA channel
  • Using CRC-16

This use case shows how to calculate the checksum for data passing through a DMA channel.

Setup steps

Prerequisites

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

  1. PMIC driver for interrupt handling
  2. DMA driver for enabling DMA transaction
  3. The common Clock service.
  4. A callback function for DMA transfer complete must be provided by the user:
    static void callback_dma_transfer_done(enum dma_channel_status status)
    {
    uint32_t checksum;
    checksum = crc_dma_checksum_stop();
    }
  5. A static uint8_t array of data with at least DMA_BUFFER_SIZE entries to perform CRC on.

Example code

Some defines and data buffers must be set up:

#define DMA_CHANNEL 0
#define DMA_BUFFER_SIZE 8
static uint8_t source[DMA_BUFFER_SIZE];
static uint8_t destination[DMA_BUFFER_SIZE];

Add to application initialization:

Workflow

  1. Initialize system clock:

Usage steps

Example code

struct dma_channel_config config;
uint32_t checksum;
crc_dma_checksum_start(DMA_CHANNEL, CRC_16BIT);
dma_enable();
dma_set_callback(DMA_CHANNEL, callback_dma_transfer_done);
memset(&config, 0, sizeof(config));
dma_channel_set_interrupt_level(&config, PMIC_LVL_LOW);
dma_channel_set_burst_length(&config, DMA_CH_BURSTLEN_1BYTE_gc);
dma_channel_set_transfer_count(&config, DMA_BUFFER_SIZE);
dma_channel_set_src_reload_mode(&config,
DMA_CH_SRCRELOAD_TRANSACTION_gc);
dma_channel_set_dest_reload_mode(&config,
DMA_CH_DESTRELOAD_TRANSACTION_gc);
dma_channel_set_src_dir_mode(&config, DMA_CH_SRCDIR_INC_gc);
dma_channel_set_dest_dir_mode(&config, DMA_CH_DESTDIR_INC_gc);
dma_channel_set_source_address(&config, (uint16_t)(uintptr_t)source);
dma_channel_set_destination_address(&config,
(uint16_t)(uintptr_t)destination);
dma_channel_write_config(DMA_CHANNEL, &config);
dma_channel_enable(DMA_CHANNEL);
dma_channel_trigger_block_transfer(DMA_CHANNEL);
while (true) {
}

Workflow

  1. Enable the CRC module for DMA
    • crc_dma_checksum_start(DMA_CHANNEL, CRC_16BIT);
  2. Enable DMA
    • dma_enable();
  3. Set callback function for DMA completion
    • dma_set_callback(DMA_CHANNEL, callback_dma_transfer_done);
  4. Make sure config is all zeroed out so we don't get any stray bits
    • memset(&config, 0, sizeof(config));
  5. Configure the DMA channel with the following settings:
    • Low interrupt priority
    • 1 byte burst length
    • DMA_BUFFER_SIZE bytes for each transfer
    • Reload source and destination address at end of each transfer
    • Increment source and destination address during transfer
    • Source address is set to source buffer
    • Destination address is set to destination buffer
      • dma_channel_set_interrupt_level(&config, PMIC_LVL_LOW);
        dma_channel_set_burst_length(&config, DMA_CH_BURSTLEN_1BYTE_gc);
        dma_channel_set_transfer_count(&config, DMA_BUFFER_SIZE);
        dma_channel_set_src_reload_mode(&config,
        DMA_CH_SRCRELOAD_TRANSACTION_gc);
        dma_channel_set_dest_reload_mode(&config,
        DMA_CH_DESTRELOAD_TRANSACTION_gc);
        dma_channel_set_src_dir_mode(&config, DMA_CH_SRCDIR_INC_gc);
        dma_channel_set_dest_dir_mode(&config, DMA_CH_DESTDIR_INC_gc);
        dma_channel_set_source_address(&config, (uint16_t)(uintptr_t)source);
        dma_channel_set_destination_address(&config,
        (uint16_t)(uintptr_t)destination);
        dma_channel_write_config(DMA_CHANNEL, &config);
  6. Use the configuration above by enabling the DMA channel in use.
    • dma_channel_enable(DMA_CHANNEL);
  7. Enable interrupts
  8. Trigger the DMA transfer
    • dma_channel_trigger_block_transfer(DMA_CHANNEL);
  9. Do nothing while waiting for DMA transfer to complete
    • while (true) {
      }