Jelajahi Sumber

Merge branch 'feature/new_esp_psram_component' into 'master'

esp_psram: new esp psram component

Closes IDF-4318, IDF-4382, IDF-4841, and IDFGH-7192

See merge request espressif/esp-idf!18050
Armando (Dou Yiwen) 3 tahun lalu
induk
melakukan
0b80546f8e
79 mengubah file dengan 1422 tambahan dan 2003 penghapusan
  1. 1 0
      .gitlab/CODEOWNERS
  2. 1 1
      components/esp_common/test/CMakeLists.txt
  3. 2 2
      components/esp_common/test/test_attr.c
  4. 3 21
      components/esp_hw_support/CMakeLists.txt
  5. 7 5
      components/esp_hw_support/esp_memory_utils.c
  6. 0 57
      components/esp_hw_support/include/esp_private/spiram_private.h
  7. 0 102
      components/esp_hw_support/include/soc/esp32/spiram.h
  8. 0 78
      components/esp_hw_support/include/soc/esp32s2/esp_private/mmu_psram.h
  9. 0 75
      components/esp_hw_support/include/soc/esp32s2/spiram.h
  10. 0 129
      components/esp_hw_support/include/soc/esp32s3/spiram.h
  11. 0 7
      components/esp_hw_support/linker.lf
  12. 1 4
      components/esp_hw_support/port/esp32/CMakeLists.txt
  13. 0 360
      components/esp_hw_support/port/esp32/spiram.c
  14. 0 77
      components/esp_hw_support/port/esp32/spiram_psram.h
  15. 0 3
      components/esp_hw_support/port/esp32s2/CMakeLists.txt
  16. 0 245
      components/esp_hw_support/port/esp32s2/mmu_psram.c
  17. 0 10
      components/esp_hw_support/port/esp32s3/CMakeLists.txt
  18. 0 370
      components/esp_hw_support/port/esp32s3/spiram.c
  19. 0 90
      components/esp_hw_support/port/esp32s3/spiram_psram.h
  20. 2 7
      components/esp_hw_support/port/include/esp_spiram.h
  21. 3 7
      components/esp_hw_support/sleep_gpio.c
  22. 1 1
      components/esp_hw_support/test/CMakeLists.txt
  23. 4 0
      components/esp_lcd/CMakeLists.txt
  24. 2 2
      components/esp_lcd/src/esp_lcd_rgb_panel.c
  25. 58 0
      components/esp_psram/CMakeLists.txt
  26. 7 0
      components/esp_psram/Kconfig
  27. 0 0
      components/esp_psram/Kconfig.spiram.common
  28. 7 11
      components/esp_psram/esp32/Kconfig.spiram
  29. 10 6
      components/esp_psram/esp32/esp_himem.c
  30. 78 0
      components/esp_psram/esp32/esp_psram_extram_cache.c
  31. 58 23
      components/esp_psram/esp32/esp_psram_impl_quad.c
  32. 1 9
      components/esp_psram/esp32s2/Kconfig.spiram
  33. 28 24
      components/esp_psram/esp32s2/esp_psram_impl_quad.c
  34. 1 11
      components/esp_psram/esp32s3/Kconfig.spiram
  35. 6 14
      components/esp_psram/esp32s3/esp_psram_impl_octal.c
  36. 6 29
      components/esp_psram/esp32s3/esp_psram_impl_quad.c
  37. 157 79
      components/esp_psram/esp_psram.c
  38. 10 30
      components/esp_psram/esp_psram_impl.h
  39. 0 0
      components/esp_psram/include/esp32/himem.h
  40. 84 0
      components/esp_psram/include/esp_private/esp_psram_extram.h
  41. 31 0
      components/esp_psram/include/esp_private/esp_psram_io.h
  42. 140 0
      components/esp_psram/include/esp_private/mmu.h
  43. 47 0
      components/esp_psram/include/esp_psram.h
  44. 17 0
      components/esp_psram/linker.lf
  45. 171 0
      components/esp_psram/mmu.c
  46. 146 0
      components/esp_psram/mmu_psram.c
  47. 0 0
      components/esp_psram/project_include.cmake
  48. 5 0
      components/esp_psram/test_apps/psram/CMakeLists.txt
  49. 4 0
      components/esp_psram/test_apps/psram/README.md
  50. 13 0
      components/esp_psram/test_apps/psram/main/CMakeLists.txt
  51. 40 0
      components/esp_psram/test_apps/psram/main/test_app_main.c
  52. 1 1
      components/esp_psram/test_apps/psram/main/test_himem.c
  53. 55 21
      components/esp_psram/test_apps/psram/main/test_psram.c
  54. 6 0
      components/esp_psram/test_apps/psram/partitions.csv
  55. 68 0
      components/esp_psram/test_apps/psram/pytest_psram.py
  56. 9 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32_release
  57. 9 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s2_advanced
  58. 7 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s2_release
  59. 10 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_octal_advanced
  60. 8 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_octal_release
  61. 10 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_quad_advanced
  62. 8 0
      components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_quad_release
  63. 2 0
      components/esp_psram/test_apps/psram/sdkconfig.defaults
  64. 6 0
      components/esp_system/CMakeLists.txt
  65. 5 14
      components/esp_system/include/esp_private/startup_internal.h
  66. 11 38
      components/esp_system/port/cpu_start.c
  67. 6 10
      components/esp_system/startup.c
  68. 4 0
      components/freertos/CMakeLists.txt
  69. 7 4
      components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c
  70. 5 9
      components/freertos/FreeRTOS-Kernel/portable/port_common.c
  71. 1 0
      components/hal/esp32/include/hal/cache_ll.h
  72. 8 0
      components/spi_flash/CMakeLists.txt
  73. 17 5
      components/spi_flash/flash_mmap.c
  74. 1 1
      docs/doxygen/Doxyfile_esp32
  75. 1 1
      docs/en/api-reference/system/himem.rst
  76. 2 5
      docs/en/migration-guides/system.rst
  77. 2 2
      examples/build_system/cmake/idf_as_lib/CMakeLists.txt
  78. 1 2
      examples/system/himem/main/himem_example_main.c
  79. 0 1
      tools/ci/check_copyright_ignore.txt

+ 1 - 0
.gitlab/CODEOWNERS

@@ -94,6 +94,7 @@
 /components/esp_netif/                @esp-idf-codeowners/network
 /components/esp_phy/                  @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
 /components/esp_pm/                   @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
+/components/esp_psram/                @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
 /components/esp_ringbuf/              @esp-idf-codeowners/system
 /components/esp_rom/                  @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
 /components/esp_serial_slave_link/    @esp-idf-codeowners/peripherals

+ 1 - 1
components/esp_common/test/CMakeLists.txt

@@ -1,3 +1,3 @@
 idf_component_register(SRC_DIRS .
-                       PRIV_REQUIRES cmock test_utils spi_flash
+                       PRIV_REQUIRES cmock test_utils spi_flash esp_psram
                     )

+ 2 - 2
components/esp_common/test/test_attr.c

@@ -11,7 +11,7 @@
 #include "soc/soc.h"
 #include "esp_system.h"
 #if CONFIG_IDF_TARGET_ESP32
-#include "spiram.h"
+#include "esp_private/esp_psram_extram.h"
 #endif
 #include "test_utils.h"
 
@@ -95,7 +95,7 @@ static void write_spiram_and_reset(void)
     }
     printf("Flushing cache\n");
     // Flush the cache out to SPIRAM before resetting.
-    esp_spiram_writeback_cache();
+    esp_psram_extram_writeback_cache();
 
     printf("Restarting\n");
     // Reset to test that noinit memory is left intact.

+ 3 - 21
components/esp_hw_support/CMakeLists.txt

@@ -43,26 +43,8 @@ idf_component_register(SRCS ${srcs}
 idf_build_get_property(target IDF_TARGET)
 add_subdirectory(port/${target})
 
-if(CONFIG_IDF_TARGET_ESP32 AND CONFIG_SPIRAM_CACHE_WORKAROUND AND NOT BOOTLOADER_BUILD)
-    # Note: Adding as a PUBLIC compile option here causes this option to propagate to all
-    # components that depend on esp32.
-    #
-    # To handle some corner cases, the same flag is set in project_include.cmake
-    target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue)
-    # also, make sure we link with this option so correct toolchain libs are pulled in
-    target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue)
-    # set strategy selected
-    # note that we don't need to set link options as the library linked is independent of this
-    if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST)
-        target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=dupldst)
-        target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=dupldst)
-    endif()
-    if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW)
-        target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=memw)
-        target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=memw)
-    endif()
-    if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS)
-        target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=nops)
-        target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=nops)
+if(NOT BOOTLOADER_BUILD)
+    if(CONFIG_SPIRAM)
+        idf_component_optional_requires(PRIVATE esp_psram)
     endif()
 endif()

+ 7 - 5
components/esp_hw_support/esp_memory_utils.c

@@ -12,7 +12,9 @@
 #include "soc/soc_caps.h"
 #include "esp_attr.h"
 #include "esp_memory_utils.h"
-#include "esp_private/spiram_private.h"
+#if CONFIG_SPIRAM
+#include "esp_private/esp_psram_extram.h"
+#endif
 
 
 bool esp_ptr_dma_ext_capable(const void *p)
@@ -23,7 +25,7 @@ bool esp_ptr_dma_ext_capable(const void *p)
 #if CONFIG_SPIRAM
     intptr_t vaddr_start = 0;
     intptr_t vaddr_end = 0;
-    esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
+    esp_psram_extram_get_mapped_range(&vaddr_start, &vaddr_end);
     return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end;
 #else
     return false;
@@ -44,7 +46,7 @@ bool esp_ptr_byte_accessible(const void *p)
 #if CONFIG_SPIRAM
     intptr_t vaddr_start = 0;
     intptr_t vaddr_end = 0;
-    esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
+    esp_psram_extram_get_mapped_range(&vaddr_start, &vaddr_end);
     r |= (ip >= vaddr_start && ip < vaddr_end);
 #endif
     return r;
@@ -58,7 +60,7 @@ bool esp_ptr_external_ram(const void *p)
 #if CONFIG_SPIRAM
     intptr_t vaddr_start = 0;
     intptr_t vaddr_end = 0;
-    esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
+    esp_psram_extram_get_mapped_range(&vaddr_start, &vaddr_end);
     return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end;
 #else
     return false;
@@ -70,7 +72,7 @@ bool esp_stack_ptr_in_extram(uint32_t sp)
 {
     intptr_t vaddr_start = 0;
     intptr_t vaddr_end = 0;
-    esp_spiram_get_mapped_range(&vaddr_start, &vaddr_end);
+    esp_psram_extram_get_mapped_range(&vaddr_start, &vaddr_end);
     //Check if stack ptr is in between SOC_EXTRAM_DATA_LOW and SOC_EXTRAM_DATA_HIGH, and 16 byte aligned.
     return !(sp < vaddr_start + 0x10 || sp > vaddr_end - 0x10 || ((sp & 0xF) != 0));
 }

+ 0 - 57
components/esp_hw_support/include/esp_private/spiram_private.h

@@ -1,57 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#include <stddef.h>
-#include "esp_err.h"
-#include "soc/soc_caps.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
-    ESP_SPIRAM_SIZE_16MBITS = 0,   /*!< SPI RAM size is 16 MBits */
-    ESP_SPIRAM_SIZE_32MBITS = 1,   /*!< SPI RAM size is 32 MBits */
-    ESP_SPIRAM_SIZE_64MBITS = 2,   /*!< SPI RAM size is 64 MBits */
-    ESP_SPIRAM_SIZE_INVALID,       /*!< SPI RAM size is invalid */
-} esp_spiram_size_t;
-
-/**
- * @brief Get the size of the attached SPI RAM chip selected in menuconfig
- *
- * @return Size in bytes, or 0 if no external RAM chip support compiled in.
- */
-size_t esp_spiram_get_size(void);
-
-/**
- * @brief Get the psram mapped vaddr range
- *
- * @param[out] out_vstart PSRAM virtual address start
- * @param[out] out_vend   PSRAM virtual address end
- *
- * @return
- *        - ESP_OK                  On success
- *        - ESP_ERR_INVALID_STATE   PSRAM is not initialized successfully
- */
-esp_err_t esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend);
-
-/**
- * @brief Get the psram alloced vaddr range
- *
- * @param[out] out_vstart PSRAM virtual address start
- * @param[out] out_vend   PSRAM virtual address end
- *
- * @return
- *        - ESP_OK                  On success
- *        - ESP_ERR_INVALID_STATE   PSRAM is not initialized successfully
- */
-esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 102
components/esp_hw_support/include/soc/esp32/spiram.h

@@ -1,102 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-#ifndef __ESP_SPIRAM_H
-#define __ESP_SPIRAM_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include "esp_err.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//TODO: IDF-4382, unify `target/spiram.h`, update migration guide as well
-
-/**
- * @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
- *
- * @return ESP_OK on success
- */
-esp_err_t esp_spiram_init(void);
-
-/**
- * @brief Configure Cache/MMU for access to external SPI RAM.
- *
- * Normally this function is called from cpu_start, if CONFIG_SPIRAM_BOOT_INIT
- * option is enabled. Applications which need to enable SPI RAM at run time
- * can disable CONFIG_SPIRAM_BOOT_INIT, and call this function later.
- *
- * @attention this function must be called with flash cache disabled.
- */
-void esp_spiram_init_cache(void);
-
-
-/**
- * @brief Memory test for SPI RAM. Should be called after SPI RAM is initialized and
- * (in case of a dual-core system) the app CPU is online. This test overwrites the
- * memory with crap, so do not call after e.g. the heap allocator has stored important
- * stuff in SPI RAM.
- *
- * @return true on success, false on failed memory test
- */
-bool esp_spiram_test(void);
-
-
-/**
- * @brief Add the initialized SPI RAM to the heap allocator.
- */
-esp_err_t esp_spiram_add_to_heapalloc(void);
-
-/**
- * @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
- * cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
- * RAM cache.
- *
- * This is meant for use from within the SPI flash code.
- */
-void esp_spiram_writeback_cache(void);
-
-/**
- * @brief get psram CS IO
- *
- * This interface should be called after PSRAM is enabled, otherwise it will
- * return an invalid value -1/0xff.
- *
- * @return psram CS IO or -1/0xff if psram not enabled
- */
-uint8_t esp_spiram_get_cs_io(void);
-
-
-/**
- * @brief Reserve a pool of internal memory for specific DMA/internal allocations
- *
- * @param size Size of reserved pool in bytes
- *
- * @return
- *          - ESP_OK on success
- *          - ESP_ERR_NO_MEM when no memory available for pool
- */
-esp_err_t esp_spiram_reserve_dma_pool(size_t size);
-
-
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return
- *          - true SPI RAM has been initialized successfully
- *          - false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif //  __ESP_SPIRAM_H

+ 0 - 78
components/esp_hw_support/include/soc/esp32s2/esp_private/mmu_psram.h

@@ -1,78 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#pragma once
-
-#include <sys/param.h>
-#include "esp_err.h"
-#include "sdkconfig.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-esp_err_t mmu_map_psram(uint32_t start_paddr, uint32_t map_length, uint32_t *out_start_vaddr);
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-extern int _instruction_reserved_start;
-extern int _instruction_reserved_end;
-
-esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
-
-/**
- * @brief Get the start page number of the instruction in SPI flash
- *
- * @return start page number
- */
-uint32_t instruction_flash_start_page_get(void);
-
-/**
- * @brief Get the end page number of the instruction in SPI flash
- *
- * @return end page number
- */
-uint32_t instruction_flash_end_page_get(void);
-
-/**
- * @brief Get the offset of instruction from SPI flash to SPI RAM
- *
- * @return instruction offset
- */
-int instruction_flash2spiram_offset(void);
-#endif
-
-#if CONFIG_SPIRAM_RODATA
-extern int _rodata_reserved_start;
-extern int _rodata_reserved_end;
-
-esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
-
-/**
- * @brief Get the start page number of the rodata in SPI flash
- *
- * @return start page number
- */
-uint32_t rodata_flash_start_page_get(void);
-
-/**
- * @brief Get the end page number of the rodata in SPI flash
- *
- * @return end page number
- */
-uint32_t rodata_flash_end_page_get(void);
-
-/**
- * @brief Get the offset number of rodata from SPI flash to SPI RAM
- *
- * @return rodata offset
- */
-int rodata_flash2spiram_offset(void);
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 75
components/esp_hw_support/include/soc/esp32s2/spiram.h

@@ -1,75 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-#ifndef __ESP_SPIRAM_H
-#define __ESP_SPIRAM_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include "esp_err.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
- *
- * @return ESP_OK on success
- */
-esp_err_t esp_spiram_init(void);
-
-/**
- * @brief Add the initialized SPI RAM to the heap allocator.
- */
-esp_err_t esp_spiram_add_to_heapalloc(void);
-
-/**
- * @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
- * cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
- * RAM cache.
- *
- * This is meant for use from within the SPI flash code.
- */
-void esp_spiram_writeback_cache(void);
-
-/**
- * @brief get psram CS IO
- *
- * This interface should be called after PSRAM is enabled, otherwise it will
- * return an invalid value -1/0xff.
- *
- * @return psram CS IO or -1/0xff if psram not enabled
- */
-uint8_t esp_spiram_get_cs_io(void);
-
-/**
- * @brief Reserve a pool of internal memory for specific DMA/internal allocations
- *
- * @param size Size of reserved pool in bytes
- *
- * @return
- *          - ESP_OK on success
- *          - ESP_ERR_NO_MEM when no memory available for pool
- */
-esp_err_t esp_spiram_reserve_dma_pool(size_t size);
-
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return
- *          - true SPI RAM has been initialized successfully
- *          - false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 129
components/esp_hw_support/include/soc/esp32s3/spiram.h

@@ -1,129 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include "esp_err.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
- *
- * @return ESP_OK on success
- */
-esp_err_t esp_spiram_init(void);
-
-/**
- * @brief Add the initialized SPI RAM to the heap allocator.
- */
-esp_err_t esp_spiram_add_to_heapalloc(void);
-
-/**
- * @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
- * cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
- * RAM cache.
- *
- * This is meant for use from within the SPI flash code.
- */
-void esp_spiram_writeback_cache(void);
-
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return
- *          - true SPI RAM has been initialized successfully
- *          - false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void);
-
-/**
- * @brief get psram CS IO
- *
- * This interface should be called after PSRAM is enabled, otherwise it will
- * return an invalid value -1/0xff.
- *
- * @return psram CS IO or -1/0xff if psram not enabled
- */
-uint8_t esp_spiram_get_cs_io(void);
-
-/**
- * @brief Reserve a pool of internal memory for specific DMA/internal allocations
- *
- * @param size Size of reserved pool in bytes
- *
- * @return
- *          - ESP_OK on success
- *          - ESP_ERR_NO_MEM when no memory available for pool
- */
-esp_err_t esp_spiram_reserve_dma_pool(size_t size);
-
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return
- *          - true SPI RAM has been initialized successfully
- *          - false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void);
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-
-extern int _instruction_reserved_start, _instruction_reserved_end;
-
-/**
- * @brief Get the start page number of the instruction in SPI flash
- *
- * @return start page number
- */
-uint32_t instruction_flash_start_page_get(void);
-/**
- * @brief Get the end page number of the instruction in SPI flash
- *
- * @return end page number
- */
-uint32_t instruction_flash_end_page_get(void);
-/**
- * @brief Get the offset of instruction from SPI flash to SPI RAM
- *
- * @return instruction offset
- */
-int instruction_flash2spiram_offset(void);
-#endif
-
-#if CONFIG_SPIRAM_RODATA
-
-extern int _rodata_reserved_start, _rodata_reserved_end;
-
-/**
- * @brief Get the start page number of the rodata in SPI flash
- *
- * @return start page number
- */
-uint32_t rodata_flash_start_page_get(void);
-/**
- * @brief Get the end page number of the rodata in SPI flash
- *
- * @return end page number
- */
-uint32_t rodata_flash_end_page_get(void);
-/**
- * @brief Get the offset number of rodata from SPI flash to SPI RAM
- *
- * @return rodata offset
- */
-int rodata_flash2spiram_offset(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 7
components/esp_hw_support/linker.lf

@@ -19,13 +19,6 @@ entries:
     rtc_time (noflash_text)
     if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y:
         rtc_wdt (noflash_text)
-    if IDF_TARGET_ESP32S3 = y:
-        if SPIRAM_MODE_QUAD = y:
-            spiram_psram (noflash)
-        if SPIRAM_MODE_OCT = y:
-            opiram_psram (noflash)
-    if IDF_TARGET_ESP32S2 = y && SPIRAM:
-        mmu_psram (noflash)
     if PERIPH_CTRL_FUNC_IN_IRAM = y:
         periph_ctrl: periph_module_reset (noflash)
         periph_ctrl: wifi_module_enable (noflash)

+ 1 - 4
components/esp_hw_support/port/esp32/CMakeLists.txt

@@ -11,10 +11,7 @@ set(srcs
     "chip_info.c")
 
 if(NOT BOOTLOADER_BUILD)
-    list(APPEND srcs "cache_sram_mmu.c"
-                     "esp_himem.c"
-                     "spiram.c"
-                     "spiram_psram.c")
+    list(APPEND srcs "cache_sram_mmu.c")
 endif()
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 0 - 360
components/esp_hw_support/port/esp32/spiram.c

@@ -1,360 +0,0 @@
-/*
-Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if
-we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
-*/
-
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <sys/param.h>
-
-#include "sdkconfig.h"
-#include "esp_attr.h"
-#include "esp_err.h"
-#include "esp32/spiram.h"
-#include "esp_private/spiram_private.h"
-#include "spiram_psram.h"
-#include "esp_log.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/xtensa_api.h"
-#include "soc/soc.h"
-#include "esp_heap_caps_init.h"
-#include "soc/soc_memory_layout.h"
-#include "soc/dport_reg.h"
-#include "esp_himem.h"
-#include "esp32/rom/cache.h"
-
-#if CONFIG_FREERTOS_UNICORE
-#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
-#else
-#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
-#endif
-
-#if CONFIG_SPIRAM
-
-static const char* TAG = "spiram";
-
-#if CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_40M
-#define PSRAM_SPEED PSRAM_CACHE_F40M_S40M
-#elif CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
-#define PSRAM_SPEED PSRAM_CACHE_F80M_S40M
-#elif CONFIG_SPIRAM_SPEED_80M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
-#define PSRAM_SPEED PSRAM_CACHE_F80M_S80M
-#else
-#error "FLASH speed can only be equal to or higher than SRAM speed while SRAM is enabled!"
-#endif
-
-#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-extern uint8_t _ext_ram_bss_start, _ext_ram_bss_end;
-#endif
-#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
-extern uint8_t _ext_ram_noinit_start, _ext_ram_noinit_end;
-#endif
-
-//These variables are in bytes
-static intptr_t s_allocable_vaddr_start;
-static intptr_t s_allocable_vaddr_end;
-static intptr_t s_mapped_vaddr_start;
-static intptr_t s_mapped_vaddr_end;
-
-static bool spiram_inited=false;
-
-
-//If no function in esp_himem.c is used, this function will be linked into the
-//binary instead of the one in esp_himem.c, automatically making sure no memory
-//is reserved if no himem function is used.
-size_t __attribute__((weak)) esp_himem_reserved_area_size(void) {
-    return 0;
-}
-
-
-static size_t spiram_size_usable_for_malloc(void)
-{
-    /* SPIRAM chip may be larger than the size we can map into address space */
-    size_t s = MIN(esp_spiram_get_size(), SOC_EXTRAM_DATA_SIZE);
-    return s - esp_himem_reserved_area_size();
-}
-
-
-/*
- Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
- true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
- initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
-*/
-bool esp_spiram_test(void)
-{
-
-#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
-    const void *keepout_addr_low = (const void*)&_ext_ram_noinit_start;
-    const void *keepout_addr_high = (const void*)&_ext_ram_noinit_end;
-#else
-    const void *keepout_addr_low = 0;
-    const void *keepout_addr_high = 0;
-#endif
-
-    volatile int *spiram=(volatile int*)SOC_EXTRAM_DATA_LOW;
-    size_t p;
-    size_t s=spiram_size_usable_for_malloc();
-    int errct=0;
-    int initial_err=-1;
-    for (p=0; p<(s/sizeof(int)); p+=8) {
-        const void *addr = (const void *)&spiram[p];
-        if ((keepout_addr_low <= addr) && (addr < keepout_addr_high)) {
-            continue;
-        }
-        spiram[p]=p^0xAAAAAAAA;
-    }
-    for (p=0; p<(s/sizeof(int)); p+=8) {
-        const void *addr = (const void *)&spiram[p];
-        if ((keepout_addr_low <= addr) && (addr < keepout_addr_high)) {
-            continue;
-        }
-        if (spiram[p]!=(p^0xAAAAAAAA)) {
-            errct++;
-            if (errct==1) initial_err=p*4;
-        }
-    }
-    if (errct) {
-        ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW);
-        return false;
-    } else {
-        ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
-        return true;
-    }
-}
-
-void IRAM_ATTR esp_spiram_init_cache(void)
-{
-    int size = esp_spiram_get_size();
-    if (size > 4 * 1024 * 1024) size = 4 * 1024 * 1024; // we can map at most 4MByte
-    //Enable external RAM in MMU
-    cache_sram_mmu_set(0, 0, SOC_EXTRAM_DATA_LOW, 0, 32, (size / 1024 / 32));
-    //Flush and enable icache for APP CPU
-#if !CONFIG_FREERTOS_UNICORE
-    DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1);
-    cache_sram_mmu_set(1, 0, SOC_EXTRAM_DATA_LOW, 0, 32, (size / 1024 / 32));
-#endif
-
-    s_mapped_vaddr_start = (intptr_t)SOC_EXTRAM_DATA_LOW;
-    s_mapped_vaddr_end = s_mapped_vaddr_start + size;
-}
-
-esp_spiram_size_t esp_spiram_get_chip_size(void)
-{
-    if (!spiram_inited) {
-        ESP_EARLY_LOGE(TAG, "SPI RAM not initialized");
-        abort();
-    }
-    psram_size_t psram_size = psram_get_size();
-    switch (psram_size) {
-        case PSRAM_SIZE_16MBITS:
-            return ESP_SPIRAM_SIZE_16MBITS;
-        case PSRAM_SIZE_32MBITS:
-            return ESP_SPIRAM_SIZE_32MBITS;
-        case PSRAM_SIZE_64MBITS:
-            return ESP_SPIRAM_SIZE_64MBITS;
-        default:
-            return ESP_SPIRAM_SIZE_INVALID;
-    }
-}
-
-esp_err_t esp_spiram_init(void)
-{
-    assert(!spiram_inited);
-    esp_err_t r;
-    r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
-    if (r != ESP_OK) {
-#if CONFIG_SPIRAM_IGNORE_NOTFOUND
-        ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
-#endif
-        return r;
-    }
-
-    spiram_inited=true; //note: this needs to be set before esp_spiram_get_chip_*/esp_spiram_get_size calls
-#if (CONFIG_SPIRAM_SIZE != -1)
-    if (esp_spiram_get_size()!=CONFIG_SPIRAM_SIZE) {
-        ESP_EARLY_LOGE(TAG, "Expected %dKiB chip but found %dKiB chip. Bailing out..", CONFIG_SPIRAM_SIZE/1024, esp_spiram_get_size()/1024);
-        return ESP_ERR_INVALID_SIZE;
-    }
-#endif
-
-    ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device",
-                                          (esp_spiram_get_size()*8)/(1024*1024));
-    ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_F40M_S40M ? "flash 40m sram 40m" : \
-                                          PSRAM_SPEED == PSRAM_CACHE_F80M_S40M ? "flash 80m sram 40m" : \
-                                          PSRAM_SPEED == PSRAM_CACHE_F80M_S80M ? "flash 80m sram 80m" : "ERROR");
-    ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
-                                          (PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)": \
-                                          (PSRAM_MODE==PSRAM_VADDR_MODE_LOWHIGH)?"low/high (2-core)": \
-                                          (PSRAM_MODE==PSRAM_VADDR_MODE_NORMAL)?"normal (1-core)":"ERROR");
-    return ESP_OK;
-}
-
-
-esp_err_t esp_spiram_add_to_heapalloc(void)
-{
-    //Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's
-    //no need to explicitly specify them.
-    s_allocable_vaddr_start = (intptr_t)SOC_EXTRAM_DATA_LOW;
-#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-    if (s_allocable_vaddr_start < (intptr_t)&_ext_ram_bss_end) {
-        s_allocable_vaddr_start = (intptr_t)&_ext_ram_bss_end;
-    }
-#endif
-#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
-    if (s_allocable_vaddr_start < (intptr_t)&_ext_ram_noinit_end) {
-        s_allocable_vaddr_start = (intptr_t)&_ext_ram_noinit_end;
-    }
-#endif
-    s_allocable_vaddr_end = (intptr_t)SOC_EXTRAM_DATA_LOW + spiram_size_usable_for_malloc() - 1;
-    ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start)/1024);
-    return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end);
-}
-
-esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
-{
-    if (!out_vstart || !out_vend) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    if (!spiram_inited) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    *out_vstart = s_mapped_vaddr_start;
-    *out_vend = s_mapped_vaddr_end;
-    return ESP_OK;
-}
-
-esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
-{
-    if (!out_vstart || !out_vend) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    if (!spiram_inited) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    *out_vstart = s_allocable_vaddr_start;
-    *out_vend = s_allocable_vaddr_end;
-    return ESP_OK;
-}
-
-
-static uint8_t *dma_heap;
-
-esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
-    ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
-    /* Pool may be allocated in multiple non-contiguous chunks, depending on available RAM */
-    while (size > 0) {
-        size_t next_size = heap_caps_get_largest_free_block(MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
-        next_size = MIN(next_size, size);
-
-        ESP_EARLY_LOGD(TAG, "Allocating block of size %d bytes", next_size);
-        dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
-        if (!dma_heap || next_size == 0) {
-            return ESP_ERR_NO_MEM;
-        }
-
-        uint32_t caps[] = { 0, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT };
-        esp_err_t e = heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap+next_size-1);
-        if (e != ESP_OK) {
-            return e;
-        }
-        size -= next_size;
-    }
-    return ESP_OK;
-}
-
-size_t esp_spiram_get_size(void)
-{
-    psram_size_t size=esp_spiram_get_chip_size();
-    if (size==PSRAM_SIZE_16MBITS) return 2*1024*1024;
-    if (size==PSRAM_SIZE_32MBITS) return 4*1024*1024;
-    if (size==PSRAM_SIZE_64MBITS) return 8*1024*1024;
-    return CONFIG_SPIRAM_SIZE;
-}
-
-/*
- Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
- otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
- Note that this routine assumes some unique mapping for the first 2 banks of the PSRAM memory range, as well as the
- 2 banks after the 2 MiB mark.
-*/
-void IRAM_ATTR esp_spiram_writeback_cache(void)
-{
-    int x;
-    volatile int i=0;
-    volatile uint8_t *psram=(volatile uint8_t*)SOC_EXTRAM_DATA_LOW;
-    int cache_was_disabled=0;
-
-    if (!spiram_inited) return;
-
-    //We need cache enabled for this to work. Re-enable it if needed; make sure we
-    //disable it again on exit as well.
-    if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
-        cache_was_disabled|=(1<<0);
-        DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
-    }
-#ifndef CONFIG_FREERTOS_UNICORE
-    if (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
-        cache_was_disabled|=(1<<1);
-        DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
-    }
-#endif
-
-#if (PSRAM_MODE != PSRAM_VADDR_MODE_LOWHIGH)
-    /*
-    Single-core and even/odd mode only have 32K of cache evenly distributed over the address lines. We can clear
-    the cache by just reading 64K worth of cache lines.
-    */.
-    for (x=0; x<1024*64; x+=32) {
-        i+=psram[x];
-    }
-#else
-    /*
-    Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI flash and another 32K for the highest
-    2MiB. Clear this by reading from both regions.
-    Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If
-    we ever support external RAM chips of 2M or smaller, this may need adjusting.
-    */
-    for (x=0; x<1024*64; x+=32) {
-        i+=psram[x];
-        i+=psram[x+(1024*1024*2)];
-    }
-#endif
-
-    if (cache_was_disabled&(1<<0)) {
-        while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) ;
-        DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
-    }
-#ifndef CONFIG_FREERTOS_UNICORE
-    if (cache_was_disabled&(1<<1)) {
-        while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1);
-        DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
-    }
-#endif
-}
-
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return true SPI RAM has been initialized successfully
- * @return false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void)
-{
-    return spiram_inited;
-}
-
-uint8_t esp_spiram_get_cs_io(void)
-{
-    return psram_get_cs_io();
-}
-#endif

+ 0 - 77
components/esp_hw_support/port/esp32/spiram_psram.h

@@ -1,77 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-#ifndef _PSRAM_H
-#define _PSRAM_H
-#include "soc/spi_periph.h"
-#include "esp_err.h"
-#include "sdkconfig.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
-    PSRAM_CACHE_F80M_S40M = 0,
-    PSRAM_CACHE_F40M_S40M,
-    PSRAM_CACHE_F80M_S80M,
-    PSRAM_CACHE_MAX,
-} psram_cache_mode_t;
-
-typedef enum {
-    PSRAM_SIZE_16MBITS = 0,
-    PSRAM_SIZE_32MBITS = 1,
-    PSRAM_SIZE_64MBITS = 2,
-    PSRAM_SIZE_MAX,
-} psram_size_t;
-
-/*
-See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
-
-Important is that NORMAL works with the app CPU cache disabled, but gives huge cache coherency
-issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
-issues but cannot be used when the app CPU cache is disabled.
-*/
-
-typedef enum {
-    PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
-    PSRAM_VADDR_MODE_LOWHIGH,  ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
-    PSRAM_VADDR_MODE_EVENODD,  ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
-} psram_vaddr_mode_t;
-
-/**
- * @brief get psram size
- * @return
- *     - PSRAM_SIZE_MAX if psram not enabled or not valid
- *     - PSRAM size
- */
-psram_size_t psram_get_size(void);
-
-/**
- * @brief psram cache enable function
- *
- * Esp-idf uses this to initialize cache for psram, mapping it into the main memory
- * address space.
- *
- * @param mode       SPI mode to access psram in
- * @param vaddrmode  Mode the psram cache works in.
- * @return ESP_OK on success, ESP_ERR_INVALID_STATE when VSPI peripheral is needed but cannot be claimed.
- */
-esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
-
-/**
- * @brief get psram CS IO
- *
- * @return psram CS IO
- */
-uint8_t psram_get_cs_io(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 3
components/esp_hw_support/port/esp32s2/CMakeLists.txt

@@ -18,9 +18,6 @@ if(NOT BOOTLOADER_BUILD)
                      "esp_crypto_lock.c"
                      "esp_ds.c")
 
-    if(CONFIG_SPIRAM)
-        list(APPEND srcs "spiram.c" "mmu_psram.c" "spiram_psram.c")
-    endif()
 endif()
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 0 - 245
components/esp_hw_support/port/esp32s2/mmu_psram.c

@@ -1,245 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include <sys/param.h>
-#include "esp_attr.h"
-#include "esp_log.h"
-#include "esp_private/mmu_psram.h"
-#include "esp32s2/rom/cache.h"
-#include "esp32s2/rom/ets_sys.h"
-#include "soc/ext_mem_defs.h"
-#include "soc/extmem_reg.h"
-
-#define MMU_PAGE_SIZE (0x10000)
-#define MMU_PAGE_TO_BYTES(page_id)      ((page_id) * MMU_PAGE_SIZE)
-#define BYTES_TO_MMU_PAGE(bytes)        ((bytes) / MMU_PAGE_SIZE)
-
-const static char *TAG = "mmu_psram";
-
-//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-static uint32_t instruction_in_spiram;
-static uint32_t instr_start_page;
-static uint32_t instr_end_page;
-static int instr_flash2spiram_offs;
-
-uint32_t esp_spiram_instruction_access_enabled(void);
-int instruction_flash2spiram_offset(void);
-uint32_t instruction_flash_start_page_get(void);
-uint32_t instruction_flash_end_page_get(void);
-#endif  //CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-
-
-//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
-#if CONFIG_SPIRAM_RODATA
-static uint32_t rodata_in_spiram;
-static int rodata_flash2spiram_offs;
-static uint32_t rodata_start_page;
-static uint32_t rodata_end_page;
-
-uint32_t esp_spiram_rodata_access_enabled(void);
-int rodata_flash2spiram_offset(void);
-uint32_t rodata_flash_start_page_get(void);
-uint32_t rodata_flash_end_page_get(void);
-#endif  //#if CONFIG_SPIRAM_RODATA
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
-// Helper macro to make a MMU entry invalid
-#define INVALID_PHY_PAGE          0xffff
-//TODO IDF-4387
-static uint32_t page0_mapped = 0;
-static uint32_t page0_page = INVALID_PHY_PAGE;
-#endif  //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
-
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page)
-{
-    uint32_t page_id = start_page;
-
-    /**
-     * TODO IDF-4387
-     * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
-     * FOR NOW, leave these logics just as it used to be.
-     */
-    uint32_t flash_pages = 0;
-    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS0, &page0_mapped);
-    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS1, &page0_mapped);
-    if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
-        ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %d B, from %d B to %d B",
-                       MMU_PAGE_TO_BYTES(flash_pages), MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(flash_pages + page_id));
-        return ESP_FAIL;
-    }
-
-    //Enable DRAM0_BUS, which is used for copying FLASH .text to PSRAM
-    REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0);
-
-    uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - (uint32_t)&_instruction_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
-    uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
-
-    instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset];
-    instr_start_page &= MMU_VALID_VAL_MASK;
-    instr_end_page = instr_start_page + instr_page_cnt - 1;
-    instr_flash2spiram_offs = instr_start_page - page_id;
-    ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", instr_start_page, page_id, instr_flash2spiram_offs);
-
-    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, page_id, &page0_page);
-    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, page_id, &page0_page);
-    instruction_in_spiram = 1;
-    ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id);
-    ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
-
-    /**
-     * Disable DRAM0_BUS.
-     * .text (instructions) are mapped in `Cache_Flash_To_SPIRAM_Copy` to both `PRO_CACHE_IBUS0` and `PRO_CACHE_IBUS1`.
-     *
-     * For now, this bus (DRAM0) is only used for copying, so can be disabled. If it is used later, other code
-     * should be responsible for enabling it.
-     */
-    REG_SET_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0);
-    *out_page = page_id - start_page;
-
-    return ESP_OK;
-}
-#endif  //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-
-
-
-#if CONFIG_SPIRAM_RODATA
-esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page)
-{
-    uint32_t page_id = start_page;
-
-    /**
-     * TODO IDF-4387
-     * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
-     * FOR NOW, leave these logics just as it used to be.
-     */
-    uint32_t flash_pages = 0;
-    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS2, &page0_mapped);
-    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS0, &page0_mapped);
-    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS1, &page0_mapped);
-    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS2, &page0_mapped);
-    if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
-        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));
-        return ESP_FAIL;
-    }
-
-    //Enable DRAM0_BUS, which is used for copying FLASH .rodata to PSRAM
-    REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0);
-
-    uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - (uint32_t)&_rodata_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
-    uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
-
-    rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset];
-    rodata_start_page &= MMU_VALID_VAL_MASK;
-    rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
-    rodata_flash2spiram_offs = rodata_start_page - page_id;
-    ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", rodata_start_page, page_id, rodata_flash2spiram_offs);
-
-    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, page_id, &page0_page);
-    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, page_id, &page0_page);
-    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, page_id, &page0_page);
-    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, page_id, &page0_page);
-    rodata_in_spiram = 1;
-    ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id);
-    ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
-
-
-    /**
-     * Disable DRAM0_BUS.
-     * .text (instructions) are mapped in `Cache_Flash_To_SPIRAM_Copy` to both `PRO_CACHE_IBUS0` and `PRO_CACHE_IBUS1`.
-     *
-     * For now, this bus (DRAM0) is only used for copying, so can be disabled. If it is used later, other code
-     * should be responsible for enabling it.
-     */
-    REG_SET_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0);
-    *out_page = page_id - start_page;
-
-    return ESP_OK;
-}
-#endif  //#if CONFIG_SPIRAM_RODATA
-
-/**
- * On ESP32S2, DPORT_BUS, DRAM1_BUS, DRAM0_BUS are consecutive, from low to high
- */
-esp_err_t mmu_map_psram(uint32_t start_paddr, uint32_t end_paddr, uint32_t *out_start_vaddr)
-{
-    /**
-     * @note For now, this function should only run when virtual address is enough
-     *       Decide these logics when there's a real PSRAM with larger size
-     */
-    uint32_t map_length = end_paddr - start_paddr;
-    if (map_length > SOC_EXTRAM_DATA_SIZE) {
-        //Decide these logics when there's a real PSRAM with larger size
-        ESP_EARLY_LOGE(TAG, "PSRAM physical size is too large, not support mapping it yet!");
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    //should be MMU page aligned
-    assert((start_paddr % MMU_PAGE_SIZE) == 0);
-
-    uint32_t start_vaddr = DPORT_CACHE_ADDRESS_LOW;
-    uint32_t end_vaddr = start_vaddr + map_length;
-    uint32_t cache_bus_mask = 0;
-
-    cache_bus_mask |= (end_vaddr > 0) ? EXTMEM_PRO_DCACHE_MASK_DPORT : 0;
-    cache_bus_mask |= (end_vaddr >= DPORT_ADDRESS_HIGH) ? EXTMEM_PRO_DCACHE_MASK_DRAM1 : 0;
-    cache_bus_mask |= (end_vaddr >= DRAM1_ADDRESS_HIGH) ? EXTMEM_PRO_DCACHE_MASK_DRAM0 : 0;
-    assert(end_vaddr <= DRAM0_CACHE_ADDRESS_HIGH);
-    ESP_EARLY_LOGV(TAG, "start_paddr is %x, map_length is %xB, %d pages", start_paddr, map_length, BYTES_TO_MMU_PAGE(map_length));
-
-    //No need to disable cache, this file is put in Internal RAM
-    Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, start_vaddr, start_paddr, 64, BYTES_TO_MMU_PAGE(map_length), 0);
-    REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, cache_bus_mask);
-
-    *out_start_vaddr = start_vaddr;
-
-    return ESP_OK;
-}
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-uint32_t esp_spiram_instruction_access_enabled(void)
-{
-    return instruction_in_spiram;
-}
-
-int instruction_flash2spiram_offset(void)
-{
-    return instr_flash2spiram_offs;
-}
-
-uint32_t instruction_flash_start_page_get(void)
-{
-    return instr_start_page;
-}
-
-uint32_t instruction_flash_end_page_get(void)
-{
-    return instr_end_page;
-}
-#endif  //CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-
-#if CONFIG_SPIRAM_RODATA
-uint32_t esp_spiram_rodata_access_enabled(void)
-{
-    return rodata_in_spiram;
-}
-
-int rodata_flash2spiram_offset(void)
-{
-    return rodata_flash2spiram_offs;
-}
-
-uint32_t rodata_flash_start_page_get(void)
-{
-    return rodata_start_page;
-}
-
-uint32_t rodata_flash_end_page_get(void)
-{
-    return rodata_end_page;
-}
-#endif  //#if CONFIG_SPIRAM_RODATA

+ 0 - 10
components/esp_hw_support/port/esp32s3/CMakeLists.txt

@@ -16,16 +16,6 @@ if(NOT BOOTLOADER_BUILD)
         "esp_hmac.c"
         "esp_ds.c"
         "esp_crypto_lock.c")
-
-    if(CONFIG_SPIRAM)
-        list(APPEND srcs "spiram.c")
-
-        if(CONFIG_SPIRAM_MODE_QUAD)
-            list(APPEND srcs "spiram_psram.c")
-        elseif(CONFIG_SPIRAM_MODE_OCT)
-            list(APPEND srcs "opiram_psram.c")
-        endif()
-    endif()
 endif()
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 0 - 370
components/esp_hw_support/port/esp32s3/spiram.c

@@ -1,370 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-/*----------------------------------------------------------------------------------------------------
- * Abstraction layer for PSRAM. PSRAM device related registers and MMU/Cache related code shouls be
- * abstracted to lower layers.
- *
- * When we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
- *----------------------------------------------------------------------------------------------------*/
-#include <stdint.h>
-#include <string.h>
-#include <sys/param.h>
-#include "sdkconfig.h"
-#include "esp_attr.h"
-#include "esp_err.h"
-#include "esp_log.h"
-#include "esp_heap_caps_init.h"
-#include "esp_private/spiram_private.h"
-#include "esp32s3/spiram.h"
-#include "spiram_psram.h"
-#include "hal/mmu_hal.h"
-#include "hal/cache_ll.h"
-
-
-#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
-#define MMU_PAGE_SIZE (0x10000)
-
-#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
-
-#if CONFIG_SPIRAM_SPEED_40M
-#define PSRAM_SPEED PSRAM_CACHE_S40M
-#else  //#if CONFIG_SPIRAM_SPEED_80M
-#define PSRAM_SPEED PSRAM_CACHE_S80M
-#endif
-
-
-static const char *TAG = "spiram";
-static bool s_spiram_inited;
-
-//These variables are in bytes
-static intptr_t s_allocable_vaddr_start;
-static intptr_t s_allocable_vaddr_end;
-static intptr_t s_mapped_vaddr_start;
-static intptr_t s_mapped_vaddr_end;
-
-
-#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-extern uint8_t _ext_ram_bss_start;
-extern uint8_t _ext_ram_bss_end;
-#endif //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-
-
-static bool esp_spiram_test(uint32_t v_start, uint32_t size);
-
-
-esp_err_t esp_spiram_init(void)
-{
-    assert(!s_spiram_inited);
-    esp_err_t ret;
-    uint32_t psram_physical_size = 0;
-    ret = psram_enable(PSRAM_SPEED, PSRAM_MODE);
-    if (ret != ESP_OK) {
-#if CONFIG_SPIRAM_IGNORE_NOTFOUND
-        ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
-#endif
-        return ret;
-    }
-    s_spiram_inited = true;
-
-    ret = psram_get_physical_size(&psram_physical_size);
-    assert(ret == ESP_OK);
-
-#if (CONFIG_SPIRAM_SIZE != -1)
-    if (psram_physical_size != CONFIG_SPIRAM_SIZE) {
-        ESP_EARLY_LOGE(TAG, "Expected %dMB chip but found %dMB chip. Bailing out..", (CONFIG_SPIRAM_SIZE / 1024 / 1024), (psram_physical_size / 1024 / 1024));
-        return ESP_ERR_INVALID_SIZE;
-    }
-#endif
-    ESP_EARLY_LOGI(TAG, "Found %dMB SPI RAM device", psram_physical_size / (1024 * 1024));
-    ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
-
-    /**
-     * TODO IDF-4318
-     * Add these feature here:
-     * - Copy Flash text into PSRAM
-     * - Copy Flash rodata into PSRAM
-     */
-    //----------------------------------Map the PSRAM physical range to MMU-----------------------------//
-    uint32_t vaddr_start = 0;
-    extern uint32_t _rodata_reserved_end;
-    uint32_t rodata_end_aligned = ALIGN_UP_BY((uint32_t)&_rodata_reserved_end, MMU_PAGE_SIZE);
-    vaddr_start = rodata_end_aligned;
-    ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned);
-
-    uint32_t psram_available_size = 0;
-    ret = psram_get_available_size(&psram_available_size);
-    assert(ret == ESP_OK);
-
-    if (vaddr_start + psram_available_size > DRAM0_CACHE_ADDRESS_HIGH) {
-        //Decide these logics when there's a real PSRAM with larger size
-        ESP_EARLY_LOGE(TAG, "Virtual address not enough for PSRAM!");
-        abort();
-    }
-
-    //On ESP32S3, MMU is shared for both of the cores. Note this when porting `spiram.c`
-    uint32_t actual_mapped_len = 0;
-    mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, 0, psram_available_size, &actual_mapped_len);
-    ESP_EARLY_LOGV(TAG, "actual_mapped_len is 0x%x bytes", actual_mapped_len);
-
-    cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, vaddr_start, actual_mapped_len);
-    cache_ll_l1_enable_bus(0, bus_mask);
-#if !CONFIG_FREERTOS_UNICORE
-    bus_mask = cache_ll_l1_get_bus(1, vaddr_start, actual_mapped_len);
-    cache_ll_l1_enable_bus(1, bus_mask);
-#endif
-
-#if CONFIG_SPIRAM_MEMTEST
-    //After mapping, simple test SPIRAM first
-    bool ext_ram_ok = esp_spiram_test(vaddr_start, psram_available_size);
-    if (!ext_ram_ok) {
-        ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
-        abort();
-    }
-#endif  //#if CONFIG_SPIRAM_MEMTEST
-
-
-    /*------------------------------------------------------------------------------
-    * After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESSS ANYMORE!
-    *----------------------------------------------------------------------------*/
-    s_mapped_vaddr_start = vaddr_start;
-    s_mapped_vaddr_end = vaddr_start + psram_available_size;
-    s_allocable_vaddr_start = vaddr_start;
-    s_allocable_vaddr_end = vaddr_start + psram_available_size;
-
-
-    //------------------------------------Configure .bss in PSRAM-------------------------------------//
-#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-    //should never be negative number
-    uint32_t ext_bss_size = ((intptr_t)&_ext_ram_bss_end - (intptr_t)&_ext_ram_bss_start);
-    ESP_EARLY_LOGV(TAG, "_ext_ram_bss_start is 0x%x, _ext_ram_bss_start is 0x%x, ext_bss_size is 0x%x bytes", &_ext_ram_bss_start, &_ext_ram_bss_end, ext_bss_size);
-
-    s_allocable_vaddr_start += ext_bss_size;
-#endif  //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
-
-    ESP_EARLY_LOGV(TAG, "s_allocable_vaddr_start is 0x%x, s_allocable_vaddr_end is 0x%x", s_allocable_vaddr_start, s_allocable_vaddr_end);
-    return ESP_OK;
-}
-
-/**
- * Add the PSRAM available region to heap allocator. Heap allocator knows the capabilities of this type of memory,
- * so there's no need to explicitly specify them.
- */
-esp_err_t esp_spiram_add_to_heapalloc(void)
-{
-    ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start) / 1024);
-    return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end);
-}
-
-esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
-{
-    if (!out_vstart || !out_vend) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    if (!s_spiram_inited) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    *out_vstart = s_mapped_vaddr_start;
-    *out_vend = s_mapped_vaddr_end;
-    return ESP_OK;
-}
-
-esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
-{
-    if (!out_vstart || !out_vend) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    if (!s_spiram_inited) {
-        return ESP_ERR_INVALID_STATE;
-    }
-
-    *out_vstart = s_allocable_vaddr_start;
-    *out_vend = s_allocable_vaddr_end;
-    return ESP_OK;
-}
-
-esp_err_t esp_spiram_reserve_dma_pool(size_t size)
-{
-    if (size == 0) {
-        return ESP_OK;
-    }
-    ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size / 1024);
-    uint8_t *dma_heap = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
-    if (!dma_heap) {
-        return ESP_ERR_NO_MEM;
-    }
-    uint32_t caps[] = {MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
-    return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size);
-}
-
-//TODO IDF-4318
-// static uint32_t pages_for_flash = 0;
-static uint32_t instruction_in_spiram = 0;
-static uint32_t rodata_in_spiram = 0;
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-static int instr_flash2spiram_offs = 0;
-static uint32_t instr_start_page = 0;
-static uint32_t instr_end_page = 0;
-#endif
-
-#if CONFIG_SPIRAM_RODATA
-static int rodata_flash2spiram_offs = 0;
-static uint32_t rodata_start_page = 0;
-static uint32_t rodata_end_page = 0;
-#endif
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
-// Helper macro to make a MMU entry invalid
-#define INVALID_PHY_PAGE          0xffff
-static uint32_t page0_mapped = 0;
-static uint32_t page0_page = INVALID_PHY_PAGE;
-#endif
-
-uint32_t esp_spiram_instruction_access_enabled(void)
-{
-    return instruction_in_spiram;
-}
-
-uint32_t esp_spiram_rodata_access_enabled(void)
-{
-    return rodata_in_spiram;
-}
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-esp_err_t esp_spiram_enable_instruction_access(void)
-{
-    //TODO IDF-4318, `pages_for_flash` will be overwritten, however it influences the psram size to be added to the heap allocator.
-    abort();
-}
-#endif
-
-#if CONFIG_SPIRAM_RODATA
-esp_err_t esp_spiram_enable_rodata_access(void)
-{
-    //TODO IDF-4318, `pages_for_flash` will be overwritten, however it influences the psram size to be added to the heap allocator.
-    abort();
-}
-#endif
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-void instruction_flash_page_info_init(void)
-{
-    uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
-
-    instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START);
-    instr_start_page &= MMU_VALID_VAL_MASK;
-    instr_end_page = instr_start_page + instr_page_cnt - 1;
-}
-
-uint32_t IRAM_ATTR instruction_flash_start_page_get(void)
-{
-    return instr_start_page;
-}
-
-uint32_t IRAM_ATTR instruction_flash_end_page_get(void)
-{
-    return instr_end_page;
-}
-
-int IRAM_ATTR instruction_flash2spiram_offset(void)
-{
-    return instr_flash2spiram_offs;
-}
-#endif
-
-#if CONFIG_SPIRAM_RODATA
-void rodata_flash_page_info_init(void)
-{
-    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;
-
-    rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
-    rodata_start_page &= MMU_VALID_VAL_MASK;
-    rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
-}
-
-uint32_t IRAM_ATTR rodata_flash_start_page_get(void)
-{
-    return rodata_start_page;
-}
-
-uint32_t IRAM_ATTR rodata_flash_end_page_get(void)
-{
-    return rodata_end_page;
-}
-
-int IRAM_ATTR rodata_flash2spiram_offset(void)
-{
-    return rodata_flash2spiram_offs;
-}
-#endif
-
-/*
- Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
- otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
-*/
-void IRAM_ATTR esp_spiram_writeback_cache(void)
-{
-    extern void Cache_WriteBack_All(void);
-    Cache_WriteBack_All();
-}
-
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return true SPI RAM has been initialized successfully
- * @return false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void)
-{
-    return s_spiram_inited;
-}
-
-uint8_t esp_spiram_get_cs_io(void)
-{
-    return psram_get_cs_io();
-}
-
-/*
- Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
- true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
- initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
-*/
-static bool esp_spiram_test(uint32_t v_start, uint32_t size)
-{
-    volatile int *spiram = (volatile int *)v_start;
-
-    size_t s = size;
-    size_t p;
-    int errct = 0;
-    int initial_err = -1;
-
-    for (p = 0; p < (s / sizeof(int)); p += 8) {
-        spiram[p] = p ^ 0xAAAAAAAA;
-    }
-    for (p = 0; p < (s / sizeof(int)); p += 8) {
-        if (spiram[p] != (p ^ 0xAAAAAAAA)) {
-            errct++;
-            if (errct == 1) {
-                initial_err = p * 4;
-            }
-            if (errct < 4) {
-                ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p ^ 0xAAAAAAAA);
-            }
-        }
-    }
-    if (errct) {
-        ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW);
-        return false;
-    } else {
-        ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
-        return true;
-    }
-}

+ 0 - 90
components/esp_hw_support/port/esp32s3/spiram_psram.h

@@ -1,90 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#pragma once
-
-#include "soc/spi_mem_reg.h"
-#include "esp_err.h"
-#include "sdkconfig.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PSRAM_SIZE_2MB                  (2 * 1024 * 1024)
-#define PSRAM_SIZE_4MB                  (4 * 1024 * 1024)
-#define PSRAM_SIZE_8MB                  (8 * 1024 * 1024)
-#define PSRAM_SIZE_16MB                 (16 * 1024 * 1024)
-#define PSRAM_SIZE_32MB                 (32 * 1024 * 1024)
-
-typedef enum {
-    PSRAM_CACHE_S80M = 1,
-    PSRAM_CACHE_S40M,
-    PSRAM_CACHE_MAX,
-} psram_cache_mode_t;
-
-
-/*
-See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
-
-Important is that NORMAL works with the app CPU cache disabled, but gives huge cache coherency
-issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
-issues but cannot be used when the app CPU cache is disabled.
-*/
-typedef enum {
-    PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
-    PSRAM_VADDR_MODE_LOWHIGH,  ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
-    PSRAM_VADDR_MODE_EVENODD,  ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
-} psram_vaddr_mode_t;
-
-/**
- * @brief To get the physical psram size in bytes.
- *
- * @param[out] out_size_bytes    physical psram size in bytes.
- */
-esp_err_t psram_get_physical_size(uint32_t *out_size_bytes);
-
-/**
- * @brief To get the available physical psram size in bytes.
- *
- * If ECC is enabled, available PSRAM size will be 15/16 times its physical size.
- * If not, it equals to the physical psram size.
- * @note For now ECC is only enabled on ESP32S3 Octal PSRAM
- *
- * @param[out] out_size_bytes    availabe physical psram size in bytes.
- */
-esp_err_t psram_get_available_size(uint32_t *out_size_bytes);
-
-/**
- * @brief psram cache enable function
- *
- * Esp-idf uses this to initialize cache for psram, mapping it into the main memory
- * address space.
- *
- * @param mode       SPI mode to access psram in
- * @param vaddrmode  Mode the psram cache works in.
- * @return ESP_OK on success, ESP_ERR_INVALID_STATE when VSPI peripheral is needed but cannot be claimed.
- */
-esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
-
-typedef enum {
-    SPIRAM_WRAP_MODE_16B,
-    SPIRAM_WRAP_MODE_32B,
-    SPIRAM_WRAP_MODE_64B,
-    SPIRAM_WRAP_MODE_DISABLE
-} spiram_wrap_mode_t;
-
-esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode);
-
-/**
- * @brief get psram CS IO
- *
- * @return psram CS IO
- */
-uint8_t psram_get_cs_io(void);
-
-#ifdef __cplusplus
-}
-#endif

+ 2 - 7
components/esp_hw_support/port/include/esp_spiram.h

@@ -6,10 +6,5 @@
 
 #pragma once
 
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
-#endif
+#include "esp_psram.h"
+#warning "esp_spiram.h is deprecated, please migrate to esp_psram.h"

+ 3 - 7
components/esp_hw_support/sleep_gpio.c

@@ -21,12 +21,8 @@
 #include "esp_private/sleep_gpio.h"
 #include "bootloader_common.h"
 
-#ifdef CONFIG_IDF_TARGET_ESP32
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
+#if CONFIG_SPIRAM
+#include "esp_private/esp_psram_io.h"
 #endif
 
 static const char *TAG = "sleep";
@@ -63,7 +59,7 @@ void esp_sleep_config_gpio_isolate(void)
         }
     }
 #if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
-    gpio_sleep_set_pull_mode(esp_spiram_get_cs_io(), GPIO_PULLUP_ONLY);
+    gpio_sleep_set_pull_mode(esp_psram_io_get_cs_io(), GPIO_PULLUP_ONLY);
 #endif
 #if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
     gpio_sleep_set_pull_mode(bootloader_flash_get_cs_io(), GPIO_PULLUP_ONLY);

+ 1 - 1
components/esp_hw_support/test/CMakeLists.txt

@@ -1,5 +1,5 @@
 idf_component_register(SRC_DIRS "."
                     PRIV_INCLUDE_DIRS "${include_dirs}"
-                    PRIV_REQUIRES cmock test_utils esp_hw_support driver efuse esp_timer)
+                    PRIV_REQUIRES cmock test_utils esp_hw_support driver efuse esp_timer esp_psram)
 
  target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_test_dport_xt_highint5")

+ 4 - 0
components/esp_lcd/CMakeLists.txt

@@ -21,3 +21,7 @@ idf_component_register(SRCS ${srcs}
                        INCLUDE_DIRS ${includes}
                        PRIV_REQUIRES ${priv_requires}
                        LDFRAGMENTS linker.lf)
+
+if(CONFIG_SPIRAM)
+    idf_component_optional_requires(PRIVATE esp_psram)
+endif()

+ 2 - 2
components/esp_lcd/src/esp_lcd_rgb_panel.c

@@ -32,7 +32,7 @@
 #include "driver/gpio.h"
 #include "esp_private/periph_ctrl.h"
 #if CONFIG_SPIRAM
-#include "spiram.h"
+#include "esp_psram.h"
 #endif
 #include "esp_lcd_common.h"
 #include "soc/lcd_periph.h"
@@ -141,7 +141,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
     // fb_in_psram is only an option, if there's no PSRAM on board, we still alloc from SRAM
     if (rgb_panel_config->flags.fb_in_psram) {
 #if CONFIG_SPIRAM_USE_MALLOC || CONFIG_SPIRAM_USE_CAPS_ALLOC
-        if (esp_spiram_is_initialized()) {
+        if (esp_psram_is_initialized()) {
             alloc_from_psram = true;
         }
 #endif

+ 58 - 0
components/esp_psram/CMakeLists.txt

@@ -0,0 +1,58 @@
+idf_build_get_property(target IDF_TARGET)
+
+set(includes "include")
+
+set(priv_requires efuse heap spi_flash)
+if(${target} STREQUAL "esp32")
+    list(APPEND priv_requires bootloader_support)
+    # [refactor-todo]: requires "driver" for `spicommon_periph_claim`
+    list(APPEND priv_requires driver)
+endif()
+
+set(srcs)
+
+if(CONFIG_SPIRAM)
+    list(APPEND srcs "esp_psram.c"
+                     "mmu.c"
+                     "mmu_psram.c")
+
+    if(${target} STREQUAL "esp32")
+        list(APPEND srcs "esp32/esp_psram_extram_cache.c"
+                         "esp32/esp_himem.c")
+    endif()
+
+    if(CONFIG_SPIRAM_MODE_QUAD)
+        list(APPEND srcs "${target}/esp_psram_impl_quad.c")
+    elseif(CONFIG_SPIRAM_MODE_OCT)
+        list(APPEND srcs "${target}/esp_psram_impl_octal.c")
+    endif()
+endif()
+
+idf_component_register(SRCS ${srcs}
+                       INCLUDE_DIRS ${includes}
+                       PRIV_REQUIRES ${priv_requires}
+                       LDFRAGMENTS linker.lf)
+
+if(CONFIG_IDF_TARGET_ESP32 AND CONFIG_SPIRAM_CACHE_WORKAROUND AND NOT BOOTLOADER_BUILD)
+    # Note: Adding as a PUBLIC compile option here causes this option to propagate to all
+    # components that depend on esp_psram.
+    #
+    # To handle some corner cases, the same flag is set in project_include.cmake
+    target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue)
+    # also, make sure we link with this option so correct toolchain libs are pulled in
+    target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue)
+    # set strategy selected
+    # note that we don't need to set link options as the library linked is independent of this
+    if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST)
+        target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=dupldst)
+        target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=dupldst)
+    endif()
+    if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW)
+        target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=memw)
+        target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=memw)
+    endif()
+    if(CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS)
+        target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=nops)
+        target_link_libraries(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-strategy=nops)
+    endif()
+endif()

+ 7 - 0
components/esp_psram/Kconfig

@@ -0,0 +1,7 @@
+menu "ESP PSRAM"
+
+    # Will be refactored after !18050 to merge target-specific items
+
+    orsource "./$IDF_TARGET/Kconfig.spiram"
+
+endmenu  # ESP PSRAM

+ 0 - 0
components/esp_hw_support/Kconfig.spiram.common → components/esp_psram/Kconfig.spiram.common


+ 7 - 11
components/esp_hw_support/port/esp32/Kconfig.spiram → components/esp_psram/esp32/Kconfig.spiram

@@ -30,14 +30,6 @@ menu "SPI RAM config"
 
     endchoice
 
-    config SPIRAM_SIZE
-        int
-        default -1 if SPIRAM_TYPE_AUTO
-        default 2097152 if SPIRAM_TYPE_ESPPSRAM16
-        default 4194304 if SPIRAM_TYPE_ESPPSRAM32
-        default 8388608 if SPIRAM_TYPE_ESPPSRAM64
-        default 0
-
     choice SPIRAM_SPEED
         prompt "Set RAM clock speed"
         default SPIRAM_SPEED_40M
@@ -62,8 +54,12 @@ menu "SPI RAM config"
             bool "80MHz clock speed"
     endchoice
 
-    # insert non-chip-specific items here
-    source "$IDF_PATH/components/esp_hw_support/Kconfig.spiram.common"
+    config SPIRAM_SPEED
+        int
+        default 80 if SPIRAM_SPEED_80M
+        default 40 if SPIRAM_SPEED_40M
+
+    source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common"    # insert non-chip-specific items here
 
     config SPIRAM_CACHE_WORKAROUND
         bool "Enable workaround for bug in SPI RAM cache for Rev1 ESP32s"
@@ -244,7 +240,7 @@ menu "SPI RAM config"
             memories, but these have to be bank-switched in and out of this address space. Enabling this allows you
             to reserve some MMU pages for this, which allows the use of the esp_himem api to manage these banks.
 
-            #Note that this is limited to 62 banks, as esp_spiram_writeback_cache needs some kind of mapping of
+            #Note that this is limited to 62 banks, as esp_psram_extram_writeback_cache needs some kind of mapping of
             #some banks below that mark to work. We cannot at this moment guarantee this to exist when himem is
             #enabled.
 

+ 10 - 6
components/esp_hw_support/port/esp32/esp_himem.c → components/esp_psram/esp32/esp_himem.c

@@ -6,14 +6,15 @@
 
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "esp32/spiram.h"
-#include "esp_private/spiram_private.h"
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
 #include "esp32/rom/cache.h"
 #include "sdkconfig.h"
-#include "esp_himem.h"
+#include "esp32/himem.h"
 #include "soc/soc.h"
 #include "esp_log.h"
 #include "esp_check.h"
+#include "../esp_psram_impl.h"
 
 /*
 So, why does the API look this way and is so inflexible to not allow any maps beyond the full 32K chunks? Most of
@@ -112,7 +113,9 @@ static void set_bank(int virt_bank, int phys_bank, int ct)
 size_t esp_himem_get_phys_size(void)
 {
     int paddr_start = (4096 * 1024) - (CACHE_BLOCKSIZE * SPIRAM_BANKSWITCH_RESERVE);
-    return esp_spiram_get_size()-paddr_start;
+    uint32_t psram_available_size = 0;
+    esp_psram_impl_get_available_size(&psram_available_size);
+    return psram_available_size - paddr_start;
 }
 
 size_t esp_himem_get_free_size(void)
@@ -132,7 +135,8 @@ size_t esp_himem_reserved_area_size(void) {
 void __attribute__((constructor)) esp_himem_init(void)
 {
     if (SPIRAM_BANKSWITCH_RESERVE == 0) return;
-    int maxram=esp_spiram_get_size();
+    uint32_t maxram = 0;
+    esp_psram_impl_get_available_size(&maxram);
     //catch double init
     ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL,  , TAG, "already initialized"); //Looks weird; last arg is empty so it expands to 'return ;'
     ESP_RETURN_ON_FALSE(s_range_descriptor == NULL,  , TAG, "already initialized");
@@ -350,7 +354,7 @@ esp_err_t esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len)
         s_ram_descriptor[ramblock].is_mapped = 0;
         s_range_descriptor[range->block_start + i + range_block].is_mapped = 0;
     }
-    esp_spiram_writeback_cache();
+    esp_psram_extram_writeback_cache();
     portEXIT_CRITICAL(&spinlock);
     return ESP_OK;
 }

+ 78 - 0
components/esp_psram/esp32/esp_psram_extram_cache.c

@@ -0,0 +1,78 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/dport_reg.h"
+#include "esp_attr.h"
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
+
+#if CONFIG_FREERTOS_UNICORE
+#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
+#else
+#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
+#endif
+
+
+/*
+ Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
+ otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
+ Note that this routine assumes some unique mapping for the first 2 banks of the PSRAM memory range, as well as the
+ 2 banks after the 2 MiB mark.
+*/
+void IRAM_ATTR esp_psram_extram_writeback_cache(void)
+{
+    int x;
+    volatile int i=0;
+    volatile uint8_t *psram=(volatile uint8_t*)SOC_EXTRAM_DATA_LOW;
+    int cache_was_disabled=0;
+
+    if (!esp_psram_is_initialized()) return;
+
+    //We need cache enabled for this to work. Re-enable it if needed; make sure we
+    //disable it again on exit as well.
+    if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
+        cache_was_disabled|=(1<<0);
+        DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
+    }
+#ifndef CONFIG_FREERTOS_UNICORE
+    if (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
+        cache_was_disabled|=(1<<1);
+        DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
+    }
+#endif
+
+#if (PSRAM_MODE != PSRAM_VADDR_MODE_LOWHIGH)
+    /*
+    Single-core and even/odd mode only have 32K of cache evenly distributed over the address lines. We can clear
+    the cache by just reading 64K worth of cache lines.
+    */
+    for (x=0; x<1024*64; x+=32) {
+        i+=psram[x];
+    }
+#else
+    /*
+    Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI flash and another 32K for the highest
+    2MiB. Clear this by reading from both regions.
+    Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If
+    we ever support external RAM chips of 2M or smaller, this may need adjusting.
+    */
+    for (x=0; x<1024*64; x+=32) {
+        i+=psram[x];
+        i+=psram[x+(1024*1024*2)];
+    }
+#endif
+
+    if (cache_was_disabled&(1<<0)) {
+        while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) ;
+        DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
+    }
+#ifndef CONFIG_FREERTOS_UNICORE
+    if (cache_was_disabled&(1<<1)) {
+        while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1);
+        DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
+    }
+#endif
+}

+ 58 - 23
components/esp_hw_support/port/esp32/spiram_psram.c → components/esp_psram/esp32/esp_psram_impl_quad.c

@@ -16,7 +16,7 @@
 #include "esp_types.h"
 #include "esp_log.h"
 #include "esp_efuse.h"
-#include "spiram_psram.h"
+#include "../esp_psram_impl.h"
 #include "esp32/rom/spi_flash.h"
 #include "esp32/rom/cache.h"
 #include "esp32/rom/efuse.h"
@@ -24,6 +24,7 @@
 #include "soc/dport_reg.h"
 #include "soc/efuse_periph.h"
 #include "soc/soc_caps.h"
+#include "soc/spi_periph.h"
 #include "driver/gpio.h"
 #include "hal/gpio_hal.h"
 #include "driver/spi_common_internal.h"
@@ -123,6 +124,23 @@ typedef enum {
 #define PICO_V3_02_PSRAM_CLK_IO    10
 #define PICO_V3_02_PSRAM_CS_IO     9
 
+typedef enum {
+    PSRAM_CACHE_F80M_S40M = 0,
+    PSRAM_CACHE_F40M_S40M,
+    PSRAM_CACHE_F80M_S80M,
+    PSRAM_CACHE_MAX,
+} psram_cache_speed_t;
+
+#if CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_40M
+#define PSRAM_SPEED PSRAM_CACHE_F40M_S40M
+#elif CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
+#define PSRAM_SPEED PSRAM_CACHE_F80M_S40M
+#elif CONFIG_SPIRAM_SPEED_80M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
+#define PSRAM_SPEED PSRAM_CACHE_F80M_S80M
+#else
+#error "FLASH speed can only be equal to or higher than SRAM speed while SRAM is enabled!"
+#endif
+
 typedef struct {
     uint8_t flash_clk_io;
     uint8_t flash_cs_io;
@@ -165,7 +183,7 @@ typedef struct {
 #define PSRAM_SPICLKEN      DPORT_SPI01_CLK_EN
 #endif
 
-static const char* TAG = "psram";
+static const char* TAG = "quad_psram";
 typedef enum {
     PSRAM_SPI_1  = 0x1,
     PSRAM_SPI_2,
@@ -173,7 +191,7 @@ typedef enum {
     PSRAM_SPI_MAX ,
 } psram_spi_num_t;
 
-static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX;
+static psram_cache_speed_t s_psram_mode = PSRAM_CACHE_MAX;
 static psram_clk_mode_t s_clk_mode = PSRAM_CLK_MODE_DCLK;
 static uint64_t s_psram_id = 0;
 static bool s_2t_mode_enabled = false;
@@ -198,11 +216,11 @@ typedef struct {
     uint32_t dummyBitLen;
 } psram_cmd_t;
 
-static void psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
+static void psram_cache_init(psram_cache_speed_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
 
 static uint8_t s_psram_cs_io = (uint8_t)-1;
 
-uint8_t psram_get_cs_io(void)
+uint8_t esp_psram_impl_get_cs_io(void)
 {
     return s_psram_cs_io;
 }
@@ -337,7 +355,9 @@ static int psram_cmd_config(psram_spi_num_t spi_num, psram_cmd_t* pInData)
         // Load send buffer
         int len = (pInData->txDataBitLen + 31) / 32;
         if (p_tx_val != NULL) {
-            memcpy((void*)SPI_W0_REG(spi_num), p_tx_val, len * 4);
+            for (int i = 0; i < len; i++) {
+                WRITE_PERI_REG(SPI_W0_REG(spi_num), p_tx_val[i]);
+            }
         }
         // Set data send buffer length.Max data length 64 bytes.
         SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spi_num), SPI_USR_MOSI_DBITLEN, (pInData->txDataBitLen - 1),
@@ -667,7 +687,7 @@ void psram_set_cs_timing(psram_spi_num_t spi_num, psram_clk_mode_t clk_mode)
 }
 
 //spi param init for psram
-void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
+void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_speed_t mode)
 {
     CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_TRANS_DONE << 5);
     // SPI_CPOL & SPI_CPHA
@@ -687,7 +707,7 @@ void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
 }
 
 //psram gpio init , different working frequency we have different solutions
-static void IRAM_ATTR psram_gpio_config(psram_io_t *psram_io, psram_cache_mode_t mode)
+static void IRAM_ATTR psram_gpio_config(psram_io_t *psram_io, psram_cache_speed_t mode)
 {
     int spi_cache_dummy = 0;
     uint32_t rd_mode_reg = READ_PERI_REG(SPI_CTRL_REG(0));
@@ -784,19 +804,6 @@ static void IRAM_ATTR psram_gpio_config(psram_io_t *psram_io, psram_cache_mode_t
     }
 }
 
-psram_size_t psram_get_size(void)
-{
-    if ((PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_64MBITS) || PSRAM_IS_64MBIT_TRIAL(s_psram_id)) {
-        return s_2t_mode_enabled ? PSRAM_SIZE_32MBITS : PSRAM_SIZE_64MBITS;
-    } else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_32MBITS) {
-        return PSRAM_SIZE_32MBITS;
-    } else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_16MBITS) {
-        return PSRAM_SIZE_16MBITS;
-    } else {
-        return PSRAM_SIZE_MAX;
-    }
-}
-
 //used in UT only
 bool psram_is_32mbit_ver0(void)
 {
@@ -807,8 +814,9 @@ bool psram_is_32mbit_ver0(void)
  * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
  * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
  */
-esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
+esp_err_t IRAM_ATTR esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode)   //psram init
 {
+    psram_cache_speed_t mode = PSRAM_SPEED;
     psram_io_t psram_io={0};
     uint32_t pkg_ver = esp_efuse_get_pkg_ver();
     if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
@@ -1010,7 +1018,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
 }
 
 //register initialization for sram cache params and r/w commands
-static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
+static void IRAM_ATTR psram_cache_init(psram_cache_speed_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
 {
     switch (psram_cache_mode) {
         case PSRAM_CACHE_F80M_S80M:
@@ -1093,4 +1101,31 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
     CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
 }
 
+
+esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes)
+{
+    if (!out_size_bytes) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    if ((PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_64MBITS) || PSRAM_IS_64MBIT_TRIAL(s_psram_id)) {
+        *out_size_bytes = s_2t_mode_enabled ? PSRAM_SIZE_4MB : PSRAM_SIZE_8MB;
+    } else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_32MBITS) {
+        *out_size_bytes = PSRAM_SIZE_4MB;
+    } else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_16MBITS) {
+        *out_size_bytes = PSRAM_SIZE_2MB;
+    } else {
+        return ESP_ERR_NOT_SUPPORTED;
+    }
+    return ESP_OK;
+}
+
+/**
+ * This function is to get the available physical psram size in bytes.
+ * On ESP32, all of the PSRAM physical region are available
+ */
+esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
+{
+    return esp_psram_impl_get_physical_size(out_size_bytes);
+}
 #endif // CONFIG_SPIRAM

+ 1 - 9
components/esp_hw_support/port/esp32s2/Kconfig.spiram → components/esp_psram/esp32s2/Kconfig.spiram

@@ -33,14 +33,6 @@ menu "SPI RAM config"
             bool "ESP-PSRAM64 or LY68L6400"
     endchoice
 
-    config SPIRAM_SIZE
-        int
-        default -1 if SPIRAM_TYPE_AUTO
-        default 2097152 if SPIRAM_TYPE_ESPPSRAM16
-        default 4194304 if SPIRAM_TYPE_ESPPSRAM32
-        default 8388608 if SPIRAM_TYPE_ESPPSRAM64
-        default 0
-
     menu "PSRAM clock and cs IO for ESP32S2"
         depends on SPIRAM
         config DEFAULT_PSRAM_CLK_IO
@@ -96,6 +88,6 @@ menu "SPI RAM config"
         default 40 if SPIRAM_SPEED_26M
         default 40 if SPIRAM_SPEED_20M
 
-    source "$IDF_PATH/components/esp_hw_support/Kconfig.spiram.common"   #insert non-chip-specific items here
+    source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common"    # insert non-chip-specific items here
 
 endmenu

+ 28 - 24
components/esp_hw_support/port/esp32s2/spiram_psram.c → components/esp_psram/esp32s2/esp_psram_impl_quad.c

@@ -15,28 +15,15 @@
 #include "esp_err.h"
 #include "esp_types.h"
 #include "esp_log.h"
-#include "spiram_psram.h"
+#include "../esp_psram_impl.h"
 #include "esp32s2/rom/spi_flash.h"
 #include "esp32s2/rom/opi_flash.h"
-#include "esp32s2/rom/cache.h"
 #include "esp32s2/rom/efuse.h"
 #include "esp_rom_efuse.h"
-#include "soc/dport_reg.h"
-#include "soc/efuse_periph.h"
-#include "soc/soc_caps.h"
 #include "soc/spi_reg.h"
 #include "soc/io_mux_reg.h"
-#include "soc/syscon_reg.h"
-#include "soc/efuse_reg.h"
-#include "soc/soc.h"
-#include "driver/gpio.h"
-#include "driver/spi_common_internal.h"
-#include "driver/spi_common.h"
-#include "esp_private/periph_ctrl.h"
-#include "bootloader_common.h"
-#include "soc/rtc.h"
-
-static const char* TAG = "psram";
+
+static const char* TAG = "quad_psram";
 
 //Commands for PSRAM chip
 #define PSRAM_READ                 0x03
@@ -153,15 +140,31 @@ typedef enum {
     PSRAM_CMD_SPI,
 } psram_cmd_mode_t;
 
+typedef enum {
+    PSRAM_CACHE_S80M = 1,
+    PSRAM_CACHE_S40M,
+    PSRAM_CACHE_S26M,
+    PSRAM_CACHE_S20M,
+    PSRAM_CACHE_MAX,
+} psram_cache_speed_t;
+
+#if CONFIG_SPIRAM_SPEED_40M
+#define PSRAM_SPEED PSRAM_CACHE_S40M
+#elif CONFIG_SPIRAM_SPEED_80M
+#define PSRAM_SPEED PSRAM_CACHE_S80M
+#else
+#define PSRAM_SPEED PSRAM_CACHE_S20M
+#endif
+
 typedef esp_rom_spi_cmd_t psram_cmd_t;
 
 static uint32_t s_psram_id = 0;
-static void psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
+static void psram_cache_init(psram_cache_speed_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
 extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode);
 
 static uint8_t s_psram_cs_io = (uint8_t)-1;
 
-uint8_t psram_get_cs_io(void)
+uint8_t esp_psram_impl_get_cs_io(void)
 {
     return s_psram_cs_io;
 }
@@ -357,7 +360,7 @@ static void psram_set_spi0_cache_cs_timing(psram_clk_mode_t clk_mode)
 }
 
 //psram gpio init , different working frequency we have different solutions
-static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
+static void IRAM_ATTR psram_gpio_config(psram_cache_speed_t mode)
 {
     psram_io_t psram_io = PSRAM_IO_CONF_DEFAULT();
     const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
@@ -395,8 +398,9 @@ static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode)
  * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
  * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
  */
-esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
+esp_err_t IRAM_ATTR esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode)   //psram init
 {
+    psram_cache_speed_t mode = PSRAM_SPEED;
     assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
     // GPIO related settings
     psram_gpio_config(mode);
@@ -468,7 +472,7 @@ static void IRAM_ATTR psram_clock_set(int spi_num, int8_t freqdiv)
 }
 
 //register initialization for sram cache params and r/w commands
-static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
+static void IRAM_ATTR psram_cache_init(psram_cache_speed_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
 {
     int extra_dummy = 0;
     switch (psram_cache_mode) {
@@ -533,7 +537,7 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
  *
  * Consider moving these to another file if this kind of APIs grows dramatically
  *-------------------------------------------------------------------------------*/
-esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
+esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes)
 {
     if (!out_size_bytes) {
         return ESP_ERR_INVALID_ARG;
@@ -555,7 +559,7 @@ esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
  * This function is to get the available physical psram size in bytes.
  * On ESP32S2, all of the PSRAM physical region are available
  */
-esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
+esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
 {
-    return psram_get_physical_size(out_size_bytes);
+    return esp_psram_impl_get_physical_size(out_size_bytes);
 }

+ 1 - 11
components/esp_hw_support/port/esp32s3/Kconfig.spiram → components/esp_psram/esp32s3/Kconfig.spiram

@@ -42,16 +42,6 @@ menu "SPI RAM config"
             bool "ESP-PSRAM64 , LY68L6400 or APS6408"
     endchoice
 
-    config SPIRAM_SIZE
-        int
-        default -1 if SPIRAM_TYPE_AUTO
-        default 2097152 if SPIRAM_TYPE_ESPPSRAM16
-        default 4194304 if SPIRAM_TYPE_ESPPSRAM32
-        default 8388608 if SPIRAM_TYPE_ESPPSRAM64
-        default 16777216 if SPIRAM_TYPE_ESPPSRAM128
-        default 33554432 if SPIRAM_TYPE_ESPPSRAM256
-        default 0
-
     menu "PSRAM Clock and CS IO for ESP32S3"
         depends on SPIRAM
         config DEFAULT_PSRAM_CLK_IO
@@ -104,6 +94,6 @@ menu "SPI RAM config"
         default 80 if SPIRAM_SPEED_80M
         default 40 if SPIRAM_SPEED_40M
 
-    source "$IDF_PATH/components/esp_hw_support/Kconfig.spiram.common"      # insert non-chip-specific items here
+    source "$IDF_PATH/components/esp_psram/Kconfig.spiram.common"    # insert non-chip-specific items here
 
 endmenu

+ 6 - 14
components/esp_hw_support/port/esp32s3/opiram_psram.c → components/esp_psram/esp32s3/esp_psram_impl_octal.c

@@ -10,22 +10,14 @@
 #include "esp_err.h"
 #include "esp_types.h"
 #include "esp_log.h"
-#include "spiram_psram.h"
+#include "../esp_psram_impl.h"
 #include "esp32s3/rom/ets_sys.h"
 #include "esp32s3/rom/spi_flash.h"
 #include "esp32s3/rom/opi_flash.h"
-#include "esp32s3/rom/gpio.h"
 #include "esp32s3/rom/cache.h"
 #include "soc/gpio_periph.h"
 #include "soc/io_mux_reg.h"
-#include "soc/dport_reg.h"
 #include "soc/syscon_reg.h"
-#include "soc/gpio_sig_map.h"
-#include "soc/efuse_reg.h"
-#include "driver/gpio.h"
-#include "driver/spi_common.h"
-#include "esp_private/periph_ctrl.h"
-#include "soc/rtc.h"
 #include "esp_private/spi_flash_os.h"
 
 #define OPI_PSRAM_SYNC_READ             0x0000
@@ -102,11 +94,11 @@ typedef struct {
     } mr8;
 } opi_psram_mode_reg_t;
 
-static const char* TAG = "opi psram";
+static const char* TAG = "octal_psram";
 static uint32_t s_psram_size;   //this stands for physical psram size in bytes
 static void s_config_psram_spi_phases(void);
 
-uint8_t psram_get_cs_io(void)
+uint8_t esp_psram_impl_get_cs_io(void)
 {
     return OCT_PSRAM_CS1_IO;
 }
@@ -295,7 +287,7 @@ static void s_configure_psram_ecc(void)
 #endif
 }
 
-esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)
+esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode)
 {
     s_init_psram_pins();
     s_set_psram_cs_timing();
@@ -379,7 +371,7 @@ static void s_config_psram_spi_phases(void)
  *
  * Consider moving these to another file if this kind of APIs grows dramatically
  *-------------------------------------------------------------------------------*/
-esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
+esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes)
 {
     if (!out_size_bytes) {
         return ESP_ERR_INVALID_ARG;
@@ -393,7 +385,7 @@ esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
  * This function is to get the available physical psram size in bytes.
  * If ECC is enabled, available PSRAM size will be 15/16 times its physical size.
  */
-esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
+esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
 {
     if (!out_size_bytes) {
         return ESP_ERR_INVALID_ARG;

+ 6 - 29
components/esp_hw_support/port/esp32s3/spiram_psram.c → components/esp_psram/esp32s3/esp_psram_impl_quad.c

@@ -11,30 +11,15 @@
 #include "esp_err.h"
 #include "esp_types.h"
 #include "esp_log.h"
-#include "spiram_psram.h"
+#include "../esp_psram_impl.h"
 #include "esp32s3/rom/spi_flash.h"
 #include "esp32s3/rom/opi_flash.h"
-#include "esp32s3/rom/cache.h"
-#include "esp32s3/rom/efuse.h"
 #include "esp_rom_gpio.h"
 #include "esp_rom_efuse.h"
-#include "soc/dport_reg.h"
-#include "soc/efuse_periph.h"
-#include "soc/soc_caps.h"
-#include "soc/io_mux_reg.h"
-#include "soc/efuse_reg.h"
-#include "soc/soc.h"
-#include "soc/io_mux_reg.h"
-#include "driver/gpio.h"
 #include "hal/gpio_hal.h"
-#include "driver/spi_common_internal.h"
-#include "driver/spi_common.h"
-#include "esp_private/periph_ctrl.h"
-#include "bootloader_common.h"
-#include "soc/rtc.h"
 #include "esp_private/spi_flash_os.h"
 
-static const char* TAG = "psram";
+static const char* TAG = "quad_psram";
 
 //Commands for PSRAM chip
 #define PSRAM_READ                 0x03
@@ -96,8 +81,6 @@ static const char* TAG = "psram";
 #define SPI1_NUM    1
 #define SPI0_NUM    0
 
-
-
 typedef enum {
     PSRAM_CMD_QPI,
     PSRAM_CMD_SPI,
@@ -112,7 +95,7 @@ extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mo
 
 static uint8_t s_psram_cs_io = (uint8_t)-1;
 
-uint8_t psram_get_cs_io(void)
+uint8_t esp_psram_impl_get_cs_io(void)
 {
     return s_psram_cs_io;
 }
@@ -314,14 +297,8 @@ static void psram_gpio_config(void)
     esp_rom_spiflash_select_qio_pins(wp_io, spiconfig);
 }
 
-/*
- * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
- * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
- */
-esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
+esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode)   //psram init
 {
-    assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
-
     psram_gpio_config();
     psram_set_cs_timing();
 
@@ -401,7 +378,7 @@ static void config_psram_spi_phases(void)
  *
  * Consider moving these to another file if this kind of APIs grows dramatically
  *-------------------------------------------------------------------------------*/
-esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
+esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes)
 {
     if (!out_size_bytes) {
         return ESP_ERR_INVALID_ARG;
@@ -417,7 +394,7 @@ esp_err_t psram_get_physical_size(uint32_t *out_size_bytes)
  * When ECC is enabled, the available size will be reduced.
  * On S3 Quad PSRAM, ECC is not enabled for now.
  */
-esp_err_t psram_get_available_size(uint32_t *out_size_bytes)
+esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes)
 {
     if (!out_size_bytes) {
         return ESP_ERR_INVALID_ARG;

+ 157 - 79
components/esp_hw_support/port/esp32s2/spiram.c → components/esp_psram/esp_psram.c

@@ -19,31 +19,43 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/xtensa_api.h"
 #include "esp_heap_caps_init.h"
-#include "esp_private/spiram_private.h"
-#include "esp32s2/spiram.h"
-#include "esp_private/mmu_psram.h"
-#include "spiram_psram.h"
-
-#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
+#include "hal/mmu_hal.h"
+#include "hal/cache_ll.h"
+#include "esp_private/esp_psram_io.h"
+#include "esp_private/esp_psram_extram.h"
+#include "esp_private/mmu.h"
+#include "esp_psram_impl.h"
+#include "esp_psram.h"
+
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/himem.h"
+#include "esp32/rom/cache.h"
+#endif
 
-#if CONFIG_SPIRAM
 
-#if CONFIG_SPIRAM_SPEED_40M
-#define PSRAM_SPEED PSRAM_CACHE_S40M
-#elif CONFIG_SPIRAM_SPEED_80M
-#define PSRAM_SPEED PSRAM_CACHE_S80M
+#if CONFIG_IDF_TARGET_ESP32
+#if CONFIG_FREERTOS_UNICORE
+#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
+#else
+#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
+#endif
 #else
-#define PSRAM_SPEED PSRAM_CACHE_S20M
+#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
 #endif
 
-#define MMU_PAGE_TO_BYTES(page_id)      ((page_id) << 16)
 
+#if CONFIG_SPIRAM
 
 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
 extern uint8_t _ext_ram_bss_start;
 extern uint8_t _ext_ram_bss_end;
 #endif //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
 
+#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
+extern uint8_t _ext_ram_noinit_start;
+extern uint8_t _ext_ram_noinit_end;
+#endif  //#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
+
 //These variables are in bytes
 static intptr_t s_allocable_vaddr_start;
 static intptr_t s_allocable_vaddr_end;
@@ -51,16 +63,36 @@ static intptr_t s_mapped_vaddr_start;
 static intptr_t s_mapped_vaddr_end;
 
 static bool s_spiram_inited;
-static const char* TAG = "spiram";
+static const char* TAG = "esp_psram";
 
-static bool esp_spiram_test(uint32_t v_start, uint32_t size);
 
+#if CONFIG_IDF_TARGET_ESP32
+//If no function in esp_himem.c is used, this function will be linked into the
+//binary instead of the one in esp_himem.c, automatically making sure no memory
+//is reserved if no himem function is used.
+size_t __attribute__((weak)) esp_himem_reserved_area_size(void) {
+    return 0;
+}
+
+static void IRAM_ATTR s_mapping(int v_start, int size)
+{
+    //Enable external RAM in MMU
+    cache_sram_mmu_set(0, 0, v_start, 0, 32, (size / 1024 / 32));
+    //Flush and enable icache for APP CPU
+#if !CONFIG_FREERTOS_UNICORE
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1);
+    cache_sram_mmu_set(1, 0, v_start, 0, 32, (size / 1024 / 32));
+#endif
+}
+#endif  //CONFIG_IDF_TARGET_ESP32
 
-esp_err_t esp_spiram_init(void)
+esp_err_t esp_psram_init(void)
 {
-    assert(!s_spiram_inited);
+    if (s_spiram_inited) {
+        return ESP_ERR_INVALID_STATE;
+    }
     esp_err_t ret;
-    ret = psram_enable(PSRAM_SPEED, PSRAM_MODE);
+    ret = esp_psram_impl_enable(PSRAM_MODE);
     if (ret != ESP_OK) {
 #if CONFIG_SPIRAM_IGNORE_NOTFOUND
         ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
@@ -70,20 +102,20 @@ esp_err_t esp_spiram_init(void)
     s_spiram_inited = true;
 
     uint32_t psram_physical_size = 0;
-    ret = psram_get_physical_size(&psram_physical_size);
+    ret = esp_psram_impl_get_physical_size(&psram_physical_size);
     assert(ret == ESP_OK);
 
-#if (CONFIG_SPIRAM_SIZE != -1)
-    if (psram_physical_size != CONFIG_SPIRAM_SIZE) {
-        ESP_EARLY_LOGE(TAG, "Expected %dMB chip but found %dMB chip. Bailing out..", CONFIG_SPIRAM_SIZE / 1024 / 1024, psram_physical_size / 1024 / 1024);
-        return ESP_ERR_INVALID_SIZE;
-    }
-#endif
     ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device", psram_physical_size / (1024 * 1024));
     ESP_EARLY_LOGI(TAG, "Speed: %dMHz", CONFIG_SPIRAM_SPEED);
+#if CONFIG_IDF_TARGET_ESP32
+    ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
+                                          (PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)": \
+                                          (PSRAM_MODE==PSRAM_VADDR_MODE_LOWHIGH)?"low/high (2-core)": \
+                                          (PSRAM_MODE==PSRAM_VADDR_MODE_NORMAL)?"normal (1-core)":"ERROR");
+#endif
 
     uint32_t psram_available_size = 0;
-    ret = psram_get_available_size(&psram_available_size);
+    ret = esp_psram_impl_get_available_size(&psram_available_size);
     assert(ret == ESP_OK);
 
     __attribute__((unused)) uint32_t total_available_size = psram_available_size;
@@ -94,7 +126,7 @@ esp_err_t esp_spiram_init(void)
      *
      * Here we plan to copy FLASH instructions to psram physical address 0, which is the No.0 page.
      */
-    uint32_t start_page = 0;
+    __attribute__((unused)) uint32_t start_page = 0;
 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
     uint32_t used_page = 0;
 #endif
@@ -123,22 +155,28 @@ esp_err_t esp_spiram_init(void)
     ESP_EARLY_LOGV(TAG, "after copy .rodata, used page is %d, start_page is %d, psram_available_size is %d B", used_page, start_page, psram_available_size);
 #endif  //#if CONFIG_SPIRAM_RODATA
 
+
     //----------------------------------Map the PSRAM physical range to MMU-----------------------------//
-    static DRAM_ATTR uint32_t vaddr_start = 0;
-    mmu_map_psram(MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(start_page) + psram_available_size, &vaddr_start);
-    if (ret != ESP_OK) {
-        ESP_EARLY_LOGE(TAG, "MMU PSRAM mapping wrong!");
-        abort();
+    intptr_t vaddr_start = mmu_get_psram_vaddr_start();
+    if (vaddr_start + psram_available_size > mmu_get_psram_vaddr_end()) {
+        ESP_EARLY_LOGV(TAG, "Virtual address not enough for PSRAM!");
+        psram_available_size = mmu_get_psram_vaddr_end() - vaddr_start;
     }
 
-#if CONFIG_SPIRAM_MEMTEST
-    //After mapping, simple test SPIRAM first
-    bool ext_ram_ok = esp_spiram_test(vaddr_start, psram_available_size);
-    if (!ext_ram_ok) {
-        ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
-        abort();
-    }
-#endif  //#if CONFIG_SPIRAM_MEMTEST
+#if CONFIG_IDF_TARGET_ESP32
+    s_mapping(vaddr_start, psram_available_size);
+#else
+    uint32_t actual_mapped_len = 0;
+    mmu_hal_map_region(0, MMU_TARGET_PSRAM0, vaddr_start, MMU_PAGE_TO_BYTES(start_page), psram_available_size, &actual_mapped_len);
+    ESP_EARLY_LOGV(TAG, "actual_mapped_len is 0x%x bytes", actual_mapped_len);
+
+    cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, vaddr_start, actual_mapped_len);
+    cache_ll_l1_enable_bus(0, bus_mask);
+#if !CONFIG_FREERTOS_UNICORE
+    bus_mask = cache_ll_l1_get_bus(1, vaddr_start, actual_mapped_len);
+    cache_ll_l1_enable_bus(1, bus_mask);
+#endif
+#endif  //#if CONFIG_IDF_TARGET_ESP32
 
     /*------------------------------------------------------------------------------
     * After mapping, we DON'T care about the PSRAM PHYSICAL ADDRESSS ANYMORE!
@@ -153,10 +191,19 @@ esp_err_t esp_spiram_init(void)
     //should never be negative number
     uint32_t ext_bss_size = ((intptr_t)&_ext_ram_bss_end - (intptr_t)&_ext_ram_bss_start);
     ESP_EARLY_LOGV(TAG, "ext_bss_size is %d", ext_bss_size);
-
     s_allocable_vaddr_start += ext_bss_size;
 #endif  //#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
 
+#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
+    uint32_t ext_noinit_size = ((intptr_t)&_ext_ram_noinit_end - (intptr_t)&_ext_ram_noinit_start);
+    ESP_EARLY_LOGV(TAG, "ext_noinit_size is %d", ext_noinit_size);
+    s_allocable_vaddr_start += ext_noinit_size;
+#endif
+
+#if CONFIG_IDF_TARGET_ESP32
+    s_allocable_vaddr_end -= esp_himem_reserved_area_size() - 1;
+#endif
+
     ESP_EARLY_LOGV(TAG, "s_allocable_vaddr_start is 0x%x, s_allocable_vaddr_end is 0x%x", s_allocable_vaddr_start, s_allocable_vaddr_end);
     return ESP_OK;
 }
@@ -165,13 +212,13 @@ esp_err_t esp_spiram_init(void)
  * Add the PSRAM available region to heap allocator. Heap allocator knows the capabilities of this type of memory,
  * so there's no need to explicitly specify them.
  */
-esp_err_t esp_spiram_add_to_heapalloc(void)
+esp_err_t esp_psram_extram_add_to_heap_allocator(void)
 {
     ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (s_allocable_vaddr_end - s_allocable_vaddr_start) / 1024);
     return heap_caps_add_region(s_allocable_vaddr_start, s_allocable_vaddr_end);
 }
 
-esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
+esp_err_t IRAM_ATTR esp_psram_extram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend)
 {
     if (!out_vstart || !out_vend) {
         return ESP_ERR_INVALID_ARG;
@@ -186,7 +233,7 @@ esp_err_t IRAM_ATTR esp_spiram_get_mapped_range(intptr_t *out_vstart, intptr_t *
     return ESP_OK;
 }
 
-esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
+esp_err_t esp_psram_extram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
 {
     if (!out_vstart || !out_vend) {
         return ESP_ERR_INVALID_ARG;
@@ -201,7 +248,31 @@ esp_err_t esp_spiram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend)
     return ESP_OK;
 }
 
-esp_err_t esp_spiram_reserve_dma_pool(size_t size)
+#if CONFIG_IDF_TARGET_ESP32
+esp_err_t esp_psram_extram_reserve_dma_pool(size_t size) {
+    ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
+    /* Pool may be allocated in multiple non-contiguous chunks, depending on available RAM */
+    while (size > 0) {
+        size_t next_size = heap_caps_get_largest_free_block(MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
+        next_size = MIN(next_size, size);
+
+        ESP_EARLY_LOGD(TAG, "Allocating block of size %d bytes", next_size);
+        uint8_t *dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
+        if (!dma_heap || next_size == 0) {
+            return ESP_ERR_NO_MEM;
+        }
+
+        uint32_t caps[] = { 0, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT };
+        esp_err_t e = heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap+next_size-1);
+        if (e != ESP_OK) {
+            return e;
+        }
+        size -= next_size;
+    }
+    return ESP_OK;
+}
+#else
+esp_err_t esp_psram_extram_reserve_dma_pool(size_t size)
 {
     if (size == 0) {
         return ESP_OK; //no-op
@@ -214,31 +285,27 @@ esp_err_t esp_spiram_reserve_dma_pool(size_t size)
     uint32_t caps[] = {MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
     return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size);
 }
+#endif
 
-/*
- Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
- otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
-*/
-void IRAM_ATTR esp_spiram_writeback_cache(void)
+bool IRAM_ATTR esp_psram_is_initialized(void)
 {
-    extern void Cache_WriteBack_All(void);
-    Cache_WriteBack_All();
+    return s_spiram_inited;
 }
 
-/**
- * @brief If SPI RAM(PSRAM) has been initialized
- *
- * @return true SPI RAM has been initialized successfully
- * @return false SPI RAM hasn't been initialized or initialized failed
- */
-bool esp_spiram_is_initialized(void)
+size_t esp_psram_get_size(void)
 {
-    return s_spiram_inited;
+    uint32_t available_size = 0;
+    esp_err_t ret = esp_psram_impl_get_available_size(&available_size);
+    if (ret != ESP_OK) {
+        //This means PSRAM isn't initialised, to keep back-compatibility, set size to 0.
+        available_size = 0;
+    }
+    return (size_t)available_size;
 }
 
-uint8_t esp_spiram_get_cs_io(void)
+uint8_t esp_psram_io_get_cs_io(void)
 {
-    return psram_get_cs_io();
+    return esp_psram_impl_get_cs_io();
 }
 
 /*
@@ -246,34 +313,45 @@ uint8_t esp_spiram_get_cs_io(void)
  true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
  initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
 */
-static bool esp_spiram_test(uint32_t v_start, uint32_t size)
+bool esp_psram_extram_test(void)
 {
-    volatile int *spiram = (volatile int *)v_start;
+#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
+    const void *keepout_addr_low = (const void*)&_ext_ram_noinit_start;
+    const void *keepout_addr_high = (const void*)&_ext_ram_noinit_end;
+#else
+    const void *keepout_addr_low = 0;
+    const void *keepout_addr_high = 0;
+#endif
 
-    size_t s = size;
+    volatile int *spiram = (volatile int *)s_mapped_vaddr_start;
     size_t p;
-    int errct = 0;
-    int initial_err = -1;
-
-    for (p = 0; p < (s / sizeof(int)); p += 8) {
-        spiram[p] = p ^ 0xAAAAAAAA;
+    size_t s = s_mapped_vaddr_end - s_mapped_vaddr_start;
+    int errct=0;
+    int initial_err=-1;
+    for (p=0; p<(s/sizeof(int)); p+=8) {
+        const void *addr = (const void *)&spiram[p];
+        if ((keepout_addr_low <= addr) && (addr < keepout_addr_high)) {
+            continue;
+        }
+        spiram[p]=p^0xAAAAAAAA;
     }
-    for (p = 0; p < (s / sizeof(int)); p += 8) {
-        if (spiram[p] != (p ^ 0xAAAAAAAA)) {
+    for (p=0; p<(s/sizeof(int)); p+=8) {
+        const void *addr = (const void *)&spiram[p];
+        if ((keepout_addr_low <= addr) && (addr < keepout_addr_high)) {
+            continue;
+        }
+        if (spiram[p]!=(p^0xAAAAAAAA)) {
             errct++;
-            if (errct == 1) {
-                initial_err = p * 4;
-            }
-            if (errct < 4) {
-                ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p ^ 0xAAAAAAAA);
-            }
+            if (errct==1) initial_err=p*4;
         }
     }
     if (errct) {
-        ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW);
+        ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err + s_mapped_vaddr_start);
         return false;
     } else {
+        ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
         return true;
     }
 }
+
 #endif  //#if CONFIG_SPIRAM

+ 10 - 30
components/esp_hw_support/port/esp32s2/spiram_psram.h → components/esp_psram/esp_psram_impl.h

@@ -6,7 +6,6 @@
 
 #pragma once
 
-#include "soc/spi_mem_reg.h"
 #include "esp_err.h"
 #include "sdkconfig.h"
 
@@ -17,14 +16,8 @@ extern "C" {
 #define PSRAM_SIZE_2MB                  (2 * 1024 * 1024)
 #define PSRAM_SIZE_4MB                  (4 * 1024 * 1024)
 #define PSRAM_SIZE_8MB                  (8 * 1024 * 1024)
-
-typedef enum {
-    PSRAM_CACHE_S80M = 1,
-    PSRAM_CACHE_S40M,
-    PSRAM_CACHE_S26M,
-    PSRAM_CACHE_S20M,
-    PSRAM_CACHE_MAX,
-} psram_cache_mode_t;
+#define PSRAM_SIZE_16MB                 (16 * 1024 * 1024)
+#define PSRAM_SIZE_32MB                 (32 * 1024 * 1024)
 
 
 /*
@@ -45,41 +38,28 @@ typedef enum {
  *
  * @param[out] out_size_bytes    physical psram size in bytes.
  */
-esp_err_t psram_get_physical_size(uint32_t *out_size_bytes);
+esp_err_t esp_psram_impl_get_physical_size(uint32_t *out_size_bytes);
 
 /**
  * @brief To get the available physical psram size in bytes.
  *
- * @note On ESP32S2, all of the PSRAM physical region are available
- *
  * @param[out] out_size_bytes    availabe physical psram size in bytes.
  */
-esp_err_t psram_get_available_size(uint32_t *out_size_bytes);
+esp_err_t esp_psram_impl_get_available_size(uint32_t *out_size_bytes);
 
 /**
- * @brief psram cache enable function
- *
- * Esp-idf uses this to initialize cache for psram, mapping it into the main memory
- * address space.
+ * @brief Enable psram and configure it to a ready state
  *
- * @param mode       SPI mode to access psram in
  * @param vaddrmode  Mode the psram cache works in.
- * @return ESP_OK on success, ESP_ERR_INVALID_STATE when VSPI peripheral is needed but cannot be claimed.
+ * @return
+ *        - ESP_OK:                On success,
+ *        - ESP_ERR_INVALID_STATE: On esp32, when VSPI peripheral is needed but cannot be claimed.
  */
-esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
-
-typedef enum {
-    SPIRAM_WRAP_MODE_16B,
-    SPIRAM_WRAP_MODE_32B,
-    SPIRAM_WRAP_MODE_64B,
-    SPIRAM_WRAP_MODE_DISABLE
-} spiram_wrap_mode_t;
-
-esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode);
+esp_err_t esp_psram_impl_enable(psram_vaddr_mode_t vaddrmode);
 
 /**
  * @brief get psram CS IO
  *
  * @return psram CS IO
  */
-uint8_t psram_get_cs_io(void);
+uint8_t esp_psram_impl_get_cs_io(void);

+ 0 - 0
components/esp_hw_support/include/esp_himem.h → components/esp_psram/include/esp32/himem.h


+ 84 - 0
components/esp_psram/include/esp_private/esp_psram_extram.h

@@ -0,0 +1,84 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Get the psram mapped vaddr range
+ *
+ * @param[out] out_vstart PSRAM virtual address start
+ * @param[out] out_vend   PSRAM virtual address end
+ *
+ * @return
+ *        - ESP_OK                  On success
+ *        - ESP_ERR_INVALID_STATE   PSRAM is not initialized successfully
+ */
+esp_err_t esp_psram_extram_get_mapped_range(intptr_t *out_vstart, intptr_t *out_vend);
+
+/**
+ * @brief Get the psram alloced vaddr range
+ *
+ * @param[out] out_vstart PSRAM virtual address start
+ * @param[out] out_vend   PSRAM virtual address end
+ *
+ * @return
+ *        - ESP_OK                  On success
+ *        - ESP_ERR_INVALID_STATE   PSRAM is not initialized successfully
+ */
+esp_err_t esp_psram_extram_get_alloced_range(intptr_t *out_vstart, intptr_t *out_vend);
+
+/**
+ * @brief Add the initialized PSRAM to the heap allocator.
+ *
+ * @return
+ *        - ESP_OK: On success
+ *        Other error type, see `heap_caps_add_region`.
+ */
+esp_err_t esp_psram_extram_add_to_heap_allocator(void);
+
+/**
+ * @brief Reserve a pool of internal memory for specific DMA/internal allocations
+ *
+ * @param size Size of reserved pool in bytes
+ *
+ * @return
+ *          - ESP_OK:         On success
+ *          - ESP_ERR_NO_MEM: When no memory available for pool
+ */
+esp_err_t esp_psram_extram_reserve_dma_pool(size_t size);
+
+/**
+ * @brief Memory test for PSRAM. Should be called after PSRAM is initialized and
+ * (in case of a dual-core system) the app CPU is online. This test overwrites the
+ * memory with crap, so do not call after e.g. the heap allocator has stored important
+ * stuff in PSRAM.
+ *
+ * @return true on success, false on failed memory test
+ */
+bool esp_psram_extram_test(void);
+
+#if CONFIG_IDF_TARGET_ESP32
+/**
+ * @brief Force a writeback of the data in the PSRAM cache. This is to be called whenever
+ * cache is disabled, because disabling cache on the ESP32 discards the data in the PSRAM
+ * cache.
+ *
+ * This is meant for use from within the SPI flash code.
+ */
+void esp_psram_extram_writeback_cache(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif

+ 31 - 0
components/esp_psram/include/esp_private/esp_psram_io.h

@@ -0,0 +1,31 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief get psram CS IO
+ *
+ * This interface should be called after PSRAM is enabled, otherwise it will
+ * return an invalid value -1/0xff.
+ *
+ * @return psram CS IO or -1/0xff if psram not enabled
+ */
+uint8_t esp_psram_io_get_cs_io(void);
+
+
+#ifdef __cplusplus
+}
+#endif

+ 140 - 0
components/esp_psram/include/esp_private/mmu.h

@@ -0,0 +1,140 @@
+/*
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * This file will be redesigned into MMU driver, to maintain all the external
+ * memory contexts including:
+ * - Flash
+ * - PSRAM
+ * - DDR
+ *
+ * Now only MMU-PSRAM related private APIs
+ */
+
+#pragma once
+
+#include <sys/param.h>
+#include "esp_err.h"
+#include "sdkconfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if CONFIG_IDF_TARGET_ESP32
+#define MMU_PAGE_SIZE                   0x8000
+#else
+#define MMU_PAGE_SIZE                   0x10000
+#define MMU_PAGE_TO_BYTES(page_id)      ((page_id) * MMU_PAGE_SIZE)
+#define BYTES_TO_MMU_PAGE(bytes)        ((bytes) / MMU_PAGE_SIZE)
+#endif
+
+/**
+ * @brief Get the vaddr start for PSRAM
+ *
+ * @return PSRAM vaddr start address
+ */
+intptr_t mmu_get_psram_vaddr_start(void);
+
+/**
+ * @brief Get the vaddr end for PSRAM
+ *
+ * @return PSRAM vaddr end address
+ */
+intptr_t mmu_get_psram_vaddr_end(void);
+
+
+#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+/**
+ * @brief Copy Flash texts to PSRAM
+ *
+ * @param[in]  start_page    PSRAM physical start page
+ * @param[in]  psram_size    PSRAM available size
+ * @param[out] out_page      Used pages
+ */
+esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
+
+/**
+ * @brief Init other file requested MMU variables
+ *
+ * - These logics are abstracted from the PSRAM driver
+ * - These functions are only required by `flash_mmap.c` for converting paddr to vaddr, and vice versa
+ * - The `flash_mmpa.c` will be rewritten into MMU driver
+ *
+ * Therefore, keep the APIs here for now
+ */
+void instruction_flash_page_info_init(uint32_t psram_start_physical_page);
+
+/**
+ * @brief Get the start page number of the instruction in SPI flash
+ *
+ * @return start page number
+ */
+uint32_t instruction_flash_start_page_get(void);
+
+/**
+ * @brief Get the end page number of the instruction in SPI flash
+ *
+ * @return end page number
+ */
+uint32_t instruction_flash_end_page_get(void);
+
+/**
+ * @brief Get the offset of instruction from SPI flash to SPI RAM
+ *
+ * @return instruction offset
+ */
+int instruction_flash2spiram_offset(void);
+#endif  // #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+
+
+#if CONFIG_SPIRAM_RODATA
+/**
+ * @brief Copy Flash rodata to PSRAM
+ *
+ * @param[in]  start_page    PSRAM physical start page
+ * @param[in]  psram_size    PSRAM available size
+ * @param[out] out_page      Used pages
+ */
+esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page);
+
+/**
+ * @brief Init other file requested MMU variables
+ *
+ * - These logics are abstracted from the PSRAM driver
+ * - These functions are only required by `flash_mmap.c` for converting paddr to vaddr, and vice versa
+ * - The `flash_mmpa.c` will be rewritten into MMU driver
+ *
+ * Therefore, keep the APIs here for now
+ */
+void rodata_flash_page_info_init(uint32_t psram_start_physical_page);
+
+/**
+ * @brief Get the start page number of the rodata in SPI flash
+ *
+ * @return start page number
+ */
+uint32_t rodata_flash_start_page_get(void);
+
+/**
+ * @brief Get the end page number of the rodata in SPI flash
+ *
+ * @return end page number
+ */
+uint32_t rodata_flash_end_page_get(void);
+
+/**
+ * @brief Get the offset number of rodata from SPI flash to SPI RAM
+ *
+ * @return rodata offset
+ */
+int rodata_flash2spiram_offset(void);
+#endif  // #if CONFIG_SPIRAM_RODATA
+
+
+#ifdef __cplusplus
+}
+#endif

+ 47 - 0
components/esp_psram/include/esp_psram.h

@@ -0,0 +1,47 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize PSRAM interface/hardware.
+ *
+ * @return
+ *        - ESP_OK:                On success
+ *        - ESP_FAIL:              PSRAM isn't initialized successfully, potential reason would be: wrong VDDSDIO, invalid chip ID, etc.
+ *        - ESP_ERR_INVALID_STATE: PSRAM is initialized already
+ */
+esp_err_t esp_psram_init(void);
+
+/**
+ * @brief If PSRAM has been initialized
+ *
+ * @return
+ *          - true:  PSRAM has been initialized successfully
+ *          - false: PSRAM hasn't been initialized or initialized failed
+ */
+bool esp_psram_is_initialized(void);
+
+/**
+ * @brief Get the available size of the attached PSRAM chip
+ *
+ * @return Size in bytes, or 0 if PSRAM isn't successfully initialized
+ */
+size_t esp_psram_get_size(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 17 - 0
components/esp_psram/linker.lf

@@ -0,0 +1,17 @@
+[mapping:esp_psram]
+archive: libesp_psram.a
+entries:
+
+    if SPIRAM = y:
+        mmu (noflash)
+
+        if SPIRAM_MODE_QUAD = y:
+            if IDF_TARGET_ESP32S3 = y:
+                esp_psram_impl_quad (noflash)
+
+        if IDF_TARGET_ESP32S3 = y:
+            if SPIRAM_MODE_OCT = y:
+                esp_psram_impl_octal (noflash)
+
+        if IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y:
+            mmu_psram (noflash)

+ 171 - 0
components/esp_psram/mmu.c

@@ -0,0 +1,171 @@
+/*
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * This file will be redesigned into MMU driver, to maintain all the external
+ * memory contexts including:
+ * - Flash
+ * - PSRAM
+ * - DDR
+ *
+ * Now only MMU-PSRAM related private APIs
+ */
+
+#include <stdint.h>
+#include <sys/param.h>
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "soc/ext_mem_defs.h"
+#include "esp_private/mmu.h"
+
+#if CONFIG_IDF_TARGET_ESP32S2
+#include "soc/extmem_reg.h"
+#include "esp32s2/rom/cache.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "soc/extmem_reg.h"
+#include "esp32s3/rom/cache.h"
+#endif
+
+
+#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
+__attribute__((unused)) static const char *TAG = "mmu";
+extern int _instruction_reserved_start;
+extern int _instruction_reserved_end;
+extern int _rodata_reserved_start;
+extern int _rodata_reserved_end;
+
+
+intptr_t mmu_get_psram_vaddr_start(void)
+{
+#if CONFIG_IDF_TARGET_ESP32S3
+
+    intptr_t rodata_end_aligned = ALIGN_UP_BY((intptr_t)&_rodata_reserved_end, MMU_PAGE_SIZE);
+    ESP_EARLY_LOGV(TAG, "rodata_end_aligned is 0x%x bytes", rodata_end_aligned);
+    return rodata_end_aligned;
+
+#elif CONFIG_IDF_TARGET_ESP32S2
+    return DPORT_CACHE_ADDRESS_LOW;
+#else   //CONFIG_IDF_TARGET_ESP32
+    return DRAM1_CACHE_ADDRESS_LOW;
+#endif
+}
+
+intptr_t mmu_get_psram_vaddr_end(void)
+{
+#if CONFIG_IDF_TARGET_ESP32S3
+    return DRAM0_CACHE_ADDRESS_HIGH;
+#elif CONFIG_IDF_TARGET_ESP32S2
+    return DRAM0_CACHE_ADDRESS_HIGH;
+#else   //CONFIG_IDF_TARGET_ESP32
+    return DRAM1_CACHE_ADDRESS_HIGH;
+#endif
+}
+
+//------------------------------------Copy Flash .text to PSRAM-------------------------------------//
+#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+static uint32_t instruction_in_spiram;
+static uint32_t instr_start_page;
+static uint32_t instr_end_page;
+static int instr_flash2spiram_offs;
+
+/**
+ * - These logics are abstracted from the PSRAM driver
+ * - These functions are only required by `flash_mmap.c` for converting paddr to vaddr, and vice versa
+ * - The `flash_mmpa.c` will be rewritten into MMU driver
+ *
+ * Therefore, keep the APIs here for now
+ */
+void instruction_flash_page_info_init(uint32_t psram_start_physical_page)
+{
+#if CONFIG_IDF_TARGET_ESP32S2
+    uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - (uint32_t)&_instruction_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
+    uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
+    instr_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START))[instr_mmu_offset];
+#elif CONFIG_IDF_TARGET_ESP32S3
+    uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
+    instr_start_page = *((volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START));
+#endif
+    instr_start_page &= MMU_VALID_VAL_MASK;
+    instr_end_page = instr_start_page + instr_page_cnt - 1;
+    instr_flash2spiram_offs = instr_start_page - psram_start_physical_page;
+    instruction_in_spiram = 1;
+    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);
+}
+
+uint32_t esp_spiram_instruction_access_enabled(void)
+{
+    return instruction_in_spiram;
+}
+
+int instruction_flash2spiram_offset(void)
+{
+    return instr_flash2spiram_offs;
+}
+
+uint32_t instruction_flash_start_page_get(void)
+{
+    return instr_start_page;
+}
+
+uint32_t instruction_flash_end_page_get(void)
+{
+    return instr_end_page;
+}
+#endif  //CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+
+
+#if CONFIG_SPIRAM_RODATA
+//------------------------------------Copy Flash .rodata to PSRAM-------------------------------------//
+static uint32_t rodata_in_spiram;
+static int rodata_flash2spiram_offs;
+static uint32_t rodata_start_page;
+static uint32_t rodata_end_page;
+
+/**
+ * - These logics are abstracted from the PSRAM driver
+ * - These functions are only required by `flash_mmap.c` for converting paddr to vaddr, and vice versa
+ * - The `flash_mmpa.c` will be rewritten into MMU driver
+ *
+ * Therefore, keep the APIs here for now
+ */
+void rodata_flash_page_info_init(uint32_t psram_start_physical_page)
+{
+#if CONFIG_IDF_TARGET_ESP32S2
+    uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - (uint32_t)&_rodata_reserved_start + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
+    uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & MMU_VADDR_MASK) / MMU_PAGE_SIZE;
+    rodata_start_page = ((volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START))[rodata_mmu_offset];
+#elif CONFIG_IDF_TARGET_ESP32S3
+    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;
+    rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
+#endif
+    rodata_start_page &= MMU_VALID_VAL_MASK;
+    rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
+    rodata_flash2spiram_offs = rodata_start_page - psram_start_physical_page;
+    rodata_in_spiram = 1;
+    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);
+}
+
+uint32_t esp_spiram_rodata_access_enabled(void)
+{
+    return rodata_in_spiram;
+}
+
+int rodata_flash2spiram_offset(void)
+{
+    return rodata_flash2spiram_offs;
+}
+
+uint32_t rodata_flash_start_page_get(void)
+{
+    return rodata_start_page;
+}
+
+uint32_t rodata_flash_end_page_get(void)
+{
+    return rodata_end_page;
+}
+#endif  //#if CONFIG_SPIRAM_RODATA

+ 146 - 0
components/esp_psram/mmu_psram.c

@@ -0,0 +1,146 @@
+/*
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * This file will be redesigned into MMU driver, to maintain all the external
+ * memory contexts including:
+ * - Flash
+ * - PSRAM
+ * - DDR
+ *
+ * Now only MMU-PSRAM related private APIs
+ */
+
+#include <sys/param.h>
+#include "sdkconfig.h"
+#include "esp_log.h"
+#include "esp_attr.h"
+#include "soc/ext_mem_defs.h"
+#include "hal/cache_types.h"
+#include "hal/cache_ll.h"
+#include "esp_private/mmu.h"
+
+#if CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rom/cache.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/cache.h"
+#endif
+
+
+#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
+//page_size - 1, where page_size on s2 and s3 is always 0x10000. To be refactored by MMU driver
+#define INVALID_PHY_PAGE 0xffff
+const static char *TAG = "mmu_psram";
+//TODO IDF-4387
+static uint32_t page0_mapped = 0;
+static uint32_t page0_page = INVALID_PHY_PAGE;
+#endif  //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
+
+
+#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+esp_err_t mmu_config_psram_text_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page)
+{
+    uint32_t page_id = start_page;
+
+    /**
+     * TODO IDF-4387
+     * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
+     * FOR NOW, leave these logics just as it used to be.
+     *
+     * The rom API will be redesigned into a MMU driver layer function
+     */
+    uint32_t flash_pages = 0;
+#if CONFIG_IDF_TARGET_ESP32S2
+    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS0, &page0_mapped);
+    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS1, &page0_mapped);
+#elif CONFIG_IDF_TARGET_ESP32S3
+    flash_pages += Cache_Count_Flash_Pages(CACHE_IBUS, &page0_mapped);
+#endif
+    if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
+        ESP_EARLY_LOGE(TAG, "PSRAM space not enough for the Flash instructions, need %d B, from %d B to %d B",
+                       MMU_PAGE_TO_BYTES(flash_pages), MMU_PAGE_TO_BYTES(start_page), MMU_PAGE_TO_BYTES(flash_pages + page_id));
+        return ESP_FAIL;
+    }
+
+    //Enable the most high bus, which is used for copying FLASH .text to PSRAM
+    cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, SOC_EXTRAM_DATA_HIGH, 0);
+    cache_ll_l1_enable_bus(0, bus_mask);
+#if !CONFIG_FREERTOS_UNICORE
+    bus_mask = cache_ll_l1_get_bus(1, SOC_EXTRAM_DATA_HIGH, 0);
+    cache_ll_l1_enable_bus(1, bus_mask);
+#endif
+
+    instruction_flash_page_info_init(page_id);
+
+#if CONFIG_IDF_TARGET_ESP32S2
+    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, page_id, &page0_page);
+    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, page_id, &page0_page);
+#elif CONFIG_IDF_TARGET_ESP32S3
+    page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page);
+#endif
+    ESP_EARLY_LOGV(TAG, "after copy instruction, page_id is %d", page_id);
+    ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
+
+    *out_page = page_id - start_page;
+
+    return ESP_OK;
+}
+#endif  //#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+
+
+#if CONFIG_SPIRAM_RODATA
+esp_err_t mmu_config_psram_rodata_segment(uint32_t start_page, uint32_t psram_size, uint32_t *out_page)
+{
+    uint32_t page_id = start_page;
+
+    /**
+     * TODO IDF-4387
+     * `Cache_Count_Flash_Pages` seems give wrong results. Need to confirm this.
+     * FOR NOW, leave these logics just as it used to be.
+     *
+     * The rom API will be redesigned into a MMU driver layer function
+     */
+    uint32_t flash_pages = 0;
+#if CONFIG_IDF_TARGET_ESP32S2
+    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_IBUS2, &page0_mapped);
+    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS0, &page0_mapped);
+    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS1, &page0_mapped);
+    flash_pages += Cache_Count_Flash_Pages(PRO_CACHE_DBUS2, &page0_mapped);
+#elif CONFIG_IDF_TARGET_ESP32S3
+    flash_pages += Cache_Count_Flash_Pages(CACHE_DBUS, &page0_mapped);
+#endif
+    if ((flash_pages + page_id) > BYTES_TO_MMU_PAGE(psram_size)) {
+        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));
+        return ESP_FAIL;
+    }
+
+    //Enable the most high bus, which is used for copying FLASH .text to PSRAM
+    cache_bus_mask_t bus_mask = cache_ll_l1_get_bus(0, SOC_EXTRAM_DATA_HIGH, 0);
+    cache_ll_l1_enable_bus(0, bus_mask);
+#if !CONFIG_FREERTOS_UNICORE
+    bus_mask = cache_ll_l1_get_bus(1, SOC_EXTRAM_DATA_HIGH, 0);
+    cache_ll_l1_enable_bus(1, bus_mask);
+#endif
+
+    rodata_flash_page_info_init(page_id);
+
+#if CONFIG_IDF_TARGET_ESP32S2
+    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, page_id, &page0_page);
+    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, page_id, &page0_page);
+    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, page_id, &page0_page);
+    page_id = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, page_id, &page0_page);
+#elif CONFIG_IDF_TARGET_ESP32S3
+    page_id = Cache_Flash_To_SPIRAM_Copy(CACHE_DBUS, DRAM0_CACHE_ADDRESS_LOW, page_id, &page0_page);
+#endif
+
+    ESP_EARLY_LOGV(TAG, "after copy rodata, page_id is %d", page_id);
+    ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
+
+    *out_page = page_id - start_page;
+
+    return ESP_OK;
+}
+#endif  //#if CONFIG_SPIRAM_RODATA

+ 0 - 0
components/esp_hw_support/project_include.cmake → components/esp_psram/project_include.cmake


+ 5 - 0
components/esp_psram/test_apps/psram/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(psram_test)

+ 4 - 0
components/esp_psram/test_apps/psram/README.md

@@ -0,0 +1,4 @@
+| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- |
+
+This test app is used to test PSRAM

+ 13 - 0
components/esp_psram/test_apps/psram/main/CMakeLists.txt

@@ -0,0 +1,13 @@
+idf_build_get_property(target IDF_TARGET)
+
+set(srcs "test_app_main.c"
+         "test_psram.c")
+
+if(${target} STREQUAL "esp32")
+    list(APPEND srcs "test_himem.c")
+endif()
+
+# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
+# the component can be registered as WHOLE_ARCHIVE
+idf_component_register(SRCS ${srcs}
+                       WHOLE_ARCHIVE)

+ 40 - 0
components/esp_psram/test_apps/psram/main/test_app_main.c

@@ -0,0 +1,40 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+#define TEST_MEMORY_LEAK_THRESHOLD (-600)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    unity_run_menu();
+}

+ 1 - 1
components/esp_hw_support/test/test_himem.c → components/esp_psram/test_apps/psram/main/test_himem.c

@@ -14,7 +14,7 @@
 #include "sdkconfig.h"
 
 #if CONFIG_IDF_TARGET_ESP32
-#include "esp_himem.h"
+#include "esp32/himem.h"
 
 #if CONFIG_SPIRAM_BANKSWITCH_ENABLE
 

+ 55 - 21
components/esp_hw_support/test/test_psram.c → components/esp_psram/test_apps/psram/main/test_psram.c

@@ -11,14 +11,13 @@
 #include "esp_attr.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "test_utils.h"
 #include "unity.h"
 #include "esp_heap_caps.h"
-#include "esp_private/spiram_private.h"
-#if CONFIG_SPIRAM
-#include "spiram.h"
+#include "esp_private/esp_psram_io.h"
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
 
-const static char *TAG = "PSRAM";
+__attribute__((unused)) const static char *TAG = "PSRAM";
 
 
 #if CONFIG_SPIRAM_MODE_OCT
@@ -31,7 +30,7 @@ static bool s_check_valid_psram_alloced_range(const void *p)
 {
     intptr_t vaddr_start = 0;
     intptr_t vaddr_end = 0;
-    esp_spiram_get_alloced_range(&vaddr_start, &vaddr_end);
+    esp_psram_extram_get_alloced_range(&vaddr_start, &vaddr_end);
     return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end;
 }
 
@@ -58,8 +57,9 @@ TEST_CASE("test psram heap allocable","[psram]")
 
 
 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
-#include "esp_timer.h"
-#include "esp32s3/rom/spi_flash.h"
+#include "esp_partition.h"
+#include "driver/gptimer.h"
+#include "esp_rom_spiflash.h"
 
 #define SECTOR_LEN              4096
 #define TEST_NUM                10
@@ -68,29 +68,61 @@ TEST_CASE("test psram heap allocable","[psram]")
 static uint32_t s_timer_cb_exe_times;
 static const uint8_t s_test_buf[TEST_NUM] = TEST_BUF;
 
-static void NOINLINE_ATTR s_test_printf(void *arg)
+static const esp_partition_t *s_get_partition(void)
+{
+    //Find the "storage1" partition defined in `partitions.csv`
+    const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1");
+    if (!result) {
+        ESP_LOGE(TAG, "Can't find the partition, please define it correctly in `partitions.csv`");
+        abort();
+    }
+    return result;
+}
+
+static bool NOINLINE_ATTR s_test_rodata(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
 {
     s_timer_cb_exe_times ++;
     uint8_t cmp_buf[TEST_NUM] = TEST_BUF;
     TEST_ASSERT(memcmp(cmp_buf, s_test_buf, TEST_NUM) == 0);
+
+    return false;
 }
 
 TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram", "[psram]")
 {
-    //Create flash partition for test
-    const esp_partition_t *part = get_test_data_partition();
-    size_t start = part->address;
-    ESP_LOGI(TAG, "test data partition: 0x%x", start);
+    //Get the partition used for SPI1 erase operation
+    const esp_partition_t *part = s_get_partition();
+    ESP_LOGI(TAG, "found partition '%s' at offset 0x%x with size 0x%x", part->label, part->address, part->size);
+    //Erase whole region
+    TEST_ESP_OK(esp_flash_erase_region(part->flash_chip, part->address, part->size));
+
+    gptimer_handle_t gptimer = NULL;
+    gptimer_config_t timer_config = {
+        .resolution_hz = 1 * 1000 * 1000,
+        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
+        .direction = GPTIMER_COUNT_UP,
+    };
+    TEST_ESP_OK(gptimer_new_timer(&timer_config, &gptimer));
 
-    esp_timer_handle_t timer;
-    esp_timer_create_args_t timer_args = {
-        .callback = &s_test_printf,
+    gptimer_alarm_config_t alarm_config = {
+        .reload_count = 0,
+        .alarm_count = 10, // 10us
+        .flags.auto_reload_on_alarm = true,
     };
-    TEST_ESP_OK(esp_timer_create(&timer_args, &timer));
+    TEST_ESP_OK(gptimer_set_alarm_action(gptimer, &alarm_config));
+
+    gptimer_event_callbacks_t cbs = {
+        .on_alarm = s_test_rodata,
+    };
+    TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
 
     esp_rom_spiflash_result_t ret;
+    size_t start = part->address;
+    ESP_LOGI(TAG, "test data partition: 0x%x", start);
     uint32_t sector_num = start / SECTOR_LEN;
-    TEST_ESP_OK(esp_timer_start_periodic(timer, 1 * 10));
+
+    TEST_ESP_OK(gptimer_enable(gptimer));
+    TEST_ESP_OK(gptimer_start(gptimer));
 
     ret = esp_rom_spiflash_erase_sector(sector_num);
     if (ret != ESP_ROM_SPIFLASH_RESULT_OK) {
@@ -98,10 +130,12 @@ TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram"
         TEST_ASSERT(false);
     }
 
-    TEST_ESP_OK(esp_timer_stop(timer));
+    TEST_ESP_OK(gptimer_stop(gptimer));
     TEST_ASSERT(s_timer_cb_exe_times > 0);
     printf("timer callback runs %d times\n", s_timer_cb_exe_times);
+
+    ESP_LOGI(TAG, "Finish");
+    TEST_ESP_OK(gptimer_disable(gptimer));
+    TEST_ESP_OK(gptimer_del_timer(gptimer));
 }
 #endif  //CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA
-
-#endif  //#if CONFIG_SPIRAM

+ 6 - 0
components/esp_psram/test_apps/psram/partitions.csv

@@ -0,0 +1,6 @@
+# Name,   Type, SubType, Offset,  Size, Flags
+# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
+nvs,        data, nvs,      0x9000,  0x6000,
+phy_init,   data, phy,      0xf000,  0x1000,
+factory,    app,  factory,  0x10000, 1M,
+storage1,   data, fat,             , 512K,

+ 68 - 0
components/esp_psram/test_apps/psram/pytest_psram.py

@@ -0,0 +1,68 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32
+@pytest.mark.generic
+@pytest.mark.parametrize(
+    'config',
+    [
+        'esp32_release',
+    ],
+    indirect=True,
+)
+def test_psram_esp32(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()
+
+
+@pytest.mark.esp32s2
+@pytest.mark.generic
+@pytest.mark.parametrize(
+    'config',
+    [
+        'esp32s2_release',
+        'esp32s2_advanced',
+    ],
+    indirect=True,
+)
+def test_psram_esp32s2(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()
+
+
+@pytest.mark.esp32s3
+@pytest.mark.quad_psram
+@pytest.mark.parametrize(
+    'config',
+    [
+        'esp32s3_quad_release',
+        'esp32s3_quad_advanced',
+    ],
+    indirect=True,
+)
+def test_psram_esp32s3(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()
+
+
+@pytest.mark.esp32s3
+@pytest.mark.octal_psram
+@pytest.mark.parametrize(
+    'config',
+    [
+        'esp32s3_octal_release',
+        'esp32s3_octal_advanced',
+    ],
+    indirect=True,
+)
+def test_psram_esp32s3_octal(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()

+ 9 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32_release

@@ -0,0 +1,9 @@
+CONFIG_IDF_TARGET="esp32"
+
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
+
+CONFIG_ESP32_SPIRAM_SUPPORT=y
+CONFIG_ESP_INT_WDT_TIMEOUT_MS=800
+CONFIG_SPIRAM_OCCUPY_NO_HOST=y

+ 9 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s2_advanced

@@ -0,0 +1,9 @@
+CONFIG_IDF_TARGET="esp32s2"
+
+CONFIG_ESP32S2_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
+CONFIG_SPIRAM_RODATA=y
+
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
+CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

+ 7 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s2_release

@@ -0,0 +1,7 @@
+CONFIG_IDF_TARGET="esp32s2"
+
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
+
+CONFIG_ESP32S2_SPIRAM_SUPPORT=y

+ 10 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_octal_advanced

@@ -0,0 +1,10 @@
+CONFIG_IDF_TARGET="esp32s3"
+
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
+CONFIG_SPIRAM_RODATA=y
+
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
+CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

+ 8 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_octal_release

@@ -0,0 +1,8 @@
+CONFIG_IDF_TARGET="esp32s3"
+
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
+
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y

+ 10 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_quad_advanced

@@ -0,0 +1,10 @@
+CONFIG_IDF_TARGET="esp32s3"
+
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_QUAD=y
+CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
+CONFIG_SPIRAM_RODATA=y
+
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
+CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

+ 8 - 0
components/esp_psram/test_apps/psram/sdkconfig.ci.esp32s3_quad_release

@@ -0,0 +1,8 @@
+CONFIG_IDF_TARGET="esp32s3"
+
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
+
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_QUAD=y

+ 2 - 0
components/esp_psram/test_apps/psram/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n

+ 6 - 0
components/esp_system/CMakeLists.txt

@@ -102,3 +102,9 @@ endif()
 if(CONFIG_SW_COEXIST_ENABLE OR CONFIG_EXTERNAL_COEX_ENABLE)
     idf_component_optional_requires(PRIVATE esp_wifi)
 endif()
+
+if(NOT BOOTLOADER_BUILD)
+    if(CONFIG_SPIRAM)
+        idf_component_optional_requires(PRIVATE esp_psram)
+    endif()
+endif()

+ 5 - 14
components/esp_system/include/esp_private/startup_internal.h

@@ -1,16 +1,8 @@
-// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #pragma once
 
@@ -25,7 +17,6 @@
 extern "C" {
 #endif
 
-extern bool g_spiram_ok; // [refactor-todo] better way to communicate this from port layer to common startup code
 
 // Port layer defines the entry point. It then transfer control to a `sys_startup_fn_t`, stored in this
 // array, one per core.

+ 11 - 38
components/esp_system/port/cpu_start.c

@@ -27,16 +27,13 @@
 #include "soc/dport_reg.h"
 #include "esp32/rtc.h"
 #include "esp32/rom/cache.h"
-#include "esp32/spiram.h"
 #elif CONFIG_IDF_TARGET_ESP32S2
 #include "esp32s2/rtc.h"
 #include "esp32s2/rom/cache.h"
-#include "esp32s2/spiram.h"
 #include "esp32s2/memprot.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rtc.h"
 #include "esp32s3/rom/cache.h"
-#include "esp32s3/spiram.h"
 #include "esp_memprot.h"
 #include "soc/assist_debug_reg.h"
 #include "soc/system_reg.h"
@@ -56,6 +53,11 @@
 #include "esp32c2/memprot.h"
 #endif
 
+#if CONFIG_SPIRAM
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
+#endif
+
 #include "esp_private/spi_flash_os.h"
 #include "bootloader_flash_config.h"
 #include "bootloader_flash.h"
@@ -126,9 +128,6 @@ static volatile bool s_cpu_inited[SOC_CPU_CORES_NUM] = { false };
 static volatile bool s_resume_cores;
 #endif
 
-// If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
-bool g_spiram_ok = true;
-
 static void core_intr_matrix_clear(void)
 {
     uint32_t core_id = cpu_hal_get_core_id();
@@ -388,7 +387,7 @@ void IRAM_ATTR call_start_cpu0(void)
 
     bootloader_init_mem();
 #if CONFIG_SPIRAM_BOOT_INIT
-    if (esp_spiram_init() != ESP_OK) {
+    if (esp_psram_init() != ESP_OK) {
 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
         ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment");
         abort();
@@ -396,18 +395,11 @@ void IRAM_ATTR call_start_cpu0(void)
 
 #if CONFIG_SPIRAM_IGNORE_NOTFOUND
         ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
-        g_spiram_ok = false;
 #else
         ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
         abort();
 #endif
     }
-    //TODO: IDF-4382
-#if CONFIG_IDF_TARGET_ESP32
-    if (g_spiram_ok) {
-        esp_spiram_init_cache();
-    }
-#endif  //#if CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382
 #endif
 
 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
@@ -436,44 +428,25 @@ void IRAM_ATTR call_start_cpu0(void)
 #endif // SOC_CPU_CORES_NUM > 1
 
 #if CONFIG_SPIRAM_MEMTEST
-    //TODO: IDF-4382
-#if CONFIG_IDF_TARGET_ESP32
-    if (g_spiram_ok) {
-        bool ext_ram_ok = esp_spiram_test();
+    if (esp_psram_is_initialized()) {
+        bool ext_ram_ok = esp_psram_extram_test();
         if (!ext_ram_ok) {
             ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
             abort();
         }
     }
-#endif  //CONFIG_IDF_TARGET_ESP32, //TODO: IDF-4382
 #endif  //CONFIG_SPIRAM_MEMTEST
 
-    //TODO: IDF-4382
+//TODO: IDF-5023, replace with MMU driver
 #if CONFIG_IDF_TARGET_ESP32S3
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-    extern void instruction_flash_page_info_init(void);
-    instruction_flash_page_info_init();
-#endif
-#if CONFIG_SPIRAM_RODATA
-    extern void rodata_flash_page_info_init(void);
-    rodata_flash_page_info_init();
-#endif
-
-#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
-    extern void esp_spiram_enable_instruction_access(void);
-    esp_spiram_enable_instruction_access();
-#endif
-#if CONFIG_SPIRAM_RODATA
-    extern void esp_spiram_enable_rodata_access(void);
-    esp_spiram_enable_rodata_access();
-#endif
-
     int s_instr_flash2spiram_off = 0;
     int s_rodata_flash2spiram_off = 0;
 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+    extern int instruction_flash2spiram_offset(void);
     s_instr_flash2spiram_off = instruction_flash2spiram_offset();
 #endif
 #if CONFIG_SPIRAM_RODATA
+    extern int rodata_flash2spiram_offset(void);
     s_rodata_flash2spiram_off = rodata_flash2spiram_offset();
 #endif
 

+ 6 - 10
components/esp_system/startup.c

@@ -71,13 +71,9 @@
 
 #include "esp_rom_sys.h"
 
-// [refactor-todo] make this file completely target-independent
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
+#if CONFIG_SPIRAM
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
 #endif
 /***********************************************/
 
@@ -251,18 +247,18 @@ static void do_core_init(void)
     esp_timer_early_init();
     esp_newlib_init();
 
-    if (g_spiram_ok) {
 #if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
-        esp_err_t r=esp_spiram_add_to_heapalloc();
+    if (esp_psram_is_initialized()) {
+        esp_err_t r=esp_psram_extram_add_to_heap_allocator();
         if (r != ESP_OK) {
             ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
             abort();
         }
 #if CONFIG_SPIRAM_USE_MALLOC
         heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
-#endif
 #endif
     }
+#endif
 
 #if CONFIG_ESP_BROWNOUT_DET
     // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) ->

+ 4 - 0
components/freertos/CMakeLists.txt

@@ -183,3 +183,7 @@ if(CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER)
     # Introduce a port wrapper function to avoid including esp_timer.h into the public header
     idf_component_optional_requires(PUBLIC esp_timer)
 endif()
+
+if(CONFIG_SPIRAM)
+    idf_component_optional_requires(PRIVATE esp_psram)
+endif()

+ 7 - 4
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -17,7 +17,6 @@
 #include "xtensa/config/core.h"
 #include "xtensa/config/core-isa.h"
 #include "xtensa/xtruntime.h"
-#include "esp_private/startup_internal.h"   /* Required by g_spiram_ok. [refactor-todo] for g_spiram_ok */
 #include "esp_private/esp_int_wdt.h"
 #include "esp_heap_caps.h"
 #include "esp_system.h"
@@ -28,7 +27,11 @@
 #include "esp_task_wdt.h"
 #include "esp_heap_caps_init.h"
 #include "esp_freertos_hooks.h"
-#include "esp32/spiram.h"                   /* Required by esp_spiram_reserve_dma_pool() */
+#if CONFIG_SPIRAM
+/* Required by esp_psram_extram_reserve_dma_pool() */
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
+#endif
 #ifdef CONFIG_APPTRACE_ENABLE
 #include "esp_app_trace.h"
 #endif
@@ -180,8 +183,8 @@ static void main_task(void* args)
 
     // Now we have startup stack RAM available for heap, enable any DMA pool memory
 #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
-    if (g_spiram_ok) {
-        esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
+    if (esp_psram_is_initialized()) {
+        esp_err_t r = esp_psram_extram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
         if (r != ESP_OK) {
             ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
             abort();

+ 5 - 9
components/freertos/FreeRTOS-Kernel/portable/port_common.c

@@ -14,19 +14,15 @@
 #include "esp_task_wdt.h"
 #include "esp_task.h"
 #include "esp_private/crosscore_int.h"
-#include "esp_private/startup_internal.h"    /* Required by g_spiram_ok. [refactor-todo] for g_spiram_ok */
 #include "esp_log.h"
 #include "esp_memory_utils.h"
 #include "esp_freertos_hooks.h"
 #include "sdkconfig.h"
 #include "esp_freertos_hooks.h"
 
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
+#if CONFIG_SPIRAM
+#include "esp_psram.h"
+#include "esp_private/esp_psram_extram.h"
 #endif
 
 #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
@@ -105,8 +101,8 @@ static void main_task(void* args)
 
     // Now we have startup stack RAM available for heap, enable any DMA pool memory
 #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
-    if (g_spiram_ok) {
-        esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
+    if (esp_psram_is_initialized()) {
+        esp_err_t r = esp_psram_extram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
         if (r != ESP_OK) {
             ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
             abort();

+ 1 - 0
components/hal/esp32/include/hal/cache_ll.h

@@ -8,6 +8,7 @@
 
 #pragma once
 
+#include <stdbool.h>
 #include "soc/dport_reg.h"
 #include "soc/ext_mem_defs.h"
 #include "hal/cache_types.h"

+ 8 - 0
components/spi_flash/CMakeLists.txt

@@ -76,3 +76,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU")
     set_property(SOURCE ${cache_srcs} APPEND_STRING PROPERTY COMPILE_FLAGS
         " -fno-inline-small-functions -fno-inline-functions-called-once")
 endif()
+
+if(NOT BOOTLOADER_BUILD)
+    if(CONFIG_SPIRAM)
+        # [refactor-todo]: requires "esp_psram" for few MMU usages in `flash_mmap.c`
+        # will be replaced with MMU requirements
+        idf_component_optional_requires(PRIVATE esp_psram)
+    endif()
+endif()

+ 17 - 5
components/spi_flash/flash_mmap.c

@@ -24,14 +24,11 @@
 #if CONFIG_IDF_TARGET_ESP32
 #include "soc/dport_reg.h"
 #include "esp32/rom/cache.h"
-#include "esp32/spiram.h"
 #elif CONFIG_IDF_TARGET_ESP32S2
 #include "esp32s2/rom/cache.h"
-#include "esp_private/mmu_psram.h"
 #include "soc/extmem_reg.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/cache.h"
-#include "esp32s3/spiram.h"
 #include "soc/extmem_reg.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/cache.h"
@@ -41,6 +38,11 @@
 #include "esp32c2/rom/cache.h"
 #endif
 
+#if CONFIG_SPIRAM
+#include "esp_private/esp_psram_extram.h"
+#include "esp_private/mmu.h"
+#endif
+
 #ifndef NDEBUG
 // Enable built-in checks in queue.h in debug builds
 #define INVARIANTS
@@ -52,6 +54,16 @@
 #define PAGES_LIMIT ((SOC_MMU_IROM0_PAGES_END > SOC_MMU_DROM0_PAGES_END) ? SOC_MMU_IROM0_PAGES_END:SOC_MMU_DROM0_PAGES_END)
 #define INVALID_PHY_PAGE(page_size)                ((page_size) - 1)
 
+#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
+extern int _instruction_reserved_start;
+extern int _instruction_reserved_end;
+#endif
+
+#if CONFIG_SPIRAM_RODATA
+extern int _rodata_reserved_start;
+extern int _rodata_reserved_end;
+#endif
+
 #if !CONFIG_SPI_FLASH_ROM_IMPL
 
 typedef struct mmap_entry_{
@@ -248,7 +260,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
     if (need_flush) {
 #if CONFIG_IDF_TARGET_ESP32
 #if CONFIG_SPIRAM
-        esp_spiram_writeback_cache();
+        esp_psram_extram_writeback_cache();
 #endif // CONFIG_SPIRAM
         Cache_Flush(0);
 #if !CONFIG_FREERTOS_UNICORE
@@ -486,7 +498,7 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
         if (is_page_mapped_in_cache(page, &vaddr)) {
 #if CONFIG_IDF_TARGET_ESP32
 #if CONFIG_SPIRAM
-            esp_spiram_writeback_cache();
+            esp_psram_extram_writeback_cache();
 #endif
             Cache_Flush(0);
 #ifndef CONFIG_FREERTOS_UNICORE

+ 1 - 1
docs/doxygen/Doxyfile_esp32

@@ -12,7 +12,7 @@ INPUT += \
          $(PROJECT_PATH)/components/driver/include/driver/rmt_rx.h \
          $(PROJECT_PATH)/components/driver/include/driver/rmt_tx.h \
          $(PROJECT_PATH)/components/driver/include/driver/rmt_types.h \
-         $(PROJECT_PATH)/components/esp_hw_support/include/esp_himem.h \
+         $(PROJECT_PATH)/components/esp_psram/include/esp32/himem.h \
          $(PROJECT_PATH)/components/esp_system/include/esp_ipc.h \
          $(PROJECT_PATH)/components/esp_system/include/esp_ipc_isr.h \
          $(PROJECT_PATH)/components/hal/include/hal/i2s_types.h \

+ 1 - 1
docs/en/api-reference/system/himem.rst

@@ -30,4 +30,4 @@ An example doing a simple memory test of the high memory range is available in e
 API Reference
 -------------
 
-.. include-build-file:: inc/esp_himem.inc
+.. include-build-file:: inc/himem.inc

+ 2 - 5
docs/en/migration-guides/system.rst

@@ -45,11 +45,8 @@ ESP HW Support
 
 PSRAM
 ^^^^^
-
-- The header file ``esp_spiram.h`` file has been deleted. Users should use the ``<target>/spiram.h`` file instead.
-- The header file ``esp32/himem.h`` file has been deleted. Users should use the esp_himem.h file instead.
-- `esp_spiram_get_chip_size` has been deleted.
-- `esp_spiram_get_size` has been moved to `esp_private/spiram_private.h`
+- The target specific header files ``spiram.h`` have been deleted. The header file ``esp_spiram.h`` has been deleted. A new component ``esp_psram`` is created, you should include ``esp_psram.h`` instead. Besides, you might need to add ``esp_psram`` component to the list of component requirements in CMakeLists.txt.
+- ``esp_spiram_get_chip_size`` and ``esp_spiram_get_size`` have been deleted. You should use ``esp_psram_get_size`` instead.
 
 ESP Common
 ----------

+ 2 - 2
examples/build_system/cmake/idf_as_lib/CMakeLists.txt

@@ -15,7 +15,7 @@ if("${TARGET}" IN_LIST targets)
                     # although esptool_py does not generate static library,
                     # processing the component is needed for flashing related
                     # targets and file generation
-                    COMPONENTS freertos esptool_py
+                    COMPONENTS freertos esptool_py esp_psram
                     SDKCONFIG ${CMAKE_CURRENT_LIST_DIR}/sdkconfig
                     BUILD_DIR ${CMAKE_BINARY_DIR})
 else()
@@ -33,7 +33,7 @@ add_executable(${elf_file} main.c)
 
 # Link the static libraries to the executable
 if("${TARGET}" IN_LIST targets)
-    target_link_libraries(${elf_file} idf::freertos idf::spi_flash)
+    target_link_libraries(${elf_file} idf::freertos idf::spi_flash idf::esp_psram)
     # Attach additional targets to the executable file for flashing,
     # linker script generation, partition_table generation, etc.
     idf_build_executable(${elf_file})

+ 1 - 2
examples/system/himem/main/himem_example_main.c

@@ -15,9 +15,8 @@
 #include "esp_system.h"
 #include "nvs_flash.h"
 #include "esp_heap_caps.h"
-#include "esp32/spiram.h"
 #include "sdkconfig.h"
-#include "esp_himem.h"
+#include "esp32/himem.h"
 
 
 //Fill memory with pseudo-random data generated from the given seed.

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -664,7 +664,6 @@ components/esp_system/include/esp_freertos_hooks.h
 components/esp_system/include/esp_int_wdt.h
 components/esp_system/include/esp_private/dbg_stubs.h
 components/esp_system/include/esp_private/panic_internal.h
-components/esp_system/include/esp_private/startup_internal.h
 components/esp_system/include/esp_private/system_internal.h
 components/esp_system/include/esp_private/usb_console.h
 components/esp_system/include/esp_task.h