diff --git a/components/esp_common/test_apps/.build-test-rules.yml b/components/esp_common/test_apps/.build-test-rules.yml index 19d922b73c..41f3dd4ef0 100644 --- a/components/esp_common/test_apps/.build-test-rules.yml +++ b/components/esp_common/test_apps/.build-test-rules.yml @@ -3,6 +3,7 @@ components/esp_common/test_apps/esp_common: disable: - if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1 - - if: CONFIG_NAME == "psram" and IDF_TARGET in ["esp32c5"] + - if: CONFIG_NAME == "psram_noinit" and SOC_SPIRAM_SUPPORTED != 1 + - if: CONFIG_NAME == "psram_noinit" and IDF_TARGET in ["esp32c61"] temporary: true - reason: esp32c5 is not supported yet # TODO: IDF-8689 + reason: esp32c61 is not supported yet # TODO: IDF-9293 diff --git a/components/esp_common/test_apps/esp_common/main/CMakeLists.txt b/components/esp_common/test_apps/esp_common/main/CMakeLists.txt index 44a5ed32a2..d1e953e638 100644 --- a/components/esp_common/test_apps/esp_common/main/CMakeLists.txt +++ b/components/esp_common/test_apps/esp_common/main/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "test_app_main.c" "test_attr.c" INCLUDE_DIRS "." - PRIV_REQUIRES unity esp_psram + PRIV_REQUIRES unity esp_mm esp_psram WHOLE_ARCHIVE) diff --git a/components/esp_common/test_apps/esp_common/main/test_attr.c b/components/esp_common/test_apps/esp_common/main/test_attr.c index 49bce8c449..0dad47c982 100644 --- a/components/esp_common/test_apps/esp_common/main/test_attr.c +++ b/components/esp_common/test_apps/esp_common/main/test_attr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,10 +10,17 @@ #include "esp_log.h" #include "soc/soc.h" #include "esp_system.h" +#include "hal/cache_ll.h" +#include "hal/cache_hal.h" +#include "esp_cache.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp_private/esp_psram_extram.h" #endif +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) + +static const char *TAG = "attr_test"; + extern int _rtc_noinit_start; extern int _rtc_noinit_end; extern int _rtc_data_start; @@ -44,6 +51,7 @@ static EXT_RAM_NOINIT_ATTR uint32_t s_noinit_ext; static bool data_in_segment(void *ptr, int *seg_start, int *seg_end) { + ESP_LOGV(TAG, "ptr:%p seg_start:%p seg_end:%p", ptr, seg_start, seg_end); return ((intptr_t)ptr < (intptr_t)seg_end) && \ ((intptr_t)ptr >= (intptr_t)seg_start); } @@ -94,7 +102,13 @@ static void write_spiram_and_reset(void) } printf("Flushing cache\n"); // Flush the cache out to SPIRAM before resetting. +#if CONFIG_IDF_TARGET_ESP32 esp_psram_extram_writeback_cache(); +#else + size_t psram_alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA); + uint32_t ext_noinit_size = sizeof(s_noinit_buffer); + TEST_ESP_OK(esp_cache_msync(&s_noinit_buffer, ALIGN_UP(ext_noinit_size, psram_alignment), ESP_CACHE_MSYNC_FLAG_DIR_C2M)); +#endif printf("Restarting\n"); // Reset to test that noinit memory is left intact. diff --git a/components/esp_common/test_apps/esp_common/pytest_esp_common.py b/components/esp_common/test_apps/esp_common/pytest_esp_common.py index 1a31480cc2..aa47cf812f 100644 --- a/components/esp_common/test_apps/esp_common/pytest_esp_common.py +++ b/components/esp_common/test_apps/esp_common/pytest_esp_common.py @@ -1,5 +1,7 @@ # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 +from typing import Any + import pytest from pytest_embedded import Dut @@ -19,6 +21,10 @@ def test_esp_common(dut: Dut) -> None: # psram noinit attr tests with psram enabled @pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -33,6 +39,10 @@ def test_esp_attr_psram_noinit(dut: Dut) -> None: # psram noinit memory tests with psram enabled @pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.supported_targets @pytest.mark.parametrize( @@ -42,8 +52,8 @@ def test_esp_attr_psram_noinit(dut: Dut) -> None: ], indirect=True, ) -def run_multiple_stages(dut: Dut, test_case_num: int, stages: int) -> None: - dut.run_all_single_board_cases() +def test_esp_attr_psram_noinit_multiple_stages(case_tester: Any) -> None: + case_tester.run_all_multi_stage_cases() # psram attr tests with psram enabled @@ -51,6 +61,7 @@ def run_multiple_stages(dut: Dut, test_case_num: int, stages: int) -> None: @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32p4 +@pytest.mark.esp32c5 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.psram_noinit b/components/esp_common/test_apps/esp_common/sdkconfig.ci.psram_noinit index b3e109b8af..dbbc267982 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.psram_noinit +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.psram_noinit @@ -1,6 +1,5 @@ # For EXT_RAM_NOINIT_ATTR -CONFIG_IDF_TARGET="esp32" CONFIG_SPIRAM=y CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.xip_psram_esp32p4 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 similarity index 61% rename from components/esp_common/test_apps/esp_common/sdkconfig.xip_psram_esp32p4 rename to components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 index 706f080ca9..0d33cfbf8f 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.xip_psram_esp32p4 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32p4 @@ -3,4 +3,6 @@ CONFIG_IDF_TARGET="esp32p4" CONFIG_SPIRAM=y CONFIG_SPIRAM_XIP_FROM_PSRAM=y +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 index 0e7812b975..fd9b7e865c 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s2 @@ -3,5 +3,6 @@ CONFIG_IDF_TARGET="esp32s2" CONFIG_SPIRAM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_RODATA=y CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y diff --git a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 index b774ddf1fd..3b1db1f233 100644 --- a/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 +++ b/components/esp_common/test_apps/esp_common/sdkconfig.ci.xip_psram_esp32s3 @@ -3,5 +3,6 @@ CONFIG_IDF_TARGET="esp32s3" CONFIG_SPIRAM=y CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y CONFIG_SPIRAM_RODATA=y CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y diff --git a/components/esp_psram/Kconfig.spiram.common b/components/esp_psram/Kconfig.spiram.common index dd584a55b4..cbff587ffc 100644 --- a/components/esp_psram/Kconfig.spiram.common +++ b/components/esp_psram/Kconfig.spiram.common @@ -23,7 +23,8 @@ config SPIRAM_IGNORE_NOTFOUND ESP_WIFI_CACHE_TX_BUFFER_NUM and use static WiFi Tx buffer may cause potential memory exhaustion issues. Suggest disable SPIRAM_TRY_ALLOCATE_WIFI_LWIP. Suggest disable ESP_WIFI_AMSDU_TX_ENABLED. - Suggest disable ESP_WIFI_CACHE_TX_BUFFER_NUM, need clear CONFIG_FEATURE_CACHE_TX_BUF_BIT of config->feature_caps. + Suggest disable ESP_WIFI_CACHE_TX_BUFFER_NUM, + need clear CONFIG_FEATURE_CACHE_TX_BUF_BIT of config->feature_caps. Suggest change ESP_WIFI_TX_BUFFER from static to dynamic. Also suggest to adjust some buffer numbers to the values used without PSRAM case. Such as, ESP_WIFI_STATIC_TX_BUFFER_NUM, ESP_WIFI_DYNAMIC_TX_BUFFER_NUM. @@ -109,7 +110,7 @@ config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY config SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY bool "Allow .noinit segment placed in external memory" default n - depends on SPIRAM && IDF_TARGET_ESP32 + depends on SPIRAM help If enabled, noinit variables can be placed in PSRAM using EXT_RAM_NOINIT_ATTR. diff --git a/components/esp_system/ld/esp32c5/memory.ld.in b/components/esp_system/ld/esp32c5/memory.ld.in index 1e5cf0de67..980c45021f 100644 --- a/components/esp_system/ld/esp32c5/memory.ld.in +++ b/components/esp_system/ld/esp32c5/memory.ld.in @@ -78,6 +78,9 @@ MEMORY The aim of this is to keep data that will not be moved around and have a fixed address. */ lp_reserved_seg(RW) : org = 0x50000000 + 0x4000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM + + /* PSRAM seg */ + extern_ram_seg(RWX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 } /* Heap ends at top of sram_seg */ diff --git a/components/esp_system/ld/esp32c5/sections.ld.in b/components/esp_system/ld/esp32c5/sections.ld.in index 12540e4ac9..98c7f07519 100644 --- a/components/esp_system/ld/esp32c5/sections.ld.in +++ b/components/esp_system/ld/esp32c5/sections.ld.in @@ -382,6 +382,45 @@ SECTIONS } > default_rodata_seg ASSERT_SECTIONS_GAP(.flash.rodata, .eh_frame_hdr) + /* External RAM */ + /** + * This section is required to skip flash sections, because `extern_ram_seg` + * and `drom_seg` / `irom_seg` are on the same bus when app build use flash sections + */ + .ext_ram.dummy (NOLOAD): + { + . = ORIGIN(extern_ram_seg); + . = . + (_rodata_reserved_end - _flash_rodata_dummy_start); + . = ALIGN (0x10000); + } > extern_ram_seg + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + /* This section holds .ext_ram.bss data, and will be put in PSRAM */ + .ext_ram.bss (NOLOAD) : + { + _ext_ram_bss_start = ABSOLUTE(.); + + mapping[extern_ram] + + ALIGNED_SYMBOL(4, _ext_ram_bss_end) + } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * This section holds data that won't be initialised when startup. + * This section locates in External RAM region. + */ + .ext_ram_noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + + *(.ext_ram_noinit*) + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) + } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + .eh_frame_hdr : { #if CONFIG_COMPILER_CXX_EXCEPTIONS || CONFIG_ESP_SYSTEM_USE_EH_FRAME diff --git a/components/esp_system/ld/esp32p4/sections.ld.in b/components/esp_system/ld/esp32p4/sections.ld.in index ef288b49a9..e9a6833cfc 100644 --- a/components/esp_system/ld/esp32p4/sections.ld.in +++ b/components/esp_system/ld/esp32p4/sections.ld.in @@ -475,7 +475,6 @@ SECTIONS mapping[rodata_noload] } > rodata_seg_low -#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY #if CONFIG_SPIRAM_XIP_FROM_PSRAM /** * This section is required to skip flash sections, because `extern_ram_seg` @@ -488,6 +487,7 @@ SECTIONS } > ext_ram_seg #endif //CONFIG_SPIRAM_XIP_FROM_PSRAM +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY /* This section holds .ext_ram.bss data, and will be put in PSRAM */ .ext_ram.bss (NOLOAD) : { @@ -497,6 +497,21 @@ SECTIONS } > ext_ram_seg #endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * This section holds data that won't be initialised when startup. + * This section locates in External RAM region. + */ + .ext_ram_noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + + *(.ext_ram_noinit*) + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) + } > ext_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + .dram0.bss (NOLOAD) : { ALIGNED_SYMBOL(4, _bss_start_low) diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index ec64034637..82fa95625c 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -113,8 +113,7 @@ _data_seg_org = ORIGIN(rtc_data_seg); /* The lines below define location alias for .rtc.data section based on Kconfig option. When the option is not defined then use slow memory segment - else the data will be placed in fast memory segment - TODO: check whether the rtc_data_location is correct for esp32s2 - IDF-761 */ + else the data will be placed in fast memory segment */ #ifndef CONFIG_ESP32S2_RTCDATA_IN_FAST_MEM REGION_ALIAS("rtc_data_location", rtc_slow_seg ); #else diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 65935dcf97..1b6e992da6 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -265,6 +265,7 @@ SECTIONS ALIGNED_SYMBOL(4, _noinit_end) } > dram0_0_seg +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY /* External Memory BSS. (Variables with EXT_RAM_BSS_ATTR attribute). */ .ext_ram.bss (NOLOAD) : { @@ -274,6 +275,22 @@ SECTIONS ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * This section holds data that won't be initialised when startup. + * This section locates in External RAM region. + */ + .ext_ram_noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + + *(.ext_ram_noinit*) + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) + } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY /* Shared RAM */ .dram0.bss (NOLOAD) : diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index 48173b8757..527f8b9350 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -439,6 +439,7 @@ SECTIONS . = ALIGN (0x10000); } > extern_ram_seg +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY /* This section holds .ext_ram.bss data, and will be put in PSRAM */ .ext_ram.bss (NOLOAD) : { @@ -448,6 +449,22 @@ SECTIONS ALIGNED_SYMBOL(4, _ext_ram_bss_end) } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + +#if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY + /** + * This section holds data that won't be initialised when startup. + * This section locates in External RAM region. + */ + .ext_ram_noinit (NOLOAD) : + { + _ext_ram_noinit_start = ABSOLUTE(.); + + *(.ext_ram_noinit*) + + ALIGNED_SYMBOL(4, _ext_ram_noinit_end) + } > extern_ram_seg +#endif //CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : diff --git a/docs/en/api-guides/external-ram.rst b/docs/en/api-guides/external-ram.rst index 2ca608da3e..a3ab6d36cd 100644 --- a/docs/en/api-guides/external-ram.rst +++ b/docs/en/api-guides/external-ram.rst @@ -123,16 +123,14 @@ This option reduces the internal static memory used by the BSS segment. Remaining external RAM can also be added to the capability heap allocator using the method shown above. -.. only:: esp32 +.. _external_ram_config_noinit: - .. _external_ram_config_noinit: +Allow .noinit Segment to Be Placed in External Memory +-------------------------------------------------------------- - Allow .noinit Segment to Be Placed in External Memory - -------------------------------------------------------------- +Enable this option by checking :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY`. If enabled, the region of the data virtual address space where the PSRAM is mapped to will be used to store non-initialized data. The values placed in this segment will not be initialized or modified even during startup or restart. - Enable this option by checking :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY`. If enabled, the region of the data virtual address space where the PSRAM is mapped to will be used to store non-initialized data. The values placed in this segment will not be initialized or modified even during startup or restart. - - By applying the macro ``EXT_RAM_NOINIT_ATTR``, data could be moved from the internal NOINIT segment to external RAM. Remaining external RAM can still be added to the capability heap allocator using the method shown above, :ref:`external_ram_config_capability_allocator`. +By applying the macro ``EXT_RAM_NOINIT_ATTR``, data could be moved from the internal NOINIT segment to external RAM. Remaining external RAM can still be added to the capability heap allocator using the method shown above, :ref:`external_ram_config_capability_allocator`. .. only:: SOC_SPIRAM_XIP_SUPPORTED diff --git a/docs/zh_CN/api-guides/external-ram.rst b/docs/zh_CN/api-guides/external-ram.rst index a09a69586e..dff291b915 100644 --- a/docs/zh_CN/api-guides/external-ram.rst +++ b/docs/zh_CN/api-guides/external-ram.rst @@ -123,16 +123,14 @@ ESP-IDF 启动过程中,片外 RAM 被映射到数据虚拟地址空间,该 剩余的片外 RAM 也可以通过上述方法添加到堆分配器中。 -.. only:: esp32 +.. _external_ram_config_noinit: - .. _external_ram_config_noinit: +允许 .noinit 段放入片外存储器 +------------------------------------- - 允许 .noinit 段放入片外存储器 - ------------------------------------- +通过勾选 :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY` 启用该选项。启用该选项后,PSRAM 被映射到的数据虚拟地址空间将用于存储未初始化的数据。即使在启动或重新启动期间,放置在该段中的值也不会被初始化或修改。 - 通过勾选 :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY` 启用该选项。启用该选项后,PSRAM 被映射到的数据虚拟地址空间将用于存储未初始化的数据。即使在启动或重新启动期间,放置在该段中的值也不会被初始化或修改。 - - 通过应用 ``EXT_RAM_NOINIT_ATTR`` 宏,可以将数据从内部 NOINIT 段移到片外 RAM。剩余的片外 RAM 也可以通过上述方法添加到堆分配器中,具体请参考 :ref:`external_ram_config_capability_allocator`。 +通过应用 ``EXT_RAM_NOINIT_ATTR`` 宏,可以将数据从内部 NOINIT 段移到片外 RAM。剩余的片外 RAM 也可以通过上述方法添加到堆分配器中,具体请参考 :ref:`external_ram_config_capability_allocator`。 .. only:: SOC_SPIRAM_XIP_SUPPORTED diff --git a/examples/system/xip_from_psram/sdkconfig.esp32p4_200m b/examples/system/xip_from_psram/sdkconfig.ci.esp32p4_200m similarity index 100% rename from examples/system/xip_from_psram/sdkconfig.esp32p4_200m rename to examples/system/xip_from_psram/sdkconfig.ci.esp32p4_200m