Skip to content

Commit

Permalink
drivers: dma: esp32: added support for multiple descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
epc-ake committed Jun 25, 2024
1 parent da9b308 commit 76e1dae
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 34 deletions.
6 changes: 6 additions & 0 deletions drivers/dma/Kconfig.esp32
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ config DMA_ESP32
default y
help
General Purpose DMA for ESP32 series.

config DMA_ESP32_DESCRIPTOR_NUM
int "Number of DMA descriptors to allocate"
default 16
help
Number of DMA descriptors to allocate.
110 changes: 76 additions & 34 deletions drivers/dma/dma_esp32_gdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct dma_esp32_channel {
int periph_id;
dma_callback_t cb;
void *user_data;
dma_descriptor_t desc;
dma_descriptor_t desc_list[CONFIG_DMA_ESP32_DESCRIPTOR_NUM];
#if defined(CONFIG_SOC_SERIES_ESP32S3)
struct intr_handle_data_t *intr_handle;
#endif
Expand Down Expand Up @@ -159,15 +159,42 @@ static int dma_esp32_disable_interrupt(const struct device *dev,
static int dma_esp32_config_rx_descriptor(struct dma_esp32_channel *dma_channel,
struct dma_block_config *block)
{
dma_descriptor_t* desc_iter = dma_channel->desc_list;

Check failure on line 162 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

POINTER_LOCATION

drivers/dma/dma_esp32_gdma.c:162 "foo* bar" should be "foo *bar"
// Check if the buffer is in DMA capable memory

Check failure on line 163 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

C99_COMMENTS

drivers/dma/dma_esp32_gdma.c:163 do not use C99 // comments
if (!esp_ptr_dma_capable((uint32_t *)block->dest_address)) {
LOG_ERR("Rx buffer not in DMA capable memory: %p", (uint32_t *)block->dest_address);
return -EINVAL;
}

memset(&dma_channel->desc, 0, sizeof(dma_channel->desc));
dma_channel->desc.buffer = (void *)block->dest_address;
dma_channel->desc.dw0.size = block->block_size;
dma_channel->desc.dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
if(!block) {

Check failure on line 169 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:169 space required before the open parenthesis '('
LOG_ERR("At least one dma block is required");
return -EINVAL;
}


for(int i=0; i < CONFIG_DMA_ESP32_DESCRIPTOR_NUM; ++i){

Check failure on line 175 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:175 spaces required around that '=' (ctx:VxV)

Check failure on line 175 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:175 space required before the open brace '{'

Check failure on line 175 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:175 space required before the open parenthesis '('
if(block->block_size > DMA_DESCRIPTOR_BUFFER_MAX_SIZE) {

Check failure on line 176 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:176 space required before the open parenthesis '('
LOG_ERR("Size of block %d is too large", i);
return -EINVAL;
}
memset(desc_iter, 0, sizeof(dma_descriptor_t));
desc_iter->buffer = (void*)block->dest_address;

Check failure on line 181 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

POINTER_LOCATION

drivers/dma/dma_esp32_gdma.c:181 "(foo*)" should be "(foo *)"
desc_iter->dw0.size = block->block_size;
desc_iter->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
if(!block->next_block) {

Check failure on line 184 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:184 space required before the open parenthesis '('
desc_iter->next = NULL;
break;
}
desc_iter->next = desc_iter + 1;
desc_iter += 1;
block = block->next_block;
}

if(desc_iter->next) {

Check failure on line 193 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

drivers/dma/dma_esp32_gdma.c:193 space required before the open parenthesis '('
memset(dma_channel->desc_list, 0, sizeof(dma_descriptor_t) * CONFIG_DMA_ESP32_DESCRIPTOR_NUM);

Check warning on line 194 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/dma/dma_esp32_gdma.c:194 line length of 110 exceeds 100 columns
LOG_ERR("Too many dma blocks. Increase CONFIG_DMA_ESP32_DESCRIPTOR_NUM");
return -EINVAL;
}

return 0;
}
Expand Down Expand Up @@ -213,18 +240,43 @@ static int dma_esp32_config_rx(const struct device *dev, struct dma_esp32_channe
static int dma_esp32_config_tx_descriptor(struct dma_esp32_channel *dma_channel,
struct dma_block_config *block)
{
dma_descriptor_t* desc_iter = dma_channel->desc_list;
if (!esp_ptr_dma_capable((uint32_t *)block->source_address)) {
LOG_ERR("Tx buffer not in DMA capable memory: %p",
(uint32_t *)block->source_address);
return -EINVAL;
}

memset(&dma_channel->desc, 0, sizeof(dma_channel->desc));
dma_channel->desc.buffer = (void *)block->source_address;
dma_channel->desc.dw0.size = block->block_size;
dma_channel->desc.dw0.length = block->block_size;
dma_channel->desc.dw0.suc_eof = 1;
dma_channel->desc.dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
if(!block) {
LOG_ERR("At least one dma block is required");
return -EINVAL;
}

for(int i=0; i < CONFIG_DMA_ESP32_DESCRIPTOR_NUM; ++i){
if(block->block_size > DMA_DESCRIPTOR_BUFFER_MAX_SIZE) {
LOG_ERR("Size of block %d is too large", i);
return -EINVAL;
}
memset(desc_iter, 0, sizeof(dma_descriptor_t));
desc_iter->buffer = (void*)block->dest_address;
desc_iter->dw0.size = block->block_size;
desc_iter->dw0.length = block->block_size;
desc_iter->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
if(!block->next_block) {
desc_iter->next = NULL;
desc_iter->dw0.suc_eof = 1;
break;
}
desc_iter->next = desc_iter + 1;
desc_iter += 1;
block = block->next_block;
}

if(desc_iter->next) {
memset(dma_channel->desc_list, 0, sizeof(dma_descriptor_t) * CONFIG_DMA_ESP32_DESCRIPTOR_NUM);

Check warning on line 276 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/dma/dma_esp32_gdma.c:276 line length of 110 exceeds 100 columns
LOG_ERR("Too many dma blocks. Increase CONFIG_DMA_ESP32_DESCRIPTOR_NUM");
return -EINVAL;
}

return 0;
}
Expand Down Expand Up @@ -349,20 +401,20 @@ static int dma_esp32_start(const struct device *dev, uint32_t channel)
&config->dma_channel[(dma_channel->channel_id * 2) + 1];

gdma_ll_rx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel_rx->desc);
(int32_t)dma_channel_rx->desc_list);
gdma_ll_rx_start(data->hal.dev, dma_channel->channel_id);

gdma_ll_tx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel_tx->desc);
(int32_t)dma_channel_tx->desc_list);
gdma_ll_tx_start(data->hal.dev, dma_channel->channel_id);
} else {
if (dma_channel->dir == DMA_RX) {
gdma_ll_rx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel->desc);
(int32_t)dma_channel->desc_list);
gdma_ll_rx_start(data->hal.dev, dma_channel->channel_id);
} else if (dma_channel->dir == DMA_TX) {
gdma_ll_tx_set_desc_addr(data->hal.dev, dma_channel->channel_id,
(int32_t)&dma_channel->desc);
(int32_t)dma_channel->desc_list);
gdma_ll_tx_start(data->hal.dev, dma_channel->channel_id);
} else {
LOG_ERR("Channel %d is not configured", channel);
Expand Down Expand Up @@ -408,6 +460,7 @@ static int dma_esp32_get_status(const struct device *dev, uint32_t channel,
struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config;
struct dma_esp32_data *data = (struct dma_esp32_data *const)(dev)->data;
struct dma_esp32_channel *dma_channel = &config->dma_channel[channel];
dma_descriptor_t *desc;

if (channel >= config->dma_channel_max) {
LOG_ERR("Unsupported channel");
Expand All @@ -418,16 +471,19 @@ static int dma_esp32_get_status(const struct device *dev, uint32_t channel,
return -EINVAL;
}

memset(status, 0, sizeof(struct dma_status));

if (dma_channel->dir == DMA_RX) {
status->busy = !gdma_ll_rx_is_fsm_idle(data->hal.dev, dma_channel->channel_id);
status->dir = PERIPHERAL_TO_MEMORY;
status->read_position = dma_channel->desc.dw0.length;
desc = (dma_descriptor_t*)gdma_ll_rx_get_current_desc_addr(data->hal.dev, dma_channel->channel_id);

Check warning on line 479 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/dma/dma_esp32_gdma.c:479 line length of 115 exceeds 100 columns
status->read_position = desc - dma_channel->desc_list;
status->total_copied = desc->dw0.length + dma_channel->desc_list[0].dw0.size * status->read_position;

Check warning on line 481 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/dma/dma_esp32_gdma.c:481 line length of 117 exceeds 100 columns
} else if (dma_channel->dir == DMA_TX) {
status->busy = !gdma_ll_tx_is_fsm_idle(data->hal.dev, dma_channel->channel_id);
status->dir = MEMORY_TO_PERIPHERAL;
status->write_position = dma_channel->desc.dw0.length;
status->total_copied = dma_channel->desc.dw0.length;
status->pending_length = dma_channel->desc.dw0.size - dma_channel->desc.dw0.length;
desc = (dma_descriptor_t*)gdma_ll_tx_get_current_desc_addr(data->hal.dev, dma_channel->channel_id);

Check warning on line 485 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/dma/dma_esp32_gdma.c:485 line length of 115 exceeds 100 columns
status->write_position = desc - dma_channel->desc_list;
}

return 0;
Expand All @@ -449,22 +505,8 @@ static int dma_esp32_reload(const struct device *dev, uint32_t channel, uint32_t

if (dma_channel->dir == DMA_RX) {
gdma_ll_rx_reset_channel(data->hal.dev, dma_channel->channel_id);
block.block_size = size;
block.dest_address = dst;
err = dma_esp32_config_rx_descriptor(dma_channel, &block);
if (err) {
LOG_ERR("Error reloading RX channel (%d)", err);
return err;
}
} else if (dma_channel->dir == DMA_TX) {
gdma_ll_tx_reset_channel(data->hal.dev, dma_channel->channel_id);
block.block_size = size;
block.source_address = src;
err = dma_esp32_config_tx_descriptor(dma_channel, &block);
if (err) {
LOG_ERR("Error reloading TX channel (%d)", err);
return err;
}
}

return 0;
Expand Down Expand Up @@ -542,7 +584,7 @@ static int dma_esp32_init(const struct device *dev)
dma_channel->cb = NULL;
dma_channel->dir = DMA_UNCONFIGURED;
dma_channel->periph_id = ESP_GDMA_TRIG_PERIPH_INVALID;
memset(&dma_channel->desc, 0, sizeof(dma_descriptor_t));
memset(dma_channel->desc_list, 0, sizeof(dma_descriptor_t) * CONFIG_DMA_ESP32_DESCRIPTOR_NUM);

Check warning on line 587 in drivers/dma/dma_esp32_gdma.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/dma/dma_esp32_gdma.c:587 line length of 110 exceeds 100 columns
}

gdma_hal_init(&data->hal, 0);
Expand Down

0 comments on commit 76e1dae

Please sign in to comment.