feat(gdma): support lp ahb dma on esp32s31

This commit is contained in:
Chen Jichang
2026-01-28 13:08:07 +08:00
committed by morris
parent 1535ac2b0a
commit 7656e0935e
18 changed files with 400 additions and 54 deletions
@@ -141,6 +141,13 @@ TEST_CASE("memory copy the same buffer with different content", "[async mcp]")
test_memory_copy_with_same_buffer(driver, &config);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_CP_DMA_SUPPORTED
#if SOC_HAS(LP_AHB_GDMA)
printf("Testing memcpy by LP AHB GDMA\r\n");
TEST_ESP_OK(esp_async_memcpy_install_gdma_lp_ahb(&config, &driver));
test_memory_copy_with_same_buffer(driver, &config);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_HAS(LP_AHB_GDMA)
}
static bool test_async_memcpy_cb_v1(async_memcpy_handle_t mcp_hdl, async_memcpy_event_t *event, void *cb_args)
@@ -206,6 +213,13 @@ TEST_CASE("memory copy by DMA (blocking)", "[async mcp]")
test_memory_copy_blocking(driver);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_CP_DMA_SUPPORTED
#if SOC_HAS(LP_AHB_GDMA)
printf("Testing memcpy by LP AHB GDMA\r\n");
TEST_ESP_OK(esp_async_memcpy_install_gdma_lp_ahb(&config, &driver));
test_memory_copy_blocking(driver);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_HAS(LP_AHB_GDMA)
}
[[maybe_unused]] static void test_memcpy_with_dest_addr_unaligned(async_memcpy_handle_t driver, bool src_in_psram, bool dst_in_psram)
@@ -273,6 +287,16 @@ TEST_CASE("memory copy with dest address unaligned", "[async mcp]")
#endif // GDMA_LL_GET(AXI_PSRAM_CAPABLE) && SOC_HAS(SPIRAM)
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_HAS(AXI_GDMA)
#if SOC_HAS(LP_AHB_GDMA) && !CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
printf("Testing memcpy by LP AHB GDMA\r\n");
TEST_ESP_OK(esp_async_memcpy_install_gdma_lp_ahb(&driver_config, &driver));
test_memcpy_with_dest_addr_unaligned(driver, false, false);
#if GDMA_LL_GET(LP_AHB_PSRAM_CAPABLE) && SOC_HAS(SPIRAM)
test_memcpy_with_dest_addr_unaligned(driver, true, true);
#endif // GDMA_LL_GET(LP_AHB_PSRAM_CAPABLE) && SOC_HAS(SPIRAM)
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_HAS(LP_AHB_GDMA)
}
#define TEST_ASYNC_MEMCPY_BENCH_COUNTS 16
@@ -362,6 +386,13 @@ TEST_CASE("memory copy performance 40KB: SRAM->SRAM", "[async mcp]")
test_memcpy_performance(driver, 40 * 1024, false, false);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_CP_DMA_SUPPORTED
#if SOC_HAS(LP_AHB_GDMA)
printf("Testing memcpy by LP AHB GDMA\r\n");
TEST_ESP_OK(esp_async_memcpy_install_gdma_lp_ahb(&driver_config, &driver));
test_memcpy_performance(driver, 40 * 1024, false, false);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // SOC_HAS(LP_AHB_GDMA)
}
#if SOC_SPIRAM_SUPPORTED
@@ -390,6 +421,15 @@ TEST_CASE("memory copy performance 40KB: PSRAM->PSRAM", "[async mcp]")
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif
#endif // SOC_HAS(AXI_GDMA)
#if SOC_HAS(LP_AHB_GDMA)
#if GDMA_LL_GET(LP_AHB_PSRAM_CAPABLE)
printf("Testing memcpy by LP AHB GDMA\r\n");
TEST_ESP_OK(esp_async_memcpy_install_gdma_lp_ahb(&driver_config, &driver));
test_memcpy_performance(driver, 40 * 1024, true, true);
TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
#endif // GDMA_LL_GET(LP_AHB_PSRAM_CAPABLE)
#endif // SOC_HAS(LP_AHB_GDMA)
}
#endif
@@ -147,6 +147,64 @@ TEST_CASE("GDMA channel allocation", "[GDMA]")
TEST_ESP_OK(gdma_del_channel(rx_channels[i]));
}
#endif // GDMA_LL_AXI_PAIRS_PER_GROUP >= 2
#if SOC_HAS(LP_AHB_GDMA)
// install TX channels
for (int i = 0; i < GDMA_LL_LP_AHB_PAIRS_PER_GROUP; i++) {
TEST_ESP_OK(gdma_new_lp_ahb_channel(&channel_config, &tx_channels[i], NULL));
};
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, gdma_new_lp_ahb_channel(&channel_config, &tx_channels[0], NULL));
// Free interrupts before installing RX interrupts to ensure enough free interrupts
for (int i = 0; i < GDMA_LL_LP_AHB_PAIRS_PER_GROUP; i++) {
TEST_ESP_OK(gdma_del_channel(tx_channels[i]));
}
// install RX channels
for (int i = 0; i < GDMA_LL_LP_AHB_PAIRS_PER_GROUP; i++) {
TEST_ESP_OK(gdma_new_lp_ahb_channel(&channel_config, NULL, &rx_channels[i]));
}
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, gdma_new_lp_ahb_channel(&channel_config, NULL, &rx_channels[0]));
for (int i = 0; i < GDMA_LL_LP_AHB_PAIRS_PER_GROUP; i++) {
TEST_ESP_OK(gdma_del_channel(rx_channels[i]));
}
#endif // SOC_HAS(LP_AHB_GDMA)
// install single and paired TX/RX channels
#if GDMA_LL_LP_AHB_PAIRS_PER_GROUP >= 2
// single tx channel
TEST_ESP_OK(gdma_new_lp_ahb_channel(&channel_config, &tx_channels[0], NULL));
// create tx and rx channel pair
TEST_ESP_OK(gdma_new_lp_ahb_channel(&channel_config, &tx_channels[1], &rx_channels[1]));
// create single rx channel
TEST_ESP_OK(gdma_new_lp_ahb_channel(&channel_config, NULL, &rx_channels[0]));
gdma_trigger_t fake_lp_ahb_trigger1 = {
.bus_id = SOC_GDMA_BUS_LP,
.instance_id = 0,
};
gdma_trigger_t fake_lp_ahb_trigger2 = {
.bus_id = SOC_GDMA_BUS_LP,
.instance_id = 1,
};
TEST_ESP_OK(gdma_connect(tx_channels[0], fake_lp_ahb_trigger1));
// can't connect multiple channels to the same peripheral
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gdma_connect(tx_channels[1], fake_lp_ahb_trigger1));
TEST_ESP_OK(gdma_connect(tx_channels[1], fake_lp_ahb_trigger2));
// but rx and tx can connect to the same peripheral
TEST_ESP_OK(gdma_connect(rx_channels[0], fake_lp_ahb_trigger1));
TEST_ESP_OK(gdma_connect(rx_channels[1], fake_lp_ahb_trigger2));
for (int i = 0; i < 2; i++) {
TEST_ESP_OK(gdma_disconnect(tx_channels[i]));
TEST_ESP_OK(gdma_disconnect(rx_channels[i]));
TEST_ESP_OK(gdma_del_channel(tx_channels[i]));
TEST_ESP_OK(gdma_del_channel(rx_channels[i]));
}
#endif // GDMA_LL_LP_AHB_PAIRS_PER_GROUP >= 2
}
static void test_gdma_config_link_list(gdma_channel_handle_t tx_chan, gdma_channel_handle_t rx_chan,
@@ -363,6 +421,15 @@ static void test_gdma_m2m_mode(bool trig_retention_backup)
TEST_ESP_OK(gdma_del_channel(tx_chan));
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif // SOC_HAS(AXI_GDMA)
#if SOC_HAS(LP_AHB_GDMA)
TEST_ESP_OK(gdma_new_lp_ahb_channel(&chan_alloc_config, &tx_chan, &rx_chan));
test_gdma_m2m_transaction(tx_chan, rx_chan, false, trig_retention_backup);
TEST_ESP_OK(gdma_del_channel(tx_chan));
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif // SOC_HAS(LP_AHB_GDMA)
}
TEST_CASE("GDMA M2M Mode", "[GDMA][M2M]")
@@ -677,5 +744,15 @@ TEST_CASE("GDMA memory copy SRAM->PSRAM->SRAM", "[GDMA][M2M]")
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif
#endif // SOC_HAS(AXI_GDMA)
#if SOC_HAS(LP_AHB_GDMA)
printf("Testing LP-AHB-GDMA memory copy SRAM->PSRAM->SRAM\n");
TEST_ESP_OK(gdma_new_lp_ahb_channel(&chan_alloc_config, &tx_chan, &rx_chan));
test_gdma_memcpy_from_to_psram(tx_chan, rx_chan);
TEST_ESP_OK(gdma_del_channel(tx_chan));
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif // SOC_HAS(LP_AHB_GDMA)
}
#endif // SOC_SPIRAM_SUPPORTED