test_himem.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "unity.h"
  7. #include <stdio.h>
  8. #include <stdbool.h>
  9. #include <stdint.h>
  10. #include "inttypes.h"
  11. #include "freertos/FreeRTOS.h"
  12. #include "freertos/task.h"
  13. #include "esp_system.h"
  14. #include "esp32/rom/cache.h"
  15. #include "sdkconfig.h"
  16. #if CONFIG_IDF_TARGET_ESP32
  17. #include "esp32/himem.h"
  18. #if CONFIG_SPIRAM_BANKSWITCH_ENABLE
  19. //Fill memory with pseudo-random data generated from the given seed.
  20. static void fill_mem_seed(int seed, void *mem, int len)
  21. {
  22. uint32_t *p = (uint32_t *)mem;
  23. unsigned int rseed = seed ^ 0xa5a5a5a5;
  24. for (int i = 0; i < len / 4; i++) {
  25. *p++ = rand_r(&rseed);
  26. }
  27. }
  28. //Check the memory filled by fill_mem_seed. Returns true if the data is still intact.
  29. static bool check_mem_seed(int seed, void *mem, int len)
  30. {
  31. uint32_t *p = (uint32_t *)mem;
  32. unsigned int rseed = seed ^ 0xa5a5a5a5;
  33. for (int i = 0; i < len / 4; i++) {
  34. uint32_t ex = rand_r(&rseed);
  35. if (ex != *p) {
  36. printf("check_mem_seed: %p @ %p has 0x%08"PRIx32" expected 0x%08"PRIx32"\n", mem, p, *p, ex);
  37. return false;
  38. }
  39. p++;
  40. }
  41. return true;
  42. }
  43. //Allocate a himem region, fill it with data, check it and release it.
  44. static bool test_region(int check_size, int seed)
  45. {
  46. esp_himem_handle_t mh;
  47. esp_himem_rangehandle_t rh;
  48. bool ret = true;
  49. ESP_ERROR_CHECK(esp_himem_alloc(check_size, &mh));
  50. ESP_ERROR_CHECK(esp_himem_alloc_map_range(ESP_HIMEM_BLKSZ * 2, &rh));
  51. for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
  52. uint32_t *ptr = NULL;
  53. ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
  54. fill_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ);
  55. ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
  56. }
  57. for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
  58. uint32_t *ptr;
  59. ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
  60. if (!check_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ)) {
  61. printf("Error in block %d\n", i / ESP_HIMEM_BLKSZ);
  62. ret = false;
  63. break;
  64. }
  65. ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
  66. }
  67. ESP_ERROR_CHECK(esp_himem_free(mh));
  68. ESP_ERROR_CHECK(esp_himem_free_map_range(rh));
  69. return ret;
  70. }
  71. static volatile int testsDone;
  72. static void memtest_thread(void *arg)
  73. {
  74. int d = (int)arg;
  75. for (int i = 0; i < 4; i++) {
  76. printf("d=%d check=%d\n", d, i);
  77. test_region(2 * 1024 * 1024, d + (i << 16));
  78. vTaskDelay(d);
  79. }
  80. testsDone++; //note possible race here... not really an issue if the two tasks have different vTaskDelay args
  81. vTaskDelete(NULL);
  82. }
  83. TEST_CASE("high psram memory test", "[himem]")
  84. {
  85. printf("Doing single-core test\n");
  86. assert(test_region(4 * 1024 * 1024, 0xaaaa));
  87. testsDone = 0;
  88. printf("Doing dual-core test...\n");
  89. xTaskCreatePinnedToCore(&memtest_thread, "th2", 1024 * 2, (void *)2, 5, NULL, 1);
  90. xTaskCreatePinnedToCore(&memtest_thread, "th1", 1024 * 2, (void *)5, 5, NULL, 0);
  91. while (testsDone != 2) {
  92. vTaskDelay(10);
  93. }
  94. printf("Done!\n");
  95. vTaskDelay(100);
  96. }
  97. #endif
  98. #endif // CONFIG_IDF_TARGET_ESP32