himem_memory_check.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // need [env:esp32cam-dev-himem]
  2. //CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
  3. //CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
  4. #include "../../include/defines.h"
  5. #ifdef DEBUG_HIMEM_MEMORY_CHECK
  6. #include "himem_memory_check.h"
  7. //source adapted from : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c
  8. //Fill memory with pseudo-random data generated from the given seed.
  9. //Fills the memory in 32-bit words for speed.
  10. static void fill_mem_seed(int seed, void *mem, int len)
  11. {
  12. uint32_t *p = (uint32_t *)mem;
  13. unsigned int rseed = seed ^ 0xa5a5a5a5;
  14. for (int i = 0; i < len / 4; i++) {
  15. *p++ = rand_r(&rseed);
  16. }
  17. }
  18. //Check the memory filled by fill_mem_seed. Returns true if the data matches the data
  19. //that fill_mem_seed wrote (when given the same seed).
  20. //Returns true if there's a match, false when the region differs from what should be there.
  21. static bool check_mem_seed(int seed, void *mem, int len, int phys_addr)
  22. {
  23. uint32_t *p = (uint32_t *)mem;
  24. unsigned int rseed = seed ^ 0xa5a5a5a5;
  25. for (int i = 0; i < len / 4; i++) {
  26. uint32_t ex = rand_r(&rseed);
  27. if (ex != *p) {
  28. //printf("check_mem_seed: %x has 0x%08"PRIx32" expected 0x%08"PRIx32"\n", phys_addr+((char*)p-(char*)mem), *p, ex);
  29. return false;
  30. }
  31. p++;
  32. }
  33. return true;
  34. }
  35. //Allocate a himem region, fill it with data, check it and release it.
  36. static bool test_region(int check_size, int seed)
  37. {
  38. esp_himem_handle_t mh; //Handle for the address space we're using
  39. esp_himem_rangehandle_t rh; //Handle for the actual RAM.
  40. bool ret = true;
  41. //Allocate the memory we're going to check.
  42. ESP_ERROR_CHECK(esp_himem_alloc(check_size, &mh));
  43. //Allocate a block of address range
  44. ESP_ERROR_CHECK(esp_himem_alloc_map_range(ESP_HIMEM_BLKSZ, &rh));
  45. for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
  46. uint32_t *ptr = NULL;
  47. //Map in block, write pseudo-random data, unmap block.
  48. ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
  49. fill_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ); //
  50. ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
  51. }
  52. vTaskDelay(5); //give the OS some time to do things so the task watchdog doesn't bark
  53. for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
  54. uint32_t *ptr;
  55. //Map in block, check against earlier written pseudo-random data, unmap block.
  56. ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
  57. if (!check_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ, i)) {
  58. //printf("Error in block %d\n", i / ESP_HIMEM_BLKSZ);
  59. ret = false;
  60. }
  61. ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
  62. if (!ret) break; //don't check rest of blocks if error occurred
  63. }
  64. //Okay, all done!
  65. ESP_ERROR_CHECK(esp_himem_free(mh));
  66. ESP_ERROR_CHECK(esp_himem_free_map_range(rh));
  67. return ret;
  68. }
  69. std::string himem_memory_check()
  70. {
  71. size_t memcnt=esp_himem_get_phys_size();
  72. size_t memfree=esp_himem_get_free_size();
  73. std::string espInfoResultStr = "";
  74. char aMsgBuf[40];
  75. espInfoResultStr += "Running HIMEM memory check";
  76. sprintf(aMsgBuf,"Himem has %dKiB of memory", (int)memcnt/1024);
  77. espInfoResultStr += std::string(aMsgBuf);
  78. sprintf(aMsgBuf,"%dKiB of which is free", (int)memfree/1024);
  79. espInfoResultStr += std::string(aMsgBuf);
  80. espInfoResultStr += "\n please wait ....\n";
  81. //running memory checks
  82. //assert(test_region(memfree, 0xaaaa));
  83. if(test_region(memfree, 0xaaaa)) {
  84. espInfoResultStr += "Himem check Failed!\n";
  85. } else {
  86. espInfoResultStr += "Himem check Done!\n";
  87. }
  88. return espInfoResultStr;
  89. }
  90. #endif // DEBUG_HIMEM_MEMORY_CHECK