19.8.5.1.3 Workflow
- Create a module software instance structure for the SPI module to store the SPI driver state while it is in use.
struct
spi_module spi_master_instance;
struct
spi_module spi_slave_instance;
Note: This should never go out of scope as long as the module is in use. In most cases, this should be global. - Create a module software instance structure for DMA resource to store the DMA resource state while it is in use.
struct
dma_resource example_resource_tx;
struct
dma_resource example_resource_rx;
Note: This should never go out of scope as long as the module is in use. In most cases, this should be global. - Create transfer done flag to indication DMA transfer done.
static
volatile
bool
transfer_tx_is_done =
false
;
static
volatile
bool
transfer_rx_is_done =
false
;
- Define the buffer length for TX/RX.
#define BUF_LENGTH 20
- Create buffer to store the data to be transferred.
static
const
uint8_t buffer_tx[BUF_LENGTH] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
};
static
uint8_t buffer_rx[BUF_LENGTH];
- Create the SPI module configuration struct, which can be filled out to adjust the configuration of a physical SPI peripheral.
struct
spi_config config_spi_master;
struct
spi_config config_spi_slave;
- Initialize the SPI configuration struct with the module's default values.
spi_get_config_defaults(&config_spi_master);
spi_get_config_defaults(&config_spi_slave);
Note: This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings. - Alter the SPI settings to configure the physical pinout, baudrate, and other relevant parameters.
config_spi_master.mux_setting = CONF_MASTER_MUX_SETTING;
config_spi_slave.mux_setting = CONF_SLAVE_MUX_SETTING;
- Configure the SPI module with the desired settings, retrying while the driver is busy until the configuration is stressfully set.
spi_init(&spi_master_instance, CONF_MASTER_SPI_MODULE, &config_spi_master);
spi_init(&spi_slave_instance, CONF_SLAVE_SPI_MODULE, &config_spi_slave);
- Enable the SPI module.
spi_enable(&spi_master_instance);
spi_enable(&spi_slave_instance);
- Create the DMA resource configuration structure, which can be filled out to adjust the configuration of a single DMA transfer.
struct
dma_resource_config tx_config;
struct
dma_resource_config rx_config;
- Initialize the DMA resource configuration struct with the module's default values.
dma_get_config_defaults(&tx_config);
dma_get_config_defaults(&rx_config);
Note: This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings. - Set extra configurations for the DMA resource. It is using peripheral trigger. SERCOM TX empty and RX complete trigger causes a beat transfer in this example.
tx_config.peripheral_trigger = CONF_PERIPHERAL_TRIGGER_TX;
tx_config.trigger_action = DMA_TRIGGER_ACTON_BEAT;
rx_config.peripheral_trigger = CONF_PERIPHERAL_TRIGGER_RX;
rx_config.trigger_action = DMA_TRIGGER_ACTON_BEAT;
- Allocate a DMA resource with the configurations.
dma_allocate(tx_resource, &tx_config);
dma_allocate(rx_resource, &rx_config);
- Create a DMA transfer descriptor configuration structure, which can be filled out to adjust the configuration of a single DMA transfer.
struct
dma_descriptor_config tx_descriptor_config;
struct
dma_descriptor_config rx_descriptor_config;
- Initialize the DMA transfer descriptor configuration struct with the module's default values.
dma_descriptor_get_config_defaults(&tx_descriptor_config);
dma_descriptor_get_config_defaults(&rx_descriptor_config);
Note: This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings. - Set the specific parameters for a DMA transfer with transfer size, source address, and destination address.
tx_descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE;
tx_descriptor_config.dst_increment_enable =
false
;
tx_descriptor_config.block_transfer_count =
sizeof
(buffer_tx)/
sizeof
(uint8_t);
tx_descriptor_config.source_address = (uint32_t)buffer_tx +
sizeof
(buffer_tx);
tx_descriptor_config.destination_address =
(uint32_t)(&spi_master_instance.hw->SPI.DATA.reg);
rx_descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE;
rx_descriptor_config.src_increment_enable =
false
;
rx_descriptor_config.block_transfer_count =
sizeof
(buffer_rx)/
sizeof
(uint8_t);
rx_descriptor_config.source_address =
(uint32_t)(&spi_slave_instance.hw->SPI.DATA.reg);
rx_descriptor_config.destination_address =
(uint32_t)buffer_rx +
sizeof
(buffer_rx);
- Create the DMA transfer descriptor.
dma_descriptor_create(tx_descriptor, &tx_descriptor_config);
dma_descriptor_create(rx_descriptor, &rx_descriptor_config);