test_async_memcpy.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/param.h>
  5. #include "esp_heap_caps.h"
  6. #include "esp_rom_sys.h"
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "freertos/semphr.h"
  10. #include "unity.h"
  11. #include "test_utils.h"
  12. #include "ccomp_timer.h"
  13. #include "esp_async_memcpy.h"
  14. #include "soc/soc_caps.h"
  15. #if SOC_CP_DMA_SUPPORTED || SOC_GDMA_SUPPORTED
  16. #define ALIGN_UP(addr, align) (((addr) + (align)-1) & ~((align)-1))
  17. static void async_memcpy_setup_testbench(uint32_t seed, uint32_t *buffer_size, uint8_t **src_buf, uint8_t **dst_buf, uint8_t **from_addr, uint8_t **to_addr, uint32_t align)
  18. {
  19. srand(seed);
  20. printf("allocating memory buffer...\r\n");
  21. // memory copy from/to PSRAM is not allowed
  22. *src_buf = heap_caps_malloc(*buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
  23. *dst_buf = heap_caps_calloc(1, *buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
  24. TEST_ASSERT_NOT_NULL_MESSAGE(*src_buf, "allocate source buffer failed");
  25. TEST_ASSERT_NOT_NULL_MESSAGE(*dst_buf, "allocate destination buffer failed");
  26. *from_addr = (uint8_t *)ALIGN_UP((uint32_t)(*src_buf), 4);
  27. *to_addr = (uint8_t *)ALIGN_UP((uint32_t)(*dst_buf), 4);
  28. uint8_t gap = MAX(*from_addr - *src_buf, *to_addr - *dst_buf);
  29. *buffer_size -= gap;
  30. *from_addr += align;
  31. *to_addr += align;
  32. *buffer_size -= align;
  33. printf("...size %d Bytes, src@%p, dst@%p\r\n", *buffer_size, *from_addr, *to_addr);
  34. printf("fill src buffer with random data\r\n");
  35. for (int i = 0; i < *buffer_size; i++) {
  36. (*from_addr)[i] = rand() % 256;
  37. }
  38. }
  39. static void async_memcpy_verify_and_clear_testbench(uint32_t seed, uint32_t buffer_size, uint8_t *src_buf, uint8_t *dst_buf, uint8_t *from_addr, uint8_t *to_addr)
  40. {
  41. srand(seed);
  42. for (int i = 0; i < buffer_size; i++) {
  43. // check if source date has been copied to destination and source data not broken
  44. TEST_ASSERT_EQUAL_MESSAGE(rand() % 256, to_addr[i], "destination data doesn't match generator data");
  45. }
  46. srand(seed);
  47. for (int i = 0; i < buffer_size; i++) {
  48. // check if source data has been copied to destination
  49. TEST_ASSERT_EQUAL_MESSAGE(rand() % 256, to_addr[i], "destination data doesn't match source data");
  50. }
  51. free(src_buf);
  52. free(dst_buf);
  53. }
  54. TEST_CASE("memory copy by DMA one by one", "[async mcp]")
  55. {
  56. async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG();
  57. config.backlog = 4;
  58. async_memcpy_t driver = NULL;
  59. TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
  60. uint32_t test_buffer_len[] = {256, 512, 1024, 2048, 4096, 5011};
  61. uint8_t *sbuf = NULL;
  62. uint8_t *dbuf = NULL;
  63. uint8_t *from = NULL;
  64. uint8_t *to = NULL;
  65. for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
  66. // Test different align edge
  67. for (int align = 0; align < 4; align++) {
  68. async_memcpy_setup_testbench(i, &test_buffer_len[i], &sbuf, &dbuf, &from, &to, align);
  69. TEST_ESP_OK(esp_async_memcpy(driver, to, from, test_buffer_len[i], NULL, NULL));
  70. async_memcpy_verify_and_clear_testbench(i, test_buffer_len[i], sbuf, dbuf, from, to);
  71. vTaskDelay(pdMS_TO_TICKS(100));
  72. }
  73. }
  74. TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
  75. }
  76. TEST_CASE("memory copy by DMA on the fly", "[async mcp]")
  77. {
  78. async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG();
  79. async_memcpy_t driver = NULL;
  80. TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
  81. uint32_t test_buffer_len[] = {512, 1024, 2048, 4096, 5011};
  82. uint8_t *sbufs[] = {0, 0, 0, 0, 0};
  83. uint8_t *dbufs[] = {0, 0, 0, 0, 0};
  84. uint8_t *froms[] = {0, 0, 0, 0, 0};
  85. uint8_t *tos[] = {0, 0, 0, 0, 0};
  86. // Aligned case
  87. for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) {
  88. async_memcpy_setup_testbench(i, &test_buffer_len[i], &sbufs[i], &dbufs[i], &froms[i], &tos[i], 0);
  89. }
  90. for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
  91. TEST_ESP_OK(esp_async_memcpy(driver, tos[i], froms[i], test_buffer_len[i], NULL, NULL));
  92. }
  93. for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) {
  94. async_memcpy_verify_and_clear_testbench(i, test_buffer_len[i], sbufs[i], dbufs[i], froms[i], tos[i]);
  95. }
  96. // Non-aligned case
  97. for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) {
  98. async_memcpy_setup_testbench(i, &test_buffer_len[i], &sbufs[i], &dbufs[i], &froms[i], &tos[i], 3);
  99. }
  100. for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
  101. TEST_ESP_OK(esp_async_memcpy(driver, tos[i], froms[i], test_buffer_len[i], NULL, NULL));
  102. }
  103. for (int i = 0; i < sizeof(sbufs) / sizeof(sbufs[0]); i++) {
  104. async_memcpy_verify_and_clear_testbench(i, test_buffer_len[i], sbufs[i], dbufs[i], froms[i], tos[i]);
  105. }
  106. TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
  107. }
  108. #define TEST_ASYNC_MEMCPY_BENCH_COUNTS (16)
  109. static uint32_t test_async_memcpy_bench_len = 4095;
  110. static int count = 0;
  111. static IRAM_ATTR bool test_async_memcpy_isr_cb(async_memcpy_t mcp_hdl, async_memcpy_event_t *event, void *cb_args)
  112. {
  113. SemaphoreHandle_t sem = (SemaphoreHandle_t)cb_args;
  114. BaseType_t high_task_wakeup = pdFALSE;
  115. count++;
  116. if (count == TEST_ASYNC_MEMCPY_BENCH_COUNTS) {
  117. xSemaphoreGiveFromISR(sem, &high_task_wakeup);
  118. }
  119. return high_task_wakeup == pdTRUE;
  120. }
  121. TEST_CASE("memory copy by DMA with callback", "[async mcp]")
  122. {
  123. SemaphoreHandle_t sem = xSemaphoreCreateBinary();
  124. async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG();
  125. config.backlog = TEST_ASYNC_MEMCPY_BENCH_COUNTS;
  126. async_memcpy_t driver = NULL;
  127. TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
  128. uint8_t *sbuf = NULL;
  129. uint8_t *dbuf = NULL;
  130. uint8_t *from = NULL;
  131. uint8_t *to = NULL;
  132. async_memcpy_setup_testbench(0, &test_async_memcpy_bench_len, &sbuf, &dbuf, &from, &to, 0);
  133. count = 0;
  134. ccomp_timer_start();
  135. for (int i = 0; i < TEST_ASYNC_MEMCPY_BENCH_COUNTS; i++) {
  136. TEST_ESP_OK(esp_async_memcpy(driver, to, from, test_async_memcpy_bench_len, test_async_memcpy_isr_cb, sem));
  137. }
  138. // wait for done semaphore
  139. TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(sem, pdMS_TO_TICKS(1000)));
  140. esp_rom_printf("memcpy %d Bytes data by HW costs %lldus\r\n", test_async_memcpy_bench_len, ccomp_timer_stop() / TEST_ASYNC_MEMCPY_BENCH_COUNTS);
  141. ccomp_timer_start();
  142. for (int i = 0; i < TEST_ASYNC_MEMCPY_BENCH_COUNTS; i++) {
  143. memcpy(to, from, test_async_memcpy_bench_len);
  144. }
  145. esp_rom_printf("memcpy %d Bytes data by SW costs %lldus\r\n", test_async_memcpy_bench_len, ccomp_timer_stop() / TEST_ASYNC_MEMCPY_BENCH_COUNTS);
  146. async_memcpy_verify_and_clear_testbench(0, test_async_memcpy_bench_len, sbuf, dbuf, from, to);
  147. TEST_ESP_OK(esp_async_memcpy_uninstall(driver));
  148. vSemaphoreDelete(sem);
  149. }
  150. #endif //SOC_CP_DMA_SUPPORTED || SOC_GDMA_SUPPORTED