mmu.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * This file will be redesigned into MMU driver, to maintain all the external
  8. * memory contexts including:
  9. * - Flash
  10. * - PSRAM
  11. * - DDR
  12. *
  13. * Now only MMU-PSRAM related private APIs
  14. */
  15. #include <stdint.h>
  16. #include <sys/param.h>
  17. #include "sdkconfig.h"
  18. #include "esp_attr.h"
  19. #include "esp_log.h"
  20. #include "soc/ext_mem_defs.h"
  21. #include "esp_private/mmu.h"
  22. #if CONFIG_IDF_TARGET_ESP32S2
  23. #include "soc/extmem_reg.h"
  24. #include "esp32s2/rom/cache.h"
  25. #elif CONFIG_IDF_TARGET_ESP32S3
  26. #include "soc/extmem_reg.h"
  27. #include "esp32s3/rom/cache.h"
  28. #endif
  29. #define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
  30. __attribute__((unused)) static const char *TAG = "mmu";
  31. extern int _instruction_reserved_start;
  32. extern int _instruction_reserved_end;
  33. extern int _rodata_reserved_start;
  34. extern int _rodata_reserved_end;
  35. intptr_t mmu_get_psram_vaddr_start(void)
  36. {
  37. #if CONFIG_IDF_TARGET_ESP32S3
  38. intptr_t rodata_end_aligned = ALIGN_UP_BY((intptr_t)&_rodata_reserved_end, MMU_PAGE_SIZE);
  39. ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned);
  40. return rodata_end_aligned;
  41. #elif CONFIG_IDF_TARGET_ESP32S2
  42. return DPORT_CACHE_ADDRESS_LOW;
  43. #else //CONFIG_IDF_TARGET_ESP32
  44. return DRAM1_CACHE_ADDRESS_LOW;
  45. #endif
  46. }
  47. intptr_t mmu_get_psram_vaddr_end(void)
  48. {
  49. #if CONFIG_IDF_TARGET_ESP32S3
  50. return DRAM0_CACHE_ADDRESS_HIGH;
  51. #elif CONFIG_IDF_TARGET_ESP32S2
  52. return DRAM0_CACHE_ADDRESS_HIGH;
  53. #else //CONFIG_IDF_TARGET_ESP32
  54. return DRAM1_CACHE_ADDRESS_HIGH;
  55. #endif
  56. }
  57. //------------------------------------Copy Flash .text to PSRAM-------------------------------------//
  58. #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
  59. static uint32_t instruction_in_spiram;
  60. static uint32_t instr_start_page;
  61. static uint32_t instr_end_page;
  62. static int instr_flash2spiram_offs;
  63. /**
  64. * - These logics are abstracted from the PSRAM driver
  65. * - These functions are only required by `flash_mmap.c` for converting paddr to vaddr, and vice versa
  66. * - The `flash_mmpa.c` will be rewritten into MMU driver
  67. *
  68. * Therefore, keep the APIs here for now
  69. */
  70. void instruction_flash_page_info_init(uint32_t psram_start_physical_page)
  71. {
  72. #if CONFIG_IDF_TARGET_ESP32S2
  73. uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - (uint32_t)&_instruction_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
  74. uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
  75. instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset];
  76. #elif CONFIG_IDF_TARGET_ESP32S3
  77. uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
  78. instr_start_page = *((volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START));
  79. #endif
  80. instr_start_page &= MMU_VALID_VAL_MASK;
  81. instr_end_page = instr_start_page + instr_page_cnt - 1;
  82. instr_flash2spiram_offs = instr_start_page - psram_start_physical_page;
  83. instruction_in_spiram = 1;
  84. ESP_DRAM_LOGV("mmu_psram", "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", instr_start_page, psram_start_physical_page, instr_flash2spiram_offs);
  85. }
  86. uint32_t esp_spiram_instruction_access_enabled(void)
  87. {
  88. return instruction_in_spiram;
  89. }
  90. int instruction_flash2spiram_offset(void)
  91. {
  92. return instr_flash2spiram_offs;
  93. }
  94. uint32_t instruction_flash_start_page_get(void)
  95. {
  96. return instr_start_page;
  97. }
  98. uint32_t instruction_flash_end_page_get(void)
  99. {
  100. return instr_end_page;
  101. }
  102. #endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS
  103. #if CONFIG_SPIRAM_RODATA
  104. //------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
  105. static uint32_t rodata_in_spiram;
  106. static int rodata_flash2spiram_offs;
  107. static uint32_t rodata_start_page;
  108. static uint32_t rodata_end_page;
  109. /**
  110. * - These logics are abstracted from the PSRAM driver
  111. * - These functions are only required by `flash_mmap.c` for converting paddr to vaddr, and vice versa
  112. * - The `flash_mmpa.c` will be rewritten into MMU driver
  113. *
  114. * Therefore, keep the APIs here for now
  115. */
  116. void rodata_flash_page_info_init(uint32_t psram_start_physical_page)
  117. {
  118. #if CONFIG_IDF_TARGET_ESP32S2
  119. uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - (uint32_t)&_rodata_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
  120. uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
  121. rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset];
  122. #elif CONFIG_IDF_TARGET_ESP32S3
  123. uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
  124. rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
  125. #endif
  126. rodata_start_page &= MMU_VALID_VAL_MASK;
  127. rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
  128. rodata_flash2spiram_offs = rodata_start_page - psram_start_physical_page;
  129. rodata_in_spiram = 1;
  130. ESP_DRAM_LOGV("mmu_psram", "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", rodata_start_page, psram_start_physical_page, rodata_flash2spiram_offs);
  131. }
  132. uint32_t esp_spiram_rodata_access_enabled(void)
  133. {
  134. return rodata_in_spiram;
  135. }
  136. int rodata_flash2spiram_offset(void)
  137. {
  138. return rodata_flash2spiram_offs;
  139. }
  140. uint32_t rodata_flash_start_page_get(void)
  141. {
  142. return rodata_start_page;
  143. }
  144. uint32_t rodata_flash_end_page_get(void)
  145. {
  146. return rodata_end_page;
  147. }
  148. #endif //#if CONFIG_SPIRAM_RODATA