Skip to content

Commit f9718ee

Browse files
committed
test(gdma): can do memory to/from psram correctly
1 parent f9d5802 commit f9718ee

File tree

1 file changed

+190
-0
lines changed
  • components/esp_hw_support/test_apps/dma/main

1 file changed

+190
-0
lines changed

components/esp_hw_support/test_apps/dma/main/test_gdma.c

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,193 @@ TEST_CASE("GDMA M2M Unaligned RX Buffer Test", "[GDMA][M2M]")
521521
free(sbuf);
522522
free(dbuf);
523523
}
524+
525+
[[maybe_unused]] static void test_gdma_memcpy_from_to_psram(gdma_channel_handle_t tx_chan, gdma_channel_handle_t rx_chan)
526+
{
527+
#define COPY_SIZE (40*1024)
528+
SemaphoreHandle_t done_sem = xSemaphoreCreateBinary();
529+
TEST_ASSERT_NOT_NULL(done_sem);
530+
gdma_rx_event_callbacks_t rx_cbs = {
531+
.on_recv_eof = test_gdma_m2m_rx_eof_callback,
532+
};
533+
TEST_ESP_OK(gdma_register_rx_event_callbacks(rx_chan, &rx_cbs, done_sem));
534+
535+
gdma_strategy_config_t strategy = {
536+
.auto_update_desc = true,
537+
.owner_check = true,
538+
.eof_till_data_popped = true,
539+
};
540+
TEST_ESP_OK(gdma_apply_strategy(tx_chan, &strategy));
541+
TEST_ESP_OK(gdma_apply_strategy(rx_chan, &strategy));
542+
543+
gdma_transfer_config_t transfer_cfg = {
544+
.max_data_burst_size = 32,
545+
.access_ext_mem = true, // allow to do memory copy from/to external memory
546+
};
547+
TEST_ESP_OK(gdma_config_transfer(tx_chan, &transfer_cfg));
548+
TEST_ESP_OK(gdma_config_transfer(rx_chan, &transfer_cfg));
549+
550+
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
551+
// get a free DMA trigger ID for memory copy
552+
uint32_t free_m2m_id_mask = 0;
553+
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
554+
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
555+
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
556+
TEST_ESP_OK(gdma_connect(rx_chan, m2m_trigger));
557+
558+
gdma_link_list_handle_t tx_link_list = NULL;
559+
gdma_link_list_handle_t rx_link_list = NULL;
560+
// create DMA link list for TX channel (a singly link with 3 nodes)
561+
gdma_link_list_config_t tx_link_list_config = {
562+
.buffer_alignment = 32,
563+
.item_alignment = 8, // 8-byte alignment required by the AXI-GDMA
564+
.num_items = 20,
565+
.flags = {
566+
.items_in_ext_mem = false,
567+
}
568+
};
569+
TEST_ESP_OK(gdma_new_link_list(&tx_link_list_config, &tx_link_list));
570+
// create DMA link list for RX channel
571+
gdma_link_list_config_t rx_link_list_config = {
572+
.buffer_alignment = 32,
573+
.item_alignment = 8, // 8-byte alignment required by the AXI-GDMA
574+
.num_items = 20,
575+
.flags = {
576+
.items_in_ext_mem = false,
577+
},
578+
};
579+
TEST_ESP_OK(gdma_new_link_list(&rx_link_list_config, &rx_link_list));
580+
581+
// allocate the source buffer from SRAM
582+
uint8_t *src_data = heap_caps_aligned_calloc(32, 1, COPY_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
583+
TEST_ASSERT_NOT_NULL(src_data);
584+
TEST_ASSERT_TRUE(esp_ptr_internal(src_data));
585+
// prepare the source data
586+
for (int i = 0; i < COPY_SIZE; i++) {
587+
src_data[i] = i;
588+
}
589+
size_t sram_cache_line_sz = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
590+
size_t psram_cache_line_sz = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
591+
// do cache sync if necessary
592+
if (sram_cache_line_sz) {
593+
TEST_ESP_OK(esp_cache_msync(src_data, COPY_SIZE, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE));
594+
}
595+
596+
// allocate the destination buffer from PSRAM
597+
uint8_t *dst_data = heap_caps_aligned_calloc(32, 1, COPY_SIZE, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
598+
TEST_ASSERT_NOT_NULL(dst_data);
599+
TEST_ASSERT_TRUE(esp_ptr_external_ram(dst_data));
600+
if (psram_cache_line_sz) {
601+
TEST_ESP_OK(esp_cache_msync(dst_data, COPY_SIZE, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE));
602+
}
603+
604+
gdma_buffer_mount_config_t tx_buf_mount_config = {
605+
.buffer = src_data,
606+
.length = COPY_SIZE,
607+
.flags = {
608+
.mark_eof = true,
609+
.mark_final = true, // using singly list, so terminate the link here
610+
}
611+
};
612+
TEST_ESP_OK(gdma_link_mount_buffers(tx_link_list, 0, &tx_buf_mount_config, 1, NULL));
613+
614+
gdma_buffer_mount_config_t rx_buf_mount_config = {
615+
.buffer = dst_data,
616+
.length = COPY_SIZE,
617+
.flags = {
618+
.mark_final = true, // using singly list, so terminate the link here
619+
}
620+
};
621+
TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, &rx_buf_mount_config, 1, NULL));
622+
623+
TEST_ESP_OK(gdma_start(rx_chan, gdma_link_get_head_addr(rx_link_list)));
624+
TEST_ESP_OK(gdma_start(tx_chan, gdma_link_get_head_addr(tx_link_list)));
625+
626+
xSemaphoreTake(done_sem, pdMS_TO_TICKS(1000));
627+
628+
/// let the DMA to copy the data back to the source buffer again
629+
/// clear the "src_data" because now we want to use it as the destination buffer
630+
memset(src_data, 0, COPY_SIZE);
631+
// do cache sync if necessary
632+
if (sram_cache_line_sz) {
633+
TEST_ESP_OK(esp_cache_msync(src_data, COPY_SIZE, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE));
634+
}
635+
636+
tx_buf_mount_config.buffer = dst_data;
637+
TEST_ESP_OK(gdma_link_mount_buffers(tx_link_list, 0, &tx_buf_mount_config, 1, NULL));
638+
rx_buf_mount_config.buffer = src_data;
639+
TEST_ESP_OK(gdma_link_mount_buffers(rx_link_list, 0, &rx_buf_mount_config, 1, NULL));
640+
641+
TEST_ESP_OK(gdma_start(rx_chan, gdma_link_get_head_addr(rx_link_list)));
642+
TEST_ESP_OK(gdma_start(tx_chan, gdma_link_get_head_addr(tx_link_list)));
643+
644+
xSemaphoreTake(done_sem, pdMS_TO_TICKS(1000));
645+
646+
bool compare_result = true;
647+
for (int i = 0; i < COPY_SIZE; i++) {
648+
if (src_data[i] != i % 256) {
649+
printf("miss match! src_data[%d]=%d, should be %d\n", i, src_data[i], i % 256);
650+
compare_result = false;
651+
}
652+
if (dst_data[i] != i % 256) {
653+
printf("miss match! dst_data[%d]=%d, should be %d\n", i, dst_data[i], i % 256);
654+
compare_result = false;
655+
}
656+
}
657+
TEST_ASSERT_TRUE(compare_result);
658+
659+
free(src_data);
660+
free(dst_data);
661+
TEST_ESP_OK(gdma_del_link_list(tx_link_list));
662+
TEST_ESP_OK(gdma_del_link_list(rx_link_list));
663+
vSemaphoreDelete(done_sem);
664+
#undef COPY_SIZE
665+
}
666+
667+
#if SOC_SPIRAM_SUPPORTED
668+
TEST_CASE("GDMA memory copy SRAM->PSRAM->SRAM", "[GDMA][M2M]")
669+
{
670+
[[maybe_unused]] gdma_channel_handle_t tx_chan = NULL;
671+
[[maybe_unused]] gdma_channel_handle_t rx_chan = NULL;
672+
[[maybe_unused]] gdma_channel_alloc_config_t tx_chan_alloc_config = {};
673+
[[maybe_unused]] gdma_channel_alloc_config_t rx_chan_alloc_config = {};
674+
675+
#if SOC_AHB_GDMA_SUPPORTED && SOC_AHB_GDMA_SUPPORT_PSRAM
676+
printf("Testing AHB-GDMA memory copy SRAM->PSRAM->SRAM\n");
677+
tx_chan_alloc_config = (gdma_channel_alloc_config_t) {
678+
.direction = GDMA_CHANNEL_DIRECTION_TX,
679+
.flags.reserve_sibling = true,
680+
};
681+
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan));
682+
rx_chan_alloc_config = (gdma_channel_alloc_config_t) {
683+
.direction = GDMA_CHANNEL_DIRECTION_RX,
684+
.sibling_chan = tx_chan,
685+
};
686+
TEST_ESP_OK(gdma_new_ahb_channel(&rx_chan_alloc_config, &rx_chan));
687+
688+
test_gdma_memcpy_from_to_psram(tx_chan, rx_chan);
689+
690+
TEST_ESP_OK(gdma_del_channel(tx_chan));
691+
TEST_ESP_OK(gdma_del_channel(rx_chan));
692+
#endif
693+
694+
#if SOC_AXI_GDMA_SUPPORTED && SOC_AXI_GDMA_SUPPORT_PSRAM
695+
printf("Testing AXI-GDMA memory copy SRAM->PSRAM->SRAM\n");
696+
tx_chan_alloc_config = (gdma_channel_alloc_config_t) {
697+
.direction = GDMA_CHANNEL_DIRECTION_TX,
698+
.flags.reserve_sibling = true,
699+
};
700+
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan));
701+
rx_chan_alloc_config = (gdma_channel_alloc_config_t) {
702+
.direction = GDMA_CHANNEL_DIRECTION_RX,
703+
.sibling_chan = tx_chan,
704+
};
705+
TEST_ESP_OK(gdma_new_axi_channel(&rx_chan_alloc_config, &rx_chan));
706+
707+
test_gdma_memcpy_from_to_psram(tx_chan, rx_chan);
708+
709+
TEST_ESP_OK(gdma_del_channel(tx_chan));
710+
TEST_ESP_OK(gdma_del_channel(rx_chan));
711+
#endif
712+
}
713+
#endif // SOC_SPIRAM_SUPPORTED

0 commit comments

Comments
 (0)