Skip to content

Commit

Permalink
Merge branch 'feature/sram1_iram' into 'master'
Browse files Browse the repository at this point in the history
system: add kconfig option for using parts of SRAM1 for IRAM

Closes IDFGH-8351 and IDF-942

See merge request espressif/esp-idf!21214
  • Loading branch information
ESP-Marius committed Apr 10, 2023
2 parents 33bfc7d + 5cbd311 commit 7108ff0
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ MEMORY
*/
iram_seg (RWX) : org = 0x40080400, len = 0xfc00
/* 64k at the end of DRAM, after ROM bootloader stack */
dram_seg (RW) : org = 0x3FFF0000, len = 0x10000
dram_seg (RW) : org = 0x3FFF0000, len = 0x6000
}

/* Default entry point: */
Expand Down
17 changes: 15 additions & 2 deletions components/esp_system/ld/esp32/memory.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,21 @@ ASSERT((CONFIG_ESP32_FIXED_STATIC_RAM_SIZE <= 0x2c200),
#define DRAM0_0_SEG_LEN 0x2c200
#endif

#if CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM
#define SRAM1_IRAM_LEN 0xA000
#else
#define SRAM1_IRAM_LEN 0x0
#endif


MEMORY
{
/* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length
of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but
are connected to the data port of the CPU and eg allow bytewise access. */

/* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */
iram0_0_seg (RX) : org = 0x40080000, len = 0x20000
iram0_0_seg (RX) : org = 0x40080000, len = 0x20000 + SRAM1_IRAM_LEN

#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/* Even though the segment name is iram, it is actually mapped to flash
Expand Down Expand Up @@ -121,8 +128,14 @@ _heap_start = 0x3FFB0000 + DRAM0_0_SEG_LEN;
_heap_start = _heap_low_start;
#endif

/* Heap ends at top of dram0_0_seg */
_sram1_iram_start = 0x400A0000;
_sram1_iram_len = ( _iram_end > _sram1_iram_start) ? (_iram_end - _sram1_iram_start) : 0;
_heap_end = ALIGN(0x40000000 - _sram1_iram_len - 3, 4);

#if CONFIG_ESP32_TRACEMEM_RESERVE_DRAM != 0
_heap_end = 0x40000000 - CONFIG_ESP32_TRACEMEM_RESERVE_DRAM;
#endif


_data_seg_org = ORIGIN(rtc_data_seg);

Expand Down
15 changes: 15 additions & 0 deletions components/esp_system/port/soc/esp32/Kconfig.memory
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,19 @@ menu "Memory"
This is possible due to handling of exceptions `LoadStoreError (3)` and `LoadStoreAlignmentError (9)`
Each unaligned read/write access will incur a penalty of maximum of 167 CPU cycles.

menu "Non-backward compatible options"

config ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM
bool "Reserve parts of SRAM1 for app IRAM (WARNING, read help before enabling)"
depends on !ESP32_TRAX
help
Reserve parts of SRAM1 for app IRAM which was previously reserved for bootloader DRAM.
If booting an app on an older bootloader from before this option was introduced, the app may fail
to boot due to overlapping memory areas. If this is the case please test carefully before pushing out
any OTA updates.

The bootloader DRAM memory should be sufficient for any non-modified IDF bootloader.

endmenu

endmenu # Memory
7 changes: 6 additions & 1 deletion components/heap/port/esp32/memory_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,14 +172,19 @@ SOC_RESERVE_MEMORY_REGION(0x3fffc000, 0x40000000, trace_mem); //Reserve trace me
SOC_RESERVE_MEMORY_REGION(SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH, spi_ram);
#endif

extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end;
extern int _data_start, _heap_start, _heap_end, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end;
// Static data region. DRAM used by data+bss and possibly rodata
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data);

// IRAM code region
// ESP32 has an IRAM-only region 0x4008_0000 - 0x4009_FFFF, reserve the used part
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);

// If IRAM spans into SRAM1 due to CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM, reserve the corresponding part of DRAM
#ifdef CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM
SOC_RESERVE_MEMORY_REGION((intptr_t) &_heap_end, 0x40000000, sram1_iram);
#endif

// RTC Fast RAM region
#ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
#ifdef CONFIG_ESP32_RTCDATA_IN_FAST_MEM
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32/include/soc/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
#define SOC_CACHE_APP_LOW 0x40078000
#define SOC_CACHE_APP_HIGH 0x40080000
#define SOC_IRAM_LOW 0x40080000
#define SOC_IRAM_HIGH 0x400A0000
#define SOC_IRAM_HIGH 0x400AA000
#define SOC_RTC_IRAM_LOW 0x400C0000
#define SOC_RTC_IRAM_HIGH 0x400C2000
#define SOC_RTC_DRAM_LOW 0x3FF80000
Expand Down
23 changes: 23 additions & 0 deletions docs/en/api-guides/performance/ram-usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,29 @@ The following options will reduce IRAM usage of some ESP-IDF features:
- Setting :ref:`CONFIG_HAL_DEFAULT_ASSERTION_LEVEL` to disable assertion for HAL component will save some IRAM especially for HAL code who calls `HAL_ASSERT` a lot and resides in IRAM.
- Refer to sdkconfig menu ``Auto-detect flash chips`` and you can disable flash drivers which you don't need to save some IRAM.

.. only:: esp32

Using SRAM1 for IRAM
^^^^^^^^^^^^^^^^^^^^

The SRAM1 memory area is normally used for DRAM, but it is possible to use parts of it for IRAM with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`. This memory would previously be reserved for DRAM data usage (e.g. bss) by the software bootloader and later added to the heap. After this option was introduced, the bootloader DRAM size was reduced to a value closer to what it normally actually needs.

When compiling with this config option, the linker will make sure that both the app's IRAM section and the bootloader's DRAM section is sufficiently large, and not overlapping. If the software bootloader was compiled before this option existed, then it is guaranteed that these two sections will not overlap. This would typically happen if you are doing an OTA update, where only the app would be updated.

If the IRAM section were to overlap the bootloader's DRAM section then this would be detected during the bootup process and result in a failed boot:

.. code-block:: text
E (204) esp_image: _dram_start = 0x3fff0000, _dram_end = 0x3fff1be0
E (208) esp_image: Segment 4 0x3fff14e0-0x3ffffffc invalid: overlaps bootloader data
.. warning::

Apps compiled with :ref:`CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM`, may fail to boot if used together with a software bootloader compiled without the config option.

Currently the software bootloader compiled with security features enabled uses less than 16KB of DRAM, which means that even when allocating the entirety of this IRAM (40KB), there should still be some spare room. However, as this is not guaranteed, we recommended thoroughly testing before pushing an app update with this option enabled.

Any memory which ends up not being used for static IRAM will be added to the heap.

.. only:: esp32c3

Expand Down
2 changes: 2 additions & 0 deletions tools/ci/build_template_app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ gen_configs() {
# CONFIG_COMPILER_OPTIMIZATION_PERF with flag -O2
echo "CONFIG_COMPILER_OPTIMIZATION_PERF=y" > esp-idf-template/sdkconfig.ci.O2
echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF=y" >> esp-idf-template/sdkconfig.ci.O2
# -O2 makes the bootloader too large to fit in the default space, otherwise(!)
echo "CONFIG_PARTITION_TABLE_OFFSET=0x10000" >> esp-idf-template/sdkconfig.ci.O2

# This part will be built in earlier stage (pre_build job) with only cmake. Built with make in later stage
# CONFIG_COMPILER_OPTIMIZATION_DEFAULT with flag -Og
Expand Down
3 changes: 3 additions & 0 deletions tools/test_apps/system/startup/sdkconfig.ci.sram1_iram
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Only ESP32 has this option
CONFIG_IDF_TARGET="esp32"
CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM=y

0 comments on commit 7108ff0

Please sign in to comment.