forked from espressif/esp-idf
Merge branch 'feat/test_gdma_psram' into 'master'
test(gdma): can do memory to/from psram correctly See merge request espressif/esp-idf!36758
This commit is contained in:
@@ -521,3 +521,193 @@ TEST_CASE("GDMA M2M Unaligned RX Buffer Test", "[GDMA][M2M]")
|
||||
free(sbuf);
|
||||
free(dbuf);
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void test_gdma_memcpy_from_to_psram(gdma_channel_handle_t tx_chan, gdma_channel_handle_t rx_chan)
|
||||
{
|
||||
#define COPY_SIZE (40*1024)
|
||||
SemaphoreHandle_t done_sem = xSemaphoreCreateBinary();
|
||||
TEST_ASSERT_NOT_NULL(done_sem);
|
||||
gdma_rx_event_callbacks_t rx_cbs = {
|
||||
.on_recv_eof = test_gdma_m2m_rx_eof_callback,
|
||||
};
|
||||
TEST_ESP_OK(gdma_register_rx_event_callbacks(rx_chan, &rx_cbs, done_sem));
|
||||
|
||||
gdma_strategy_config_t strategy = {
|
||||
.auto_update_desc = true,
|
||||
.owner_check = true,
|
||||
.eof_till_data_popped = true,
|
||||
};
|
||||
TEST_ESP_OK(gdma_apply_strategy(tx_chan, &strategy));
|
||||
TEST_ESP_OK(gdma_apply_strategy(rx_chan, &strategy));
|
||||
|
||||
gdma_transfer_config_t transfer_cfg = {
|
||||
.max_data_burst_size = 32,
|
||||
.access_ext_mem = true, // allow to do memory copy from/to external memory
|
||||
};
|
||||
TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_cfg));
|
||||
TEST_ESP_OK(gdma_config_transfer(rx_chan, &transfer_cfg));
|
||||
|
||||
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
|
||||
// get a free DMA trigger ID for memory copy
|
||||
uint32_t free_m2m_id_mask = 0;
|
||||
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
|
||||
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
|
||||
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
|
||||
TEST_ESP_OK(gdma_connect(rx_chan, m2m_trigger));
|
||||
|
||||
gdma_link_list_handle_t tx_link_list = NULL;
|
||||
gdma_link_list_handle_t rx_link_list = NULL;
|
||||
// create DMA link list for TX channel (a singly link with 3 nodes)
|
||||
gdma_link_list_config_t tx_link_list_config = {
|
||||
.buffer_alignment = 32,
|
||||
.item_alignment = 8, // 8-byte alignment required by the AXI-GDMA
|
||||
.num_items = 20,
|
||||
.flags = {
|
||||
.items_in_ext_mem = false,
|
||||
}
|
||||
};
|
||||
TEST_ESP_OK(gdma_new_link_list(&tx_link_list_config, &tx_link_list));
|
||||
// create DMA link list for RX channel
|
||||
gdma_link_list_config_t rx_link_list_config = {
|
||||
.buffer_alignment = 32,
|
||||
.item_alignment = 8, // 8-byte alignment required by the AXI-GDMA
|
||||
.num_items = 20,
|
||||
.flags = {
|
||||
.items_in_ext_mem = false,
|
||||
},
|
||||
};
|
||||
TEST_ESP_OK(gdma_new_link_list(&rx_link_list_config, &rx_link_list));
|
||||
|
||||
// allocate the source buffer from SRAM
|
||||
uint8_t *src_data = heap_caps_aligned_calloc(32, 1, COPY_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(src_data);
|
||||
TEST_ASSERT_TRUE(esp_ptr_internal(src_data));
|
||||
// prepare the source data
|
||||
for (int i = 0; i < COPY_SIZE; i++) {
|
||||
src_data[i] = i;
|
||||
}
|
||||
size_t sram_cache_line_sz = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
|
||||
size_t psram_cache_line_sz = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
|
||||
// do cache sync if necessary
|
||||
if (sram_cache_line_sz) {
|
||||
TEST_ESP_OK(esp_cache_msync(src_data, COPY_SIZE, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE));
|
||||
}
|
||||
|
||||
// allocate the destination buffer from PSRAM
|
||||
uint8_t *dst_data = heap_caps_aligned_calloc(32, 1, COPY_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
TEST_ASSERT_NOT_NULL(dst_data);
|
||||
TEST_ASSERT_TRUE(esp_ptr_external_ram(dst_data));
|
||||
if (psram_cache_line_sz) {
|
||||
TEST_ESP_OK(esp_cache_msync(dst_data, COPY_SIZE, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE));
|
||||
}
|
||||
|
||||
gdma_buffer_mount_config_t tx_buf_mount_config = {
|
||||
.buffer = src_data,
|
||||
.length = COPY_SIZE,
|
||||
.flags = {
|
||||
.mark_eof = true,
|
||||
.mark_final = true, // using singly list, so terminate the link here
|
||||
}
|
||||
};
|
||||
TEST_ESP_OK(gdma_link_mount_buffers(tx_link_list, 0, &tx_buf_mount_config, 1, NULL));
|
||||
|
||||
gdma_buffer_mount_config_t rx_buf_mount_config = {
|
||||
.buffer = dst_data,
|
||||
.length = COPY_SIZE,
|
||||
.flags = {
|
||||
.mark_final = true, // using singly list, so terminate the link here
|
||||
}
|
||||
};
|
||||
TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, &rx_buf_mount_config, 1, NULL));
|
||||
|
||||
TEST_ESP_OK(gdma_start(rx_chan, gdma_link_get_head_addr(rx_link_list)));
|
||||
TEST_ESP_OK(gdma_start(tx_chan, gdma_link_get_head_addr(tx_link_list)));
|
||||
|
||||
xSemaphoreTake(done_sem, pdMS_TO_TICKS(1000));
|
||||
|
||||
/// let the DMA to copy the data back to the source buffer again
|
||||
/// clear the "src_data" because now we want to use it as the destination buffer
|
||||
memset(src_data, 0, COPY_SIZE);
|
||||
// do cache sync if necessary
|
||||
if (sram_cache_line_sz) {
|
||||
TEST_ESP_OK(esp_cache_msync(src_data, COPY_SIZE, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE));
|
||||
}
|
||||
|
||||
tx_buf_mount_config.buffer = dst_data;
|
||||
TEST_ESP_OK(gdma_link_mount_buffers(tx_link_list, 0, &tx_buf_mount_config, 1, NULL));
|
||||
rx_buf_mount_config.buffer = src_data;
|
||||
TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, &rx_buf_mount_config, 1, NULL));
|
||||
|
||||
TEST_ESP_OK(gdma_start(rx_chan, gdma_link_get_head_addr(rx_link_list)));
|
||||
TEST_ESP_OK(gdma_start(tx_chan, gdma_link_get_head_addr(tx_link_list)));
|
||||
|
||||
xSemaphoreTake(done_sem, pdMS_TO_TICKS(1000));
|
||||
|
||||
bool compare_result = true;
|
||||
for (int i = 0; i < COPY_SIZE; i++) {
|
||||
if (src_data[i] != i % 256) {
|
||||
printf("miss match! src_data[%d]=%d, should be %d\n", i, src_data[i], i % 256);
|
||||
compare_result = false;
|
||||
}
|
||||
if (dst_data[i] != i % 256) {
|
||||
printf("miss match! dst_data[%d]=%d, should be %d\n", i, dst_data[i], i % 256);
|
||||
compare_result = false;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_TRUE(compare_result);
|
||||
|
||||
free(src_data);
|
||||
free(dst_data);
|
||||
TEST_ESP_OK(gdma_del_link_list(tx_link_list));
|
||||
TEST_ESP_OK(gdma_del_link_list(rx_link_list));
|
||||
vSemaphoreDelete(done_sem);
|
||||
#undef COPY_SIZE
|
||||
}
|
||||
|
||||
#if SOC_SPIRAM_SUPPORTED
|
||||
TEST_CASE("GDMA memory copy SRAM->PSRAM->SRAM", "[GDMA][M2M]")
|
||||
{
|
||||
[[maybe_unused]] gdma_channel_handle_t tx_chan = NULL;
|
||||
[[maybe_unused]] gdma_channel_handle_t rx_chan = NULL;
|
||||
[[maybe_unused]] gdma_channel_alloc_config_t tx_chan_alloc_config = {};
|
||||
[[maybe_unused]] gdma_channel_alloc_config_t rx_chan_alloc_config = {};
|
||||
|
||||
#if SOC_AHB_GDMA_SUPPORTED && SOC_AHB_GDMA_SUPPORT_PSRAM
|
||||
printf("Testing AHB-GDMA memory copy SRAM->PSRAM->SRAM\n");
|
||||
tx_chan_alloc_config = (gdma_channel_alloc_config_t) {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_TX,
|
||||
.flags.reserve_sibling = true,
|
||||
};
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan));
|
||||
rx_chan_alloc_config = (gdma_channel_alloc_config_t) {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
.sibling_chan = tx_chan,
|
||||
};
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&rx_chan_alloc_config, &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
|
||||
|
||||
#if SOC_AXI_GDMA_SUPPORTED && SOC_AXI_GDMA_SUPPORT_PSRAM
|
||||
printf("Testing AXI-GDMA memory copy SRAM->PSRAM->SRAM\n");
|
||||
tx_chan_alloc_config = (gdma_channel_alloc_config_t) {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_TX,
|
||||
.flags.reserve_sibling = true,
|
||||
};
|
||||
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan));
|
||||
rx_chan_alloc_config = (gdma_channel_alloc_config_t) {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
.sibling_chan = tx_chan,
|
||||
};
|
||||
TEST_ESP_OK(gdma_new_axi_channel(&rx_chan_alloc_config, &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
|
||||
}
|
||||
#endif // SOC_SPIRAM_SUPPORTED
|
||||
|
Reference in New Issue
Block a user