test_spiram_cache_flush.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. This code tests the interaction between PSRAM and SPI flash routines.
  8. */
  9. #include <esp_types.h>
  10. #include <stdio.h>
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/task.h"
  13. #include "freertos/semphr.h"
  14. #include "freertos/queue.h"
  15. #include "freertos/xtensa_api.h"
  16. #include "unity.h"
  17. #include <stdint.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include "esp_heap_caps.h"
  22. #include "esp_spi_flash.h"
  23. #include "esp_partition.h"
  24. #include "test_utils.h"
  25. #include "soc/soc.h"
  26. #if CONFIG_SPIRAM
  27. #if CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC
  28. #define USE_CAPS_ALLOC 1
  29. #endif // CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC
  30. #define TSTSZ (16*1024)
  31. #if !CONFIG_FREERTOS_UNICORE
  32. volatile static int res[2], err[2];
  33. void tstMem(void *arg) {
  34. volatile unsigned char *mem=(volatile unsigned char*)arg;
  35. int p=0;
  36. while(1) {
  37. for (int i=0; i<TSTSZ; i++) {
  38. mem[i]=(i^p);
  39. }
  40. for (int i=0; i<TSTSZ; i++) {
  41. if (mem[i]!=((i^p)&0xff)) {
  42. printf("Core %d mem err! Got %x espected %x at addr %p\n", xPortGetCoreID(), mem[i], (i^p)&0xff, &mem[i]);
  43. err[xPortGetCoreID()]++;
  44. }
  45. }
  46. p++;
  47. res[xPortGetCoreID()]++;
  48. }
  49. }
  50. TEST_CASE("Spiram cache flush on mmap", "[spiram]")
  51. {
  52. void *mem[2];
  53. res[0]=0; res[1]=0;
  54. #if USE_CAPS_ALLOC
  55. printf("Allocating SPI RAM chunk...\n");
  56. mem[0]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
  57. mem[1]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
  58. #else
  59. mem[0]=(void*)SOC_EXTRAM_DATA_LOW;
  60. mem[1]=(void*)SOC_EXTRAM_DATA_LOW+TSTSZ;
  61. #endif
  62. assert(mem[0]);
  63. assert(mem[1]);
  64. TaskHandle_t th[2];
  65. err[0]=0; err[1]=0;
  66. printf("Creating tasks\n");
  67. xTaskCreatePinnedToCore(tstMem , "tskone" , 2048, mem[0], 3, &th[0], 0);
  68. xTaskCreatePinnedToCore(tstMem , "tsktwo" , 2048, mem[1], 3, &th[1], 1);
  69. for (int l=0; l<10; l++) {
  70. for (int p=0; p<4096*1024; p+=65536) {
  71. const void *out;
  72. spi_flash_mmap_handle_t h;
  73. spi_flash_mmap(p, 65536, SPI_FLASH_MMAP_DATA, &out, &h);
  74. spi_flash_munmap(h);
  75. }
  76. }
  77. printf("Checked memory %d and %d times. Errors: %d and %d\n", res[0], res[1], err[0], err[1]);
  78. vTaskDelete(th[0]);
  79. vTaskDelete(th[1]);
  80. #if USE_CAPS_ALLOC
  81. free(mem[0]);
  82. free(mem[1]);
  83. #endif
  84. TEST_ASSERT(err[0]==0);
  85. TEST_ASSERT(err[1]==0);
  86. }
  87. #define CYCLES 1024
  88. TEST_CASE("Spiram cache flush on write/read", "[spiram]")
  89. {
  90. void *mem[2];
  91. res[0]=0; res[1]=0;
  92. #if USE_CAPS_ALLOC
  93. printf("Allocating SPI RAM chunk...\n");
  94. mem[0]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
  95. mem[1]=heap_caps_malloc(TSTSZ, MALLOC_CAP_SPIRAM);
  96. #else
  97. mem[0]=(void*)SOC_EXTRAM_DATA_LOW;
  98. mem[1]=(void*)SOC_EXTRAM_DATA_LOW+TSTSZ;
  99. #endif
  100. assert(mem[0]);
  101. assert(mem[1]);
  102. TaskHandle_t th[2];
  103. const esp_partition_t* part = get_test_data_partition();
  104. assert(part!=NULL);
  105. printf("Erasing sector...\n");
  106. esp_partition_erase_range(part, 0, 64*1024);
  107. printf("Erased.\n");
  108. printf("Creating tasks\n");
  109. xTaskCreatePinnedToCore(tstMem , "tskone" , 2048, mem[0], 3, &th[0], 0);
  110. xTaskCreatePinnedToCore(tstMem , "tsktwo" , 2048, mem[1], 3, &th[1], 1);
  111. char buf[512];
  112. const void *out;
  113. spi_flash_mmap_handle_t handle;
  114. esp_partition_mmap(part, 0, 512, SPI_FLASH_MMAP_DATA, &out, &handle);
  115. for (int i=0; i<CYCLES; i++) {
  116. esp_partition_write(part, 0, buf, 512);
  117. esp_partition_read(part, 0, buf, 512);
  118. vTaskDelay(1);
  119. }
  120. spi_flash_munmap(handle);
  121. printf("Checked memory %d and %d times.\n", res[0], res[1]);
  122. vTaskDelete(th[0]);
  123. vTaskDelete(th[1]);
  124. #if USE_CAPS_ALLOC
  125. free(mem[0]);
  126. free(mem[1]);
  127. #endif
  128. }
  129. #endif // !CONFIG_FREERTOS_UNICORE
  130. IRAM_ATTR TEST_CASE("Spiram memcmp weirdness at 80MHz", "[spiram]") {
  131. char *mem1=malloc(0x10000);
  132. #if USE_CAPS_ALLOC
  133. char *mem2=heap_caps_malloc(0x10000, MALLOC_CAP_SPIRAM);
  134. #else
  135. char *mem2=(void*)SOC_EXTRAM_DATA_LOW;
  136. #endif
  137. #if !CONFIG_SPIRAM_SPEED_80M
  138. printf("**** WARNING **** Spi memory isn't running at 80MHz, so this test is somewhat meaningless.\n");
  139. #endif
  140. printf("RAM: Got %p and %p\n", mem1, mem2);
  141. assert(mem1);
  142. assert(mem2);
  143. for (int i=0; i<0x10000; i++) mem1[i]=i^0xAAAAAAAA;
  144. for (int cycle=1; cycle<100; cycle++) {
  145. memcpy(mem2, mem1, 0x10000);
  146. if (memcmp(mem1, mem2, 0x10000)!=0) {
  147. printf("Memcmp failed! Cycle %d\n", cycle);
  148. for (int i=0; i<0x10000; i++) {
  149. if (mem1[i]!=mem2[i]) {
  150. printf("Found real difference at index %d: 0x%x vs 0x%x\n", i, mem1[i], mem2[i]);
  151. break;
  152. }
  153. }
  154. }
  155. }
  156. free(mem1);
  157. #if USE_CAPS_ALLOC
  158. free(mem2);
  159. #endif
  160. }
  161. #endif // CONFIG_SPIRAM