mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
feat(gdma): add burst size validation check during config
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -202,7 +202,7 @@ esp_err_t gdma_disconnect(gdma_channel_handle_t dma_chan);
|
||||
typedef struct {
|
||||
uint32_t max_data_burst_size; /*!< Set the max burst size when DMA read/write the data buffer.
|
||||
Set to 0 means to disable the data burst.
|
||||
Other value must be power of 2, e.g., 4/8/16/32/64 */
|
||||
Other values must be powers of 2 or supported by the selected GDMA bus. */
|
||||
bool access_ext_mem; /*!< Set this if the DMA transfer will access external memory */
|
||||
} gdma_transfer_config_t;
|
||||
|
||||
|
||||
@@ -421,6 +421,9 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
gdma_pair_t *pair = dma_chan->pair;
|
||||
gdma_group_t *group = pair->group;
|
||||
gdma_hal_context_t *hal = &group->hal;
|
||||
uint32_t max_data_burst_size = config->max_data_burst_size;
|
||||
size_t int_mem_alignment = 1;
|
||||
size_t ext_enc_mem_alignment = 1;
|
||||
@@ -443,8 +446,7 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf
|
||||
#endif
|
||||
}
|
||||
if (max_data_burst_size) {
|
||||
// burst size must be power of 2
|
||||
ESP_RETURN_ON_FALSE((max_data_burst_size & (max_data_burst_size - 1)) == 0, ESP_ERR_INVALID_ARG,
|
||||
ESP_RETURN_ON_FALSE(gdma_hal_check_burst_size(hal, max_data_burst_size), ESP_ERR_INVALID_ARG,
|
||||
TAG, "invalid max_data_burst_size: %"PRIu32, max_data_burst_size);
|
||||
}
|
||||
|
||||
@@ -477,10 +479,6 @@ esp_err_t gdma_config_transfer(gdma_channel_handle_t dma_chan, const gdma_transf
|
||||
ext_no_enc_mem_alignment = BIT(31);
|
||||
}
|
||||
|
||||
gdma_pair_t *pair = dma_chan->pair;
|
||||
gdma_group_t *group = pair->group;
|
||||
gdma_hal_context_t *hal = &group->hal;
|
||||
|
||||
// always enable descriptor burst as the descriptor is always word aligned and is in the internal SRAM
|
||||
bool en_desc_burst = true;
|
||||
gdma_hal_enable_burst(hal, pair->pair_id, dma_chan->direction, en_data_burst, en_desc_burst);
|
||||
|
||||
@@ -921,3 +921,66 @@ TEST_CASE("GDMA interrupt priority configuration", "[GDMA]")
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
TEST_ESP_OK(gdma_del_channel(rx_chan));
|
||||
}
|
||||
|
||||
#if SOC_HAS(AHB_GDMA)
|
||||
TEST_CASE("GDMA rejects invalid AHB burst sizes", "[GDMA]")
|
||||
{
|
||||
gdma_channel_handle_t tx_chan = NULL;
|
||||
gdma_channel_alloc_config_t channel_config = {};
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&channel_config, &tx_chan, NULL));
|
||||
|
||||
gdma_transfer_config_t transfer_config = {
|
||||
.max_data_burst_size = 16,
|
||||
.access_ext_mem = false,
|
||||
};
|
||||
TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_config));
|
||||
|
||||
#if GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE)
|
||||
// Non power-of-two must be rejected when the burst size is programmable.
|
||||
transfer_config.max_data_burst_size = 3;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config));
|
||||
|
||||
// 8 is a power of two but is outside every current AHB supported-burst mask.
|
||||
transfer_config.max_data_burst_size = 8;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config));
|
||||
|
||||
#if GDMA_LL_GET(AHB_PSRAM_CAPABLE)
|
||||
transfer_config.access_ext_mem = true;
|
||||
transfer_config.max_data_burst_size = GDMA_LL_MAX_BURST_SIZE_PSRAM * 2;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config));
|
||||
#endif // GDMA_LL_GET(AHB_PSRAM_CAPABLE)
|
||||
#endif // GDMA_LL_GET(AHB_BURST_SIZE_ADJUSTABLE)
|
||||
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
}
|
||||
#endif // SOC_HAS(AHB_GDMA)
|
||||
|
||||
#if SOC_HAS(AXI_GDMA)
|
||||
TEST_CASE("GDMA rejects invalid AXI burst sizes", "[GDMA]")
|
||||
{
|
||||
gdma_channel_handle_t tx_chan = NULL;
|
||||
gdma_channel_alloc_config_t channel_config = {};
|
||||
TEST_ESP_OK(gdma_new_axi_channel(&channel_config, &tx_chan, NULL));
|
||||
|
||||
gdma_transfer_config_t transfer_config = {
|
||||
.max_data_burst_size = 16,
|
||||
.access_ext_mem = false,
|
||||
};
|
||||
TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_config));
|
||||
|
||||
transfer_config.max_data_burst_size = 3;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config));
|
||||
|
||||
// 4 is a power of two but is outside the AXI supported-burst mask.
|
||||
transfer_config.max_data_burst_size = 4;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config));
|
||||
|
||||
#if GDMA_LL_GET(AXI_PSRAM_CAPABLE)
|
||||
transfer_config.access_ext_mem = true;
|
||||
transfer_config.max_data_burst_size = GDMA_LL_MAX_BURST_SIZE_PSRAM * 2;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gdma_config_transfer(tx_chan, &transfer_config));
|
||||
#endif // GDMA_LL_GET(AXI_PSRAM_CAPABLE)
|
||||
|
||||
TEST_ESP_OK(gdma_del_channel(tx_chan));
|
||||
}
|
||||
#endif // SOC_HAS(AXI_GDMA)
|
||||
|
||||
Reference in New Issue
Block a user