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:
- PMIC driver for interrupt handling
- DMA driver for enabling DMA transaction
- The common Clock service.
- 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;
}
- 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
- 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
- Enable the CRC module for DMA
crc_dma_checksum_start(DMA_CHANNEL,
CRC_16BIT);
- Enable DMA
- Set callback function for DMA completion
dma_set_callback(DMA_CHANNEL, callback_dma_transfer_done);
- Make sure config is all zeroed out so we don't get any stray bits
memset(&config, 0, sizeof(config));
- 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);
- Use the configuration above by enabling the DMA channel in use.
dma_channel_enable(DMA_CHANNEL);
- Enable interrupts
- Trigger the DMA transfer
dma_channel_trigger_block_transfer(DMA_CHANNEL);
- Do nothing while waiting for DMA transfer to complete