mmu_psram.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 <sys/param.h>
  16. #include "sdkconfig.h"
  17. #include "esp_log.h"
  18. #include "esp_attr.h"
  19. #include "soc/ext_mem_defs.h"
  20. #include "hal/cache_types.h"
  21. #include "hal/cache_ll.h"
  22. #include "esp_private/mmu.h"
  23. #if CONFIG_IDF_TARGET_ESP32S2
  24. #include "esp32s2/rom/cache.h"
  25. #elif CONFIG_IDF_TARGET_ESP32S3
  26. #include "esp32s3/rom/cache.h"
  27. #endif
  28. #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
  29. //page_size - 1, where page_size on s2 and s3 is always 0x10000. To be refactored by MMU driver
  30. #define INVALID_PHY_PAGE 0xffff
  31. const static char *TAG = "mmu_psram";
  32. //TODO IDF-4387
  33. static uint32_t page0_mapped = 0;
  34. static uint32_t page0_page = INVALID_PHY_PAGE;
  35. #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
  36. #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
  37. esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page)
  38. {
  39. uint32_t page_id = start_page;
  40. /**
  41. * TODO IDF-4387
  42. * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
  43. * FOR NOW, leave these logics just as it used to be.
  44. *
  45. * The rom API will be redesigned into a MMU driver layer function
  46. */
  47. uint32_t flash_pages = 0;
  48. #if CONFIG_IDF_TARGET_ESP32S2
  49. flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS0, &page0_mapped);
  50. flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS1, &page0_mapped);
  51. #elif CONFIG_IDF_TARGET_ESP32S3
  52. flash_pages += Cache_Count_Flash_Pages(CACHE_IBUS, &page0_mapped);
  53. #endif
  54. if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
  55. ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %d B, from %d B to %d B",
  56. MMU_PAGE_TO_BYTES(flash_pages), MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(flash_pages + page_id));
  57. return ESP_FAIL;
  58. }
  59. //Enable the most high bus, which is used for copying FLASH .text to PSRAM
  60. cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, SOC_EXTRAM_DATA_HIGH, 0);
  61. cache_ll_l1_enable_bus(0, bus_mask);
  62. #if !CONFIG_FREERTOS_UNICORE
  63. bus_mask = cache_ll_l1_get_bus(1, SOC_EXTRAM_DATA_HIGH, 0);
  64. cache_ll_l1_enable_bus(1, bus_mask);
  65. #endif
  66. instruction_flash_page_info_init(page_id);
  67. #if CONFIG_IDF_TARGET_ESP32S2
  68. page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, page_id, &page0_page);
  69. page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, page_id, &page0_page);
  70. #elif CONFIG_IDF_TARGET_ESP32S3
  71. page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page);
  72. #endif
  73. ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id);
  74. ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
  75. *out_page = page_id - start_page;
  76. return ESP_OK;
  77. }
  78. #endif //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
  79. #if CONFIG_SPIRAM_RODATA
  80. esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page)
  81. {
  82. uint32_t page_id = start_page;
  83. /**
  84. * TODO IDF-4387
  85. * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
  86. * FOR NOW, leave these logics just as it used to be.
  87. *
  88. * The rom API will be redesigned into a MMU driver layer function
  89. */
  90. uint32_t flash_pages = 0;
  91. #if CONFIG_IDF_TARGET_ESP32S2
  92. flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS2, &page0_mapped);
  93. flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS0, &page0_mapped);
  94. flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS1, &page0_mapped);
  95. flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS2, &page0_mapped);
  96. #elif CONFIG_IDF_TARGET_ESP32S3
  97. flash_pages += Cache_Count_Flash_Pages(CACHE_DBUS, &page0_mapped);
  98. #endif
  99. if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
  100. ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, need to copy to %d B.", MMU_PAGE_TO_BYTES(flash_pages + page_id));
  101. return ESP_FAIL;
  102. }
  103. //Enable the most high bus, which is used for copying FLASH .text to PSRAM
  104. cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, SOC_EXTRAM_DATA_HIGH, 0);
  105. cache_ll_l1_enable_bus(0, bus_mask);
  106. #if !CONFIG_FREERTOS_UNICORE
  107. bus_mask = cache_ll_l1_get_bus(1, SOC_EXTRAM_DATA_HIGH, 0);
  108. cache_ll_l1_enable_bus(1, bus_mask);
  109. #endif
  110. rodata_flash_page_info_init(page_id);
  111. #if CONFIG_IDF_TARGET_ESP32S2
  112. page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, page_id, &page0_page);
  113. page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, page_id, &page0_page);
  114. page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, page_id, &page0_page);
  115. page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, page_id, &page0_page);
  116. #elif CONFIG_IDF_TARGET_ESP32S3
  117. page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_DBUS, DRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page);
  118. #endif
  119. ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id);
  120. ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
  121. *out_page = page_id - start_page;
  122. return ESP_OK;
  123. }
  124. #endif //#if CONFIG_SPIRAM_RODATA