memory_layout.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdlib.h>
  7. #include <stdint.h>
  8. #include "sdkconfig.h"
  9. #include "soc/soc.h"
  10. #include "soc/tracemem_config.h"
  11. #include "heap_memory_layout.h"
  12. #include "esp_heap_caps.h"
  13. /* Memory layout for ESP32 SoC */
  14. /*
  15. Memory type descriptors. These describe the capabilities of a type of memory in the SoC. Each type of memory
  16. map consist of one or more regions in the address space.
  17. Each type contains an array of prioritised capabilities; types with later entries are only taken if earlier
  18. ones can't fulfill the memory request.
  19. The prioritised capabilities work roughly like this:
  20. - For a normal malloc (MALLOC_CAP_DEFAULT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions,
  21. finally eat into the application memory.
  22. - For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM.
  23. - Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM.
  24. - Most other malloc caps only fit in one region anyway.
  25. */
  26. enum {
  27. SOC_MEMORY_TYPE_DIRAM = 0,
  28. SOC_MEMORY_TYPE_SPIRAM = 1,
  29. SOC_MEMORY_TYPE_RTCRAM = 2,
  30. SOC_MEMORY_TYPE_NUM,
  31. };
  32. /* COMMON_CAPS is the set of attributes common to all types of memory on this chip */
  33. #define ESP32S2_MEM_COMMON_CAPS (MALLOC_CAP_DEFAULT | MALLOC_CAP_32BIT | MALLOC_CAP_8BIT)
  34. #ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
  35. #define MALLOC_DIRAM_BASE_CAPS ESP32S2_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA
  36. #define MALLOC_RTCRAM_BASE_CAPS ESP32S2_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL
  37. #else
  38. #define MALLOC_DIRAM_BASE_CAPS ESP32S2_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_EXEC
  39. #define MALLOC_RTCRAM_BASE_CAPS ESP32S2_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_EXEC
  40. #endif
  41. /**
  42. * Defined the attributes and allocation priority of each memory on the chip,
  43. * The heap allocator will traverse all types of memory types in column High Priority Matching and match the specified caps at first,
  44. * if no memory caps matched or the allocation is failed, it will go to columns Medium Priorty Matching and Low Priority Matching
  45. * in turn to continue matching.
  46. */
  47. const soc_memory_type_desc_t soc_memory_types[] = {
  48. /* Mem Type Name | High Priority Matching | Medium Priorty Matching | Low Priority Matching */
  49. [SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS, 0, 0 }},
  50. //TODO, in fact, part of them support EDMA, to be supported.
  51. [SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, ESP32S2_MEM_COMMON_CAPS, 0 }},
  52. [SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS }},
  53. };
  54. const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
  55. /*
  56. Region descriptors. These describe all regions of memory available, and map them to a type in the above type.
  57. Because of requirements in the coalescing code which merges adjacent regions, this list should always be sorted
  58. from low to high start address.
  59. */
  60. const soc_memory_region_t soc_memory_regions[] = {
  61. #ifdef CONFIG_SPIRAM
  62. { SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_SIZE, SOC_MEMORY_TYPE_SPIRAM, 0, false}, //SPI SRAM, if available
  63. #endif
  64. #if CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB
  65. #if CONFIG_ESP32S2_DATA_CACHE_0KB
  66. { 0x3FFB2000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40022000, false}, //Block 1, can be use as I/D cache memory
  67. { 0x3FFB4000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40024000, false}, //Block 2, can be use as D cache memory
  68. { 0x3FFB6000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40026000, false}, //Block 3, can be use as D cache memory
  69. #elif CONFIG_ESP32S2_DATA_CACHE_8KB
  70. { 0x3FFB4000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40024000, false}, //Block 2, can be use as D cache memory
  71. { 0x3FFB6000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40026000, false}, //Block 3, can be use as D cache memory
  72. #else
  73. { 0x3FFB6000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40026000, false}, //Block 3, can be use as D cache memory
  74. #endif
  75. #else
  76. #if CONFIG_ESP32S2_DATA_CACHE_0KB
  77. { 0x3FFB4000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40024000, false}, //Block 3, can be use as D cache memory
  78. { 0x3FFB6000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40026000, false}, //Block 3, can be use as D cache memory
  79. #elif CONFIG_ESP32S2_DATA_CACHE_8KB
  80. { 0x3FFB6000, 0x2000, SOC_MEMORY_TYPE_DIRAM, 0x40026000, false}, //Block 3, can be use as D cache memory
  81. #endif
  82. #endif
  83. { 0x3FFB8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40028000, false}, //Block 4, can be remapped to ROM, can be used as trace memory
  84. { 0x3FFBC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4002C000, false}, //Block 5, can be remapped to ROM, can be used as trace memory
  85. { 0x3FFC0000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40030000, false}, //Block 6, can be used as trace memory
  86. { 0x3FFC4000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40034000, false}, //Block 7, can be used as trace memory
  87. { 0x3FFC8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40038000, false}, //Block 8, can be used as trace memory
  88. { 0x3FFCC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4003C000, false}, //Block 9, can be used as trace memory
  89. { 0x3FFD0000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40040000, false}, //Block 10, can be used as trace memory
  90. { 0x3FFD4000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40044000, false}, //Block 11, can be used as trace memory
  91. { 0x3FFD8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40048000, false}, //Block 12, can be used as trace memory
  92. { 0x3FFDC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4004C000, false}, //Block 13, can be used as trace memory
  93. { 0x3FFE0000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40050000, false}, //Block 14, can be used as trace memory
  94. { 0x3FFE4000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40054000, false}, //Block 15, can be used as trace memory
  95. { 0x3FFE8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40058000, false}, //Block 16, can be used as trace memory
  96. { 0x3FFEC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4005C000, false}, //Block 17, can be used as trace memory
  97. { 0x3FFF0000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40060000, false}, //Block 18, can be used for MAC dump, can be used as trace memory
  98. { 0x3FFF4000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40064000, false}, //Block 19, can be used for MAC dump, can be used as trace memory
  99. { 0x3FFF8000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x40068000, false}, //Block 20, can be used for MAC dump, can be used as trace memory
  100. { 0x3FFFC000, 0x4000, SOC_MEMORY_TYPE_DIRAM, 0x4006C000, true}, //Block 21, can be used for MAC dump, can be used as trace memory, used for startup stack
  101. #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
  102. { SOC_RTC_DRAM_LOW, 0x2000, SOC_MEMORY_TYPE_RTCRAM, 0, false}, //RTC Fast Memory
  103. #endif
  104. };
  105. const size_t soc_memory_region_count = sizeof(soc_memory_regions)/sizeof(soc_memory_region_t);
  106. extern int _dram0_rtos_reserved_start;
  107. extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end;
  108. extern int _rtc_reserved_start, _rtc_reserved_end;
  109. /* Reserved memory regions
  110. These are removed from the soc_memory_regions array when heaps are created.
  111. */
  112. //ROM data region
  113. SOC_RESERVE_MEMORY_REGION((intptr_t)&_dram0_rtos_reserved_start, SOC_BYTE_ACCESSIBLE_HIGH, rom_data_region);
  114. // Static data region. DRAM used by data+bss and possibly rodata
  115. SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data);
  116. // ESP32S2 has a big D/IRAM region, the part used by code is reserved
  117. // The address of the D/I bus are in the same order, directly shift IRAM address to get reserved DRAM address
  118. #define I_D_OFFSET (SOC_IRAM_LOW - SOC_DRAM_LOW)
  119. SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start - I_D_OFFSET, (intptr_t)&_iram_end - I_D_OFFSET, iram_code);
  120. #ifdef CONFIG_SPIRAM
  121. /* Reserve the whole possible SPIRAM region here, spiram.c will add some or all of this
  122. * memory to heap depending on the actual SPIRAM chip size. */
  123. SOC_RESERVE_MEMORY_REGION( SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH, extram_data_region);
  124. #endif
  125. // Blocks 19 and 20 may be reserved for the trace memory
  126. #if CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM > 0
  127. SOC_RESERVE_MEMORY_REGION(TRACEMEM_BLK0_ADDR, TRACEMEM_BLK0_ADDR + CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM / 2, trace_mem0);
  128. SOC_RESERVE_MEMORY_REGION(TRACEMEM_BLK1_ADDR, TRACEMEM_BLK1_ADDR + CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM / 2, trace_mem1);
  129. #endif
  130. // RTC Fast RAM region
  131. #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
  132. #ifdef CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM
  133. SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_noinit_end, rtcram_data);
  134. #else
  135. SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_fast_end, rtcram_data);
  136. #endif
  137. #endif
  138. SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data);