psram.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "defines.h"
  2. #include "ClassLogFile.h"
  3. #include "psram.h"
  4. static const char *TAG = "PSRAM";
  5. using namespace std;
  6. void *shared_region = NULL;
  7. uint32_t allocatedBytesForSTBI = 0;
  8. std::string sharedMemoryInUseFor = "";
  9. /** Reserve a large block in the PSRAM which will be shared between the different steps.
  10. * Each step uses it differently but only wiuthin itself. */
  11. bool reserve_psram_shared_region(void)
  12. {
  13. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating shared PSRAM region (" + std::to_string(TENSOR_ARENA_SIZE + MAX_MODEL_SIZE) + " bytes)...");
  14. shared_region = malloc_psram_heap("Shared PSRAM region", TENSOR_ARENA_SIZE + MAX_MODEL_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  15. if (shared_region == NULL)
  16. {
  17. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocating shared PSRAM region!");
  18. return false;
  19. }
  20. else
  21. {
  22. return true;
  23. }
  24. }
  25. /*******************************************************************
  26. * Memory used in Take Image (STBI)
  27. *******************************************************************/
  28. bool psram_init_shared_memory_for_take_image_step(void)
  29. {
  30. if (sharedMemoryInUseFor != "")
  31. {
  32. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM already in use for " + sharedMemoryInUseFor + "!");
  33. return false;
  34. }
  35. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Init shared memory for step 'Take Image' (STBI buffers)");
  36. allocatedBytesForSTBI = 0;
  37. sharedMemoryInUseFor = "TakeImage";
  38. return true;
  39. }
  40. void psram_deinit_shared_memory_for_take_image_step(void)
  41. {
  42. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Deinit shared memory for step 'Take Image' (STBI buffers)");
  43. allocatedBytesForSTBI = 0;
  44. sharedMemoryInUseFor = "";
  45. }
  46. /*******************************************************************
  47. * Memory used in Aligning Step
  48. * During this step we only use the shared part of the PSRAM
  49. * for the TempImage.
  50. *******************************************************************/
  51. void *psram_reserve_shared_tmp_image_memory(void)
  52. {
  53. if (sharedMemoryInUseFor != "")
  54. {
  55. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM already in use for " + sharedMemoryInUseFor + "!");
  56. return NULL;
  57. }
  58. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating TempImage (" + std::to_string(IMAGE_SIZE) + " bytes, use shared memory in PSRAM)...");
  59. sharedMemoryInUseFor = "TempImage";
  60. return shared_region; // Use 1th part of the shared memory for the TempImage (only user)
  61. }
  62. void psram_free_shared_temp_image_memory(void)
  63. {
  64. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Shared memory used for TempImage (PSRAM, part of shared memory) is free again");
  65. sharedMemoryInUseFor = "";
  66. }
  67. /*******************************************************************
  68. *
  69. *******************************************************************/
  70. void *psram_reserve_shared_stbi_memory(size_t size)
  71. {
  72. /* Only large buffers should be placed in the shared PSRAM
  73. * If we also place all smaller STBI buffers here, we get artefacts for some reasons. */
  74. if (size >= 100000)
  75. {
  76. if ((allocatedBytesForSTBI + size) > TENSOR_ARENA_SIZE + MAX_MODEL_SIZE)
  77. {
  78. // Check if it still fits in the shared region
  79. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM too small (STBI) to fit additional " + std::to_string(size) + " bytes! Available: " + std::to_string(TENSOR_ARENA_SIZE + MAX_MODEL_SIZE - allocatedBytesForSTBI) + " bytes!");
  80. return NULL;
  81. }
  82. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating memory (" + std::to_string(size) + " bytes) for STBI (use shared memory in PSRAM)...");
  83. allocatedBytesForSTBI += size;
  84. return (uint8_t *)shared_region + allocatedBytesForSTBI - size;
  85. }
  86. else
  87. {
  88. // Normal PSRAM
  89. return malloc_psram_heap("STBI", size, MALLOC_CAP_SPIRAM);
  90. }
  91. }
  92. void *psram_reallocate_shared_stbi_memory(void *ptr, size_t newsize)
  93. {
  94. char buf[20];
  95. sprintf(buf, "%p", ptr);
  96. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "STBI requested realloc for " + std::string(buf) + " but this is currently unsupported!");
  97. return NULL;
  98. }
  99. void psram_free_shared_stbi_memory(void *p)
  100. {
  101. if ((p >= shared_region) && (p <= ((uint8_t *)shared_region + allocatedBytesForSTBI)))
  102. {
  103. // was allocated inside the shared memory
  104. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Part of shared memory used for STBI (PSRAM, part of shared memory) is free again");
  105. }
  106. else
  107. {
  108. // Normal PSRAM
  109. free_psram_heap("STBI", p);
  110. }
  111. }
  112. /*******************************************************************
  113. * Memory used in Digitization Steps
  114. * During this step we only use the shared part of the PSRAM for the
  115. * Tensor Arena and one of the Models.
  116. * The shared memory is large enough for the largest model and the
  117. * Tensor Arena. Therefore we do not need to monitor the usage.
  118. *******************************************************************/
  119. void *psram_get_shared_tensor_arena_memory(void)
  120. {
  121. if ((sharedMemoryInUseFor == "") || (sharedMemoryInUseFor == "Digitization_Model"))
  122. {
  123. sharedMemoryInUseFor = "Digitization_Tensor";
  124. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating Tensor Arena (" + std::to_string(TENSOR_ARENA_SIZE) + " bytes, use shared memory in PSRAM)...");
  125. return shared_region; // Use 1th part of the shared memory for Tensor
  126. }
  127. else
  128. {
  129. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM already in use for " + sharedMemoryInUseFor + "!");
  130. return NULL;
  131. }
  132. }
  133. void *psram_get_shared_model_memory(void)
  134. {
  135. if ((sharedMemoryInUseFor == "") || (sharedMemoryInUseFor == "Digitization_Tensor"))
  136. {
  137. sharedMemoryInUseFor = "Digitization_Model";
  138. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating Model memory (" + std::to_string(MAX_MODEL_SIZE) + " bytes, use shared memory in PSRAM)...");
  139. return (uint8_t *)shared_region + TENSOR_ARENA_SIZE; // Use 2nd part of the shared memory (after Tensor Arena) for the model
  140. }
  141. else
  142. {
  143. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM already in use for " + sharedMemoryInUseFor + "!");
  144. return NULL;
  145. }
  146. }
  147. void psram_free_shared_tensor_arena_and_model_memory(void)
  148. {
  149. sharedMemoryInUseFor = "";
  150. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Shared memory used for Tensor Arena and model (PSRAM, part of shared memory) is free again");
  151. }
  152. /*******************************************************************
  153. * General
  154. *******************************************************************/
  155. void *malloc_psram_heap(std::string name, size_t size, uint32_t caps)
  156. {
  157. void *ptr;
  158. ptr = heap_caps_malloc(size, caps);
  159. if (ptr != NULL)
  160. {
  161. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocated " + to_string(size) + " bytes in PSRAM for '" + name + "'");
  162. }
  163. else
  164. {
  165. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!");
  166. }
  167. return ptr;
  168. }
  169. void *realloc_psram_heap(std::string name, void *ptr, size_t size, uint32_t caps)
  170. {
  171. ptr = heap_caps_realloc(ptr, size, caps);
  172. if (ptr != NULL)
  173. {
  174. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Reallocated " + to_string(size) + " bytes in PSRAM for '" + name + "'");
  175. }
  176. else
  177. {
  178. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to reallocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!");
  179. }
  180. return ptr;
  181. }
  182. void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps)
  183. {
  184. void *ptr;
  185. ptr = heap_caps_calloc(n, size, caps);
  186. if (ptr != NULL)
  187. {
  188. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Allocated " + to_string(size) + " bytes in PSRAM for '" + name + "'");
  189. }
  190. else
  191. {
  192. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!");
  193. }
  194. return ptr;
  195. }
  196. void free_psram_heap(std::string name, void *ptr)
  197. {
  198. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Freeing memory in PSRAM used for '" + name + "'...");
  199. heap_caps_free(ptr);
  200. }