Skip to content

Commit

Permalink
feat(psram): add psram noinit segment support on S2/S3/P4/C5
Browse files Browse the repository at this point in the history
Closes #14253
  • Loading branch information
Kainarx committed Sep 12, 2024
1 parent 6d947cd commit 58c3ee2
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 50 deletions.
11 changes: 9 additions & 2 deletions components/esp_common/test/test_attr.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand All @@ -15,6 +15,8 @@
#endif
#include "test_utils.h"

#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))

extern int _rtc_noinit_start;
extern int _rtc_noinit_end;
extern int _rtc_data_start;
Expand All @@ -30,7 +32,6 @@ extern int _ext_ram_noinit_end;
extern int _ext_ram_bss_start;
extern int _ext_ram_bss_end;


#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2)
//IDF-5045
//Variables for test: Attributes place variables into correct sections
Expand Down Expand Up @@ -95,7 +96,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
uint32_t ext_noinit_size = sizeof(s_noinit_buffer);
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
Cache_WriteBack_Addr((uint32_t)s_noinit_buffer, ext_noinit_size);
#endif

printf("Restarting\n");
// Reset to test that noinit memory is left intact.
Expand Down
6 changes: 3 additions & 3 deletions components/esp_psram/Kconfig.spiram.common
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +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.

Expand Down Expand Up @@ -110,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.

Expand Down
3 changes: 1 addition & 2 deletions components/esp_system/ld/esp32s2/memory.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,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
Expand Down
16 changes: 15 additions & 1 deletion components/esp_system/ld/esp32s2/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ SECTIONS
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg

/* external memory bss, from any global variable with EXT_RAM_BSS_ATTR attribute*/
/* External Memory BSS. (Variables with EXT_RAM_BSS_ATTR attribute). */
.ext_ram.bss (NOLOAD) :
{
_ext_ram_bss_start = ABSOLUTE(.);
Expand All @@ -258,6 +258,20 @@ SECTIONS
_ext_ram_bss_end = ABSOLUTE(.);
} > extern_ram_seg

/**
* 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*)

. = ALIGN(4);
_ext_ram_noinit_end = ABSOLUTE(.);
} > extern_ram_seg

/* Shared RAM */
.dram0.bss (NOLOAD) :
{
Expand Down
14 changes: 14 additions & 0 deletions components/esp_system/ld/esp32s3/sections.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,20 @@ SECTIONS
_ext_ram_bss_end = ABSOLUTE(.);
} > extern_ram_seg

/**
* 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*)

. = ALIGN(4);
_ext_ram_noinit_end = ABSOLUTE(.);
} > extern_ram_seg

/* Marks the end of IRAM code segment */
.iram0.text_end (NOLOAD) :
{
Expand Down
36 changes: 16 additions & 20 deletions docs/en/api-guides/external-ram.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ ESP-IDF fully supports the use of external RAM in applications. Once the externa
* :ref:`external_ram_config_memory_map`
* :ref:`external_ram_config_capability_allocator`
* :ref:`external_ram_config_malloc` (default)
:esp32 or esp32s2: * :ref:`external_ram_config_bss`
:esp32: * :ref:`external_ram_config_noinit`
* :ref:`external_ram_config_bss`
* :ref:`external_ram_config_noinit`

.. _external_ram_config_memory_map:

Expand Down Expand Up @@ -94,36 +94,32 @@ If a suitable block of preferred internal/external memory is not available, the

Because some buffers can only be allocated in internal memory, a second configuration item :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` defines a pool of internal memory which is reserved for *only* explicitly internal allocations (such as memory for DMA use). Regular ``malloc()`` will not allocate from this pool. The :ref:`MALLOC_CAP_DMA <dma-capable-memory>` and ``MALLOC_CAP_INTERNAL`` flags can be used to allocate memory from this pool.

.. only:: SOC_SPIRAM_SUPPORTED
.. _external_ram_config_bss:

.. _external_ram_config_bss:
Allow .bss Segment to be Placed in External Memory
-------------------------------------------------------

Allow .bss Segment to be Placed in External Memory
-------------------------------------------------------
Enable this option by checking :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`. This configuration setting is independent of the other three.

Enable this option by checking :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY`. This configuration setting is independent of the other three.
If enabled, the region of the data virtual address space where the PSRAM is mapped to will be used to store zero-initialized data (BSS segment) from the lwIP, net80211, libpp, wpa_supplicant and bluedroid ESP-IDF libraries.

If enabled, the region of the data virtual address space where the PSRAM is mapped to will be used to store zero-initialized data (BSS segment) from the lwIP, net80211, libpp, wpa_supplicant and bluedroid ESP-IDF libraries.
Additional data can be moved from the internal BSS segment to external RAM by applying the macro ``EXT_RAM_BSS_ATTR`` to any static declaration (which is not initialized to a non-zero value).

Additional data can be moved from the internal BSS segment to external RAM by applying the macro ``EXT_RAM_BSS_ATTR`` to any static declaration (which is not initialized to a non-zero value).
It is also possible to place the BSS section of a component or a library to external RAM using linker fragment scheme ``extram_bss``.

It is also possible to place the BSS section of a component or a library to external RAM using linker fragment scheme ``extram_bss``.
This option reduces the internal static memory used by the BSS segment.

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.

Remaining external RAM can also be added to the capability heap allocator using the method shown above.

.. _external_ram_config_noinit:

.. only:: esp32

.. _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, a region of the address space provided in external RAM 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`.

Restrictions
============
Expand Down
2 changes: 1 addition & 1 deletion docs/en/api-guides/memory-types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Constant data may also be placed into DRAM, for example if it is used in an non-

The macro ``__NOINIT_ATTR`` can be used as attribute to place data into ``.noinit`` section. The values placed into this section will not be initialized at startup and should keep its value after software restart.

.. only:: esp32
.. only:: SOC_SPIRAM_SUPPORTED

By applying the ``EXT_RAM_NOINIT_ATTR`` macro, non-initialized value could also be placed in external RAM. To do this, the :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY` needs to be enabled. See :ref:`external_ram_config_noinit`. If the :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY` is not enabled, ``EXT_RAM_NOINIT_ATTR`` will behave just as ``__NOINIT_ATTR``, it will make data to be placed into ``.noinit`` segment in internal RAM.

Expand Down
36 changes: 16 additions & 20 deletions docs/zh_CN/api-guides/external-ram.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ ESP-IDF 完全支持将片外 RAM 集成到您的应用程序中。在启动并
* :ref:`external_ram_config_memory_map`
* :ref:`external_ram_config_capability_allocator`
* :ref:`external_ram_config_malloc` (default)
:esp32 or esp32s2: * :ref:`external_ram_config_bss`
:esp32: * :ref:`external_ram_config_noinit`
* :ref:`external_ram_config_bss`
* :ref:`external_ram_config_noinit`

.. _external_ram_config_memory_map:

Expand Down Expand Up @@ -91,36 +91,32 @@ ESP-IDF 启动过程中,片外 RAM 被映射到以 {IDF_TARGET_PSRAM_ADDR_STAR

由于有些内存缓冲器仅可在内部存储器中分配,因此需要使用第二个配置项 :ref:`CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL` 定义一个内部内存池,仅限显式的内部存储器分配使用(例如用于 DMA 的存储器)。常规 ``malloc()`` 将不会从该池中分配,但可以使用 :ref:`MALLOC_CAP_DMA <dma-capable-memory>` 和 ``MALLOC_CAP_INTERNAL`` 标志从该池中分配存储器。

.. only:: SOC_SPIRAM_SUPPORTED
.. _external_ram_config_bss:

.. _external_ram_config_bss:
允许 .bss 段放入片外存储器
-----------------------------------

允许 .bss 段放入片外存储器
-----------------------------------
通过勾选 :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` 启用该选项,此选项配置与其它三个选项互不影响。

通过勾选 :ref:`CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY` 启用该选项,此选项配置与其它三个选项互不影响
启用该选项后,PSRAM 被映射到的数据虚拟地址空间将用于存储来自 lwip、net80211、libpp, wpa_supplicant 和 bluedroid ESP-IDF 库中零初始化的数据(BSS 段)

启用该选项后,PSRAM 被映射到的数据虚拟地址空间将用于存储来自 lwip、net80211、libpp, wpa_supplicant 和 bluedroid ESP-IDF 库中零初始化的数据(BSS 段)
``EXT_RAM_BSS_ATTR`` 宏应用于任何静态声明(未初始化为非零值)之后,可以将附加数据从内部 BSS 段移到片外 RAM

``EXT_RAM_BSS_ATTR`` 宏应用于任何静态声明(未初始化为非零值)之后,可以将附加数据从内部 BSS 段移到片外 RAM。
也可以使用链接器片段方案 ``extram_bss`` 将组件或库的 BSS 段放到片外 RAM

也可以使用链接器片段方案 ``extram_bss`` 将组件或库的 BSS 段放到片外 RAM 中
启用此选项可以减少 BSS 段占用的内部静态存储

启用此选项可以减少 BSS 段占用的内部静态存储
剩余的片外 RAM 也可以通过上述方法添加到堆分配器中

剩余的片外 RAM 也可以通过上述方法添加到堆分配器中。

.. _external_ram_config_noinit:

.. only:: esp32

.. _external_ram_config_noinit:

允许 .noinit 段放入片外存储器
-------------------------------------
允许 .noinit 段放入片外存储器
-------------------------------------

通过勾选 :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY` 启用该选项。启用该选项后,外部 RAM 中提供的地址空间区域将用于存储未初始化的数据。即使在启动或重新启动期间,放置在该段中的值也不会被初始化或修改。
通过勾选 :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`。

片外 RAM 使用限制
===================
Expand Down
2 changes: 1 addition & 1 deletion docs/zh_CN/api-guides/memory-types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ DRAM(数据 RAM)

可以将 ``__NOINIT_ATTR`` 宏用作属性,从而将数据放入 ``.noinit`` 部分。放入该部分的值在启动时不会被初始化,在软件重启后也会保持值不变。

.. only:: esp32
.. only:: SOC_SPIRAM_SUPPORTED

通过使用 ``EXT_RAM_NOINIT_ATTR`` 宏,noinit 数据也可以放入外部 RAM 中。为此,需要启用 :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY`,可参考 :ref:`external_ram_config_noinit`。如果没有启用 :ref:`CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY`, ``EXT_RAM_NOINIT_ATTR`` 会和 ``__NOINIT_ATTR`` 一样,将数据放入内部 RAM 的 ``.noinit`` 部分。

Expand Down
7 changes: 7 additions & 0 deletions tools/unit-test-app/configs/psram_noinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TEST_COMPONENTS=spi_flash

CONFIG_SPIRAM=y
CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y

CONFIG_IDF_TARGET="esp32s2"

0 comments on commit 58c3ee2

Please sign in to comment.