Astra MCU SDK Peripheral Driver Library
 
Loading...
Searching...
No Matches

Topics

 Type Definitions
 Type Definition for DMA driver.
 
 Enumerated Types
 Enumerated types for DMA driver.
 
 Data Structures
 Data Structures for DMA driver.
 
 Functions
 Functions for DMA driver.
 
 Command Linking Support
 Command Linking Support for DMA driver.
 
 Template Configuration
 Template Configurations for DMA driver.
 

Detailed Description

Driver API for ARM CoreLink DMA Controller.

The DMA is a high-performance Direct Memory Access controller that supports multiple independent channels with advanced features including 2D transfers, hardware triggering, and scatter-gather operations.

Features:

Note
DMA APIs are divided into two categories:
Warning
Mixing high-level and low-level DMA APIs for the same channel is not recommended. Each has different expectations for channel state and resource management. Use only one model per channel to avoid undefined behavior.

Configuration Considerations

To initialize and use the DMA driver:

  1. Call dma_init to initialize the DMA controller instance.
  2. Request a channel using dma_channel_request or dma_request_specific_channel.
  3. Configure the transfer using dma_prepare_transfer. For more complex scatter-gather operations, create and link descriptors using dma_create_descriptor and dma_link_descriptors.
  4. Start the transfer using dma_start_transfer or dma_start_descriptor_chain.
  5. Monitor the transfer status using dma_get_status or by providing a callback in the channel configuration.
  6. Once the transfer is complete, release the channel using dma_free_channel.

dma_init

Initialize the DMA hardware and internal driver structures for the specified DMA instance.

rc = dma_init(DMA_0);
if (rc != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Init failed.\n");
}

dma_deinit

Deinitializes the DMA hardware and releases any resources held by the driver for the specified DMA instance.

rc = dma_deinit(DMA_0);
if (rc != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "De-init failed.\n");
}

dma_prepare_transfer

Configures a DMA channel for a specific transfer type. This includes setting source and destination addresses, transfer size, and other parameters.

/* Configure the DMA channel for a 1D memory-to-memory transfer */
dma_channel_config_t config_1d = {
.config_1d = {
.x_type = DMA_OP_CONTINUE,
.src_addr = (uint32_t)dma_src_buf,
.dest_addr = (uint32_t)dma_dest_buf,
.transfer_size = DMA_TRANSFER_SIZE,
.unit_size = DMA_UNIT_SIZE_4BYTES,
.src_burst_size = DMA_BURST_SIZE_4,
.dest_burst_size = DMA_BURST_SIZE_4,
.src_x_increment = 1,
.dest_x_increment = 1,
.fill_value = 0,
.template_config = { 0 },
.link_addr = 0
},
.priority = 0,
.src_security = DMA_SECURITY_SECURE,
.dest_security = DMA_SECURITY_SECURE,
.src_privilege = DMA_PRIVILEGE_PRIVILEGED,
.dest_privilege = DMA_PRIVILEGE_PRIVILEGED,
.src_trigger = { 0 },
.dest_trigger = { 0 },
.auto_restart.infinite_restart = 0,
.reg_reload_type = DMA_REG_RELOAD_DISABLED,
.callback = dma_transfer_callback,
.user_data = NULL
};
/* Prepare the channel for the transfer */
rc = dma_prepare_transfer(instance, channel, &config_1d);
if (rc != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Transfer preparation failed.\n");
}

dma_start_transfer

Initiates a DMA transfer on a pre-configured channel. This is a non-blocking call, and the transfer completion can be monitored via interrupts or polling.

rc = dma_enable_ints(instance, channel, (uint32_t)DMA_INT_DONE);
if (rc != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Enable interrupts failed.\n");
}
/* Start the transfer */
rc = dma_start_transfer(instance, channel);
if (rc != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Transfer start failed.\n");
}

dma_create_descriptor

Creates a DMA descriptor for use in scatter-gather operations. The descriptor contains the configuration for a single DMA transfer.

/* Configure channel for 1D transfer */
dma_channel_config_t config_1d = {
.config_1d = {
.x_type = DMA_OP_CONTINUE,
.src_addr = (uint32_t)dma_src_buf,
.dest_addr = (uint32_t)dma_dest_buf,
.transfer_size = DMA_TRANSFER_SIZE,
.unit_size = DMA_UNIT_SIZE_4BYTES,
.src_burst_size = DMA_BURST_SIZE_4,
.dest_burst_size = DMA_BURST_SIZE_4,
.src_x_increment = 1,
.dest_x_increment = 1,
.fill_value = 0,
.template_config = { 0 },
.link_addr = 0
},
.priority = 0,
.src_security = DMA_SECURITY_SECURE,
.dest_security = DMA_SECURITY_SECURE,
.src_privilege = DMA_PRIVILEGE_PRIVILEGED,
.dest_privilege = DMA_PRIVILEGE_PRIVILEGED,
.src_trigger = { 0 },
.dest_trigger = { 0 },
.auto_restart.infinite_restart = 0,
.reg_reload_type = DMA_REG_RELOAD_DISABLED,
.callback = NULL,
.user_data = NULL
};
/* Create descriptor */
rc = dma_create_descriptor(instance, channel, &descriptor_config, &desc1);
if (rc != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Descriptor creation failed.\n");
}
/* Configure channel for 2D transfer */
dma_channel_config_t config_2d = {
.config_2d = {
.x_type = DMA_OP_CONTINUE,
.y_type = DMA_OP_CONTINUE,
.src_addr = (uint32_t)dma_src_2d_buf,
.dest_addr = (uint32_t)dma_dest_2d_buf,
.src_x_size = COLS,
.dest_x_size = COLS,
.src_y_size = ROWS,
.dest_y_size = ROWS,
.unit_size = DMA_UNIT_SIZE_4BYTES,
.src_burst_size = DMA_BURST_SIZE_4,
.dest_burst_size = DMA_BURST_SIZE_4,
.src_x_increment = 1,
.dest_x_increment = 1,
.src_y_stride = COLS,
.dest_y_stride = COLS,
.fill_value = 0,
.link_addr = 0
},
.priority = 0,
.src_security = DMA_SECURITY_SECURE,
.dest_security = DMA_SECURITY_SECURE,
.src_privilege = DMA_PRIVILEGE_PRIVILEGED,
.dest_privilege = DMA_PRIVILEGE_PRIVILEGED,
.src_trigger = { 0 },
.dest_trigger = { 0 },
.auto_restart.infinite_restart = 0,
.reg_reload_type = DMA_REG_RELOAD_DISABLED,
.callback = NULL,
.user_data = NULL
};
if ((rc = dma_create_descriptor(DMA_0, channel, &config_2d, &desc2)) != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Descriptor 2 creation failed.\n");
return rc;
}

dma_link_descriptors

Link the two created descriptors. Once the first descriptor is done execting, the descriptor 2 is fetched and run using the Linkaddr.

/* Link descriptors */
if ((rc = dma_link_descriptors(desc1, desc2)) != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Failed to link descriptor 1 -> 2.\n");
return rc;
}

dma_start_descriptor_chain

Starts execution of the descriptor chain by starting the first descriptor in the chain.

/* Start chain */
if ((rc = dma_start_descriptor_chain(DMA_0, channel, &desc1)) != DMA_OK) {
LOG_ERROR(LOG_MOD_DMA, "Failed to start descriptor chain.\n");
return rc;
}