@@ -36,6 +36,7 @@ typedef struct {
3636 uint32_t dst_offset ;
3737 bool src_in_psram ;
3838 bool dst_in_psram ;
39+ bool src_dst_same ;
3940} memcpy_testbench_context_t ;
4041
4142static void async_memcpy_setup_testbench (memcpy_testbench_context_t * test_context )
@@ -51,10 +52,13 @@ static void async_memcpy_setup_testbench(memcpy_testbench_context_t *test_contex
5152 uint32_t mem_caps = test_context -> src_in_psram ? MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT : MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT ;
5253 src_buf = heap_caps_aligned_calloc (test_context -> align , 1 , buffer_size , mem_caps );
5354 TEST_ASSERT_NOT_NULL (src_buf );
54-
55- mem_caps = test_context -> dst_in_psram ? MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT : MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT ;
56- dst_buf = heap_caps_aligned_calloc (test_context -> align , 1 , buffer_size , mem_caps );
57- TEST_ASSERT_NOT_NULL (dst_buf );
55+ if (test_context -> src_dst_same ) {
56+ dst_buf = src_buf ;
57+ } else {
58+ mem_caps = test_context -> dst_in_psram ? MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA | MALLOC_CAP_8BIT : MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT ;
59+ dst_buf = heap_caps_aligned_calloc (test_context -> align , 1 , buffer_size , mem_caps );
60+ TEST_ASSERT_NOT_NULL (dst_buf );
61+ }
5862
5963 // adding extra offset
6064 from_addr = src_buf + test_context -> src_offset ;
@@ -87,10 +91,10 @@ static void async_memcpy_verify_and_clear_testbench(uint32_t copy_size, uint8_t
8791 free (dst_buf );
8892}
8993
90- static void test_memory_copy_with_same_buffer (async_memcpy_handle_t driver )
94+ static void test_memory_copy_with_same_buffer (async_memcpy_handle_t driver , async_memcpy_config_t * config )
9195{
92- uint8_t * sbuf = heap_caps_calloc ( 1 , 256 , MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT );
93- uint8_t * dbuf = heap_caps_calloc ( 1 , 256 , MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT );
96+ uint8_t * sbuf = heap_caps_aligned_calloc ( config -> dma_burst_size , 1 , 256 , MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT );
97+ uint8_t * dbuf = heap_caps_aligned_calloc ( config -> dma_burst_size , 1 , 256 , MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT );
9498 TEST_ASSERT_NOT_NULL (sbuf );
9599 TEST_ASSERT_NOT_NULL (dbuf );
96100
@@ -118,21 +122,21 @@ TEST_CASE("memory copy the same buffer with different content", "[async mcp]")
118122#if SOC_AHB_GDMA_SUPPORTED
119123 printf ("Testing memcpy by AHB GDMA\r\n" );
120124 TEST_ESP_OK (esp_async_memcpy_install_gdma_ahb (& config , & driver ));
121- test_memory_copy_with_same_buffer (driver );
125+ test_memory_copy_with_same_buffer (driver , & config );
122126 TEST_ESP_OK (esp_async_memcpy_uninstall (driver ));
123127#endif // SOC_AHB_GDMA_SUPPORTED
124128
125129#if SOC_AXI_GDMA_SUPPORTED
126130 printf ("Testing memcpy by AXI GDMA\r\n" );
127131 TEST_ESP_OK (esp_async_memcpy_install_gdma_axi (& config , & driver ));
128- test_memory_copy_with_same_buffer (driver );
132+ test_memory_copy_with_same_buffer (driver , & config );
129133 TEST_ESP_OK (esp_async_memcpy_uninstall (driver ));
130134#endif // SOC_AXI_GDMA_SUPPORTED
131135
132136#if SOC_CP_DMA_SUPPORTED
133137 printf ("Testing memcpy by CP DMA\r\n" );
134138 TEST_ESP_OK (esp_async_memcpy_install_cpdma (& config , & driver ));
135- test_memory_copy_with_same_buffer (driver );
139+ test_memory_copy_with_same_buffer (driver , & config );
136140 TEST_ESP_OK (esp_async_memcpy_uninstall (driver ));
137141#endif // SOC_CP_DMA_SUPPORTED
138142}
@@ -243,7 +247,7 @@ TEST_CASE("memory copy with dest address unaligned", "[async mcp]")
243247 TEST_ESP_OK (esp_async_memcpy_uninstall (driver ));
244248#endif // SOC_CP_DMA_SUPPORTED
245249
246- #if SOC_AHB_GDMA_SUPPORTED && !GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT
250+ #if SOC_AHB_GDMA_SUPPORTED && !GDMA_LL_AHB_RX_BURST_NEEDS_ALIGNMENT && ! CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
247251 printf ("Testing memcpy by AHB GDMA\r\n" );
248252 TEST_ESP_OK (esp_async_memcpy_install_gdma_ahb (& driver_config , & driver ));
249253 test_memcpy_with_dest_addr_unaligned (driver , false, false);
@@ -253,7 +257,7 @@ TEST_CASE("memory copy with dest address unaligned", "[async mcp]")
253257 TEST_ESP_OK (esp_async_memcpy_uninstall (driver ));
254258#endif // SOC_AHB_GDMA_SUPPORTED
255259
256- #if SOC_AXI_GDMA_SUPPORTED
260+ #if SOC_AXI_GDMA_SUPPORTED && ! CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
257261 printf ("Testing memcpy by AXI GDMA\r\n" );
258262 TEST_ESP_OK (esp_async_memcpy_install_gdma_axi (& driver_config , & driver ));
259263 test_memcpy_with_dest_addr_unaligned (driver , false, false);
@@ -377,3 +381,117 @@ TEST_CASE("memory copy performance 40KB: PSRAM->PSRAM", "[async mcp]")
377381#endif // SOC_AXI_GDMA_SUPPORTED && SOC_AXI_GDMA_SUPPORT_PSRAM
378382}
379383#endif
384+
385+ #if CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
386+ typedef struct {
387+ SemaphoreHandle_t sem ;
388+ int64_t elapse_us ;
389+ } test_weighted_arb_context_t ;
390+ static IRAM_ATTR bool test_weighted_arb_isr_cb (async_memcpy_handle_t mcp_hdl , async_memcpy_event_t * event , void * cb_args )
391+ {
392+ test_weighted_arb_context_t * ctx = (test_weighted_arb_context_t * )cb_args ;
393+ BaseType_t high_task_wakeup = pdFALSE ;
394+ ctx -> elapse_us = ccomp_timer_get_time ();
395+ xSemaphoreGiveFromISR (ctx -> sem , & high_task_wakeup );
396+ return high_task_wakeup == pdTRUE ;
397+ }
398+
399+ static void memcpy_weighted_arb_test (async_memcpy_handle_t driver [2 ], size_t burst_size , uint32_t buffer_size , bool buffer_in_psram )
400+ {
401+ SemaphoreHandle_t sem [2 ] = {xSemaphoreCreateBinary (),xSemaphoreCreateBinary ()};
402+ int64_t elapse_us [2 ] = {0 };
403+ float throughput [2 ] = {0.0 };
404+
405+ memcpy_testbench_context_t test_context = {
406+ .align = burst_size ,
407+ .buffer_size = buffer_size ,
408+ .src_dst_same = !buffer_in_psram , // if buffer is in PSRAM, no memory size limitation
409+ .src_in_psram = buffer_in_psram ,
410+ .dst_in_psram = buffer_in_psram ,
411+ };
412+ async_memcpy_setup_testbench (& test_context );
413+ test_weighted_arb_context_t ctx [2 ] = {
414+ [0 ] = {
415+ .sem = sem [0 ],
416+ },
417+ [1 ] = {
418+ .sem = sem [1 ],
419+ }
420+ };
421+
422+ ccomp_timer_start ();
423+ TEST_ESP_OK (esp_async_memcpy (driver [0 ], test_context .to_addr , test_context .from_addr , test_context .copy_size , test_weighted_arb_isr_cb , & ctx [0 ]));
424+ TEST_ESP_OK (esp_async_memcpy (driver [1 ], test_context .to_addr , test_context .from_addr , test_context .copy_size , test_weighted_arb_isr_cb , & ctx [1 ]));
425+
426+ // get channel_1 spent time
427+ TEST_ASSERT_EQUAL (pdTRUE , xSemaphoreTake (sem [1 ], pdMS_TO_TICKS (1000 )));
428+ elapse_us [1 ] = ctx [1 ].elapse_us ;
429+
430+ // wait for channel_0 done, keep channel_1 busy to do arbitration
431+ while (xSemaphoreTake (sem [0 ], 0 ) == pdFALSE ) {
432+ TEST_ESP_OK (esp_async_memcpy (driver [1 ], test_context .to_addr , test_context .from_addr , test_context .copy_size , test_weighted_arb_isr_cb , & ctx [1 ]));
433+ TEST_ASSERT_EQUAL (pdTRUE , xSemaphoreTake (sem [1 ], pdMS_TO_TICKS (1000 )));
434+ }
435+ // get channel_0 spent time
436+ elapse_us [0 ] = ctx [0 ].elapse_us ;
437+
438+ ccomp_timer_stop ();
439+ throughput [0 ] = (float )test_context .buffer_size * 1e6 / 1024 / 1024 / elapse_us [0 ];
440+ IDF_LOG_PERFORMANCE ("DMA0_COPY" , "%.2f MB/s, size: %zu Bytes" , throughput [0 ], test_context .buffer_size );
441+
442+ throughput [1 ] = (float )test_context .buffer_size * 1e6 / 1024 / 1024 / elapse_us [1 ];
443+ IDF_LOG_PERFORMANCE ("DMA1_COPY" , "%.2f MB/s, size: %zu Bytes" , throughput [1 ], test_context .buffer_size );
444+
445+ // the bandwidth of channel_1 should be at least 10 times of channel_0
446+ TEST_ASSERT_EQUAL (throughput [1 ] / throughput [0 ] > 10 , true);
447+
448+ async_memcpy_verify_and_clear_testbench (test_context .copy_size , test_context .src_buf , buffer_in_psram ? test_context .dst_buf : NULL ,
449+ test_context .from_addr , test_context .to_addr );
450+
451+ vSemaphoreDelete (sem [0 ]);
452+ vSemaphoreDelete (sem [1 ]);
453+ }
454+
455+ TEST_CASE ("GDMA M2M Weighted Arbitration Test SRAM->SRAM" , "[GDMA][M2M][async mcp]" )
456+ {
457+ async_memcpy_config_t driver_config = {
458+ .backlog = TEST_ASYNC_MEMCPY_BENCH_COUNTS ,
459+ .dma_burst_size = 64 ,
460+ };
461+
462+ async_memcpy_handle_t driver [2 ] = {NULL };
463+
464+ #if SOC_AHB_GDMA_SUPPORTED
465+ driver_config .weight = 1 ;
466+ TEST_ESP_OK (esp_async_memcpy_install_gdma_ahb (& driver_config , & driver [0 ]));
467+ driver_config .weight = 15 ;
468+ TEST_ESP_OK (esp_async_memcpy_install_gdma_ahb (& driver_config , & driver [1 ]));
469+ memcpy_weighted_arb_test (driver , driver_config .dma_burst_size , 200 * 1024 , false);
470+ TEST_ESP_OK (esp_async_memcpy_uninstall (driver [0 ]));
471+ TEST_ESP_OK (esp_async_memcpy_uninstall (driver [1 ]));
472+ #endif // SOC_AHB_GDMA_SUPPORTED
473+ }
474+
475+ #if SOC_SPIRAM_SUPPORTED
476+ TEST_CASE ("GDMA M2M Weighted Arbitration Test PSRAM->PSRAM" , "[GDMA][M2M][async mcp]" )
477+ {
478+ [[maybe_unused ]] async_memcpy_config_t driver_config = {
479+ .backlog = TEST_ASYNC_MEMCPY_BENCH_COUNTS ,
480+ .dma_burst_size = 32 , // PSRAM bandwidth may be not enough if burst size is 64
481+ };
482+
483+ [[maybe_unused ]] async_memcpy_handle_t driver [2 ] = {NULL };
484+
485+ #if SOC_AHB_GDMA_SUPPORTED && SOC_AHB_GDMA_SUPPORT_PSRAM
486+ driver_config .weight = 1 ;
487+ TEST_ESP_OK (esp_async_memcpy_install_gdma_ahb (& driver_config , & driver [0 ]));
488+ driver_config .weight = 15 ;
489+ TEST_ESP_OK (esp_async_memcpy_install_gdma_ahb (& driver_config , & driver [1 ]));
490+ memcpy_weighted_arb_test (driver , driver_config .dma_burst_size , 200 * 1024 , true);
491+ TEST_ESP_OK (esp_async_memcpy_uninstall (driver [0 ]));
492+ TEST_ESP_OK (esp_async_memcpy_uninstall (driver [1 ]));
493+ #endif // SOC_AHB_GDMA_SUPPORTED && SOC_AHB_GDMA_SUPPORT_PSRAM
494+ }
495+ #endif // SOC_SPIRAM_SUPPORTED
496+
497+ #endif // CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
0 commit comments