Skip to content

Conversation

@tmedicci
Copy link
Contributor

@tmedicci tmedicci commented Jul 22, 2025

Summary

  • esp32s3/elf: Fix ELF loader on ESP32-S3 when using external PSRAM

Prior to this change, it wasn't possible to load ELF modules from the external PSRAM. There were two main issues about it: 1) copying data using the instruction bus was being used instead of the data bus (this, per se, isn't a problem, but requires special attention regarding data alignment), and 2) the cache was not being properly cleaned and flushed to properly access the loaded data using the instruction bus.

  • esp32s3: Fix bug related to the PSRAM-allocated task stack

If both SPI Flash support (CONFIG_ESP32S3_SPIFLASH) and PSRAM (CONFIG_ESP32S3_SPIRAM) are enabled, the PSRAM can only be assigned to the user's heap (CONFIG_ESP32S3_SPIRAM_USER_HEAP). Additionally, CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK must be set because the system will end up allocating tasks' stacks from the external PSRAM. This has an impact when dealing with SPI flash operations because the cache must be disabled and the running task should not rely on any data from the PSRAM. To accomplish that, It offloads the SPI flash operation to a work queue (which, by definition, allocates its heap from the kernel heap).

The same (assigning the PSRAM to the user's heap) is valid when the Wi-Fi is enabled because the lower-half driver requires data being allocated from the internal memory (which can only be achieved by allocating from the kernel heap when both the kernel and user heaps exist).

  • boards/xtensa/esp32s3: Add missing board_memorymap.h

It is necessary to add the missing board_memorymap.h file for all the ESP32-S3's boards. This header file is necessary whenever Wi-Fi is enabled because it now requires the kernel heap to be enabled (and this file is a dependency for it).

Impact

Impact on user: Yes. It fixes a bug.

Impact on build: No.

Impact on hardware: Yes. It impacts ESP32-S3.

Impact on documentation: No.

Impact on security: No.

Impact on compatibility: No.

Testing

Testing can be performed by building the firmware and flashing it to a ESP32-S3 board with a PSRAM module (this example uses a ESP32-S3-DevKitC-1 v1.1 board with a ESP32-S3-WROOM-2 module). Before applying this patch, the device fails to boot.

Building

The firmware can be built and flashed with the following command:

make -j distclean && ./tools/configure.sh esp32s3-devkit:sta_softap && kconfig-tweak -e ESP32S3_FLASH_MODE_OCT && kconfig-tweak -e ESP32S3_SPIRAM && kconfig-tweak -e ESP32S3_SPIRAM_MODE_OCT && kconfig-tweak -e ESP32S3_SPIRAM_USER_HEAP && make olddefconfig && make EXTRAFLAGS="-Wno-cpp -Werror" bootloader && make flash EXTRAFLAGS="-Wno-cpp -Werror" ESPTOOL_PORT=/dev/ttyUSB0 ESPTOOL_BINDIR=./ -s -j$(nproc) && xtensa-esp32s3-elf-objdump -D nuttx  > objdump.flat

Running

Check boot on UART0:

picocom -b 115200 /dev/ttyUSB0

Results

Before

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x18 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
Octal Flash Mode Enabled
For OPI Flash, Use Default Flash Boot Mode
mode:SLOW_RD, clock div:2
load:0x3fcabc50,len:0x3250
load:0x40374000,len:0xd5fc
SHA-256 comparison failed:
Calculated: bab955807470cc44dd6b715f2a557b2a0aec28520a7bf2a0d5b3bf819db15e9e
Expected: 0000000070f70000000000000000000000000000000000000000000000000000
Attempting to boot anyway...
entry 0x403750ac
*** Booting NuttX ***
dram: lma 0x00000020 vma 0x3fcabc50 len 0x3250   (12880)
iram: lma 0x00003278 vma 0x40374000 len 0xd5fc   (54780)
padd: lma 0x00010888 vma 0x00000000 len 0xf770   (63344)
imap: lma 0x00020000 vma 0x42010000 len 0x7b66c  (505452)
padd: lma 0x0009b674 vma 0x00000000 len 0x4984   (18820)
dmap: lma 0x000a0000 vma 0x3c0a0000 len 0x19928  (104744)
total segments stored 6


Boot failed...

After

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x18 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
Octal Flash Mode Enabled
For OPI Flash, Use Default Flash Boot Mode
mode:SLOW_RD, clock div:2
load:0x3fcabd60,len:0x3260
load:0x40374000,len:0xd74c
SHA-256 comparison failed:
Calculated: 2b6bcf83299757a8ddfc669a9afaa75c94ac31431dbaa96ec8ff2d05d23c59bc
Expected: 0000000010f60000000000000000000000000000000000000000000000000000
Attempting to boot anyway...
entry 0x403750c0
*** Booting NuttX ***
dram: lma 0x00000020 vma 0x3fcabd60 len 0x3260   (12896)
iram: lma 0x00003288 vma 0x40374000 len 0xd74c   (55116)
padd: lma 0x000109e8 vma 0x00000000 len 0xf610   (62992)
imap: lma 0x00020000 vma 0x42010000 len 0x7b804  (505860)
padd: lma 0x0009b80c vma 0x00000000 len 0x47ec   (18412)
dmap: lma 0x000a0000 vma 0x3c0a0000 len 0x19928  (104744)
total segments stored 6

NuttShell (NSH) NuttX-10.4.0
nsh> free
      total       used       free    maxused    maxfree  nused  nfree name
     261744      62616     199128      62976     199056    116      3 Kmem
    8388608      10400    8378208      11384    8378208      8      1 Umem

@github-actions github-actions bot added Arch: xtensa Issues related to the Xtensa architecture Board: xtensa Size: M The size of the change in this PR is medium labels Jul 22, 2025
jerpelea
jerpelea previously approved these changes Jul 23, 2025
simbit18
simbit18 previously approved these changes Jul 23, 2025
yamt
yamt previously requested changes Jul 24, 2025
Copy link
Contributor

@yamt yamt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please let me test a bit.

@yamt
Copy link
Contributor

yamt commented Jul 24, 2025

please let me test a bit.

this breaks my configuration.

my configuration assumes spiram is available for text heap. (for wamr)
the configuration also uses wifi.
as text heap for esp32s3 is currently backed by kmm, kmm separation forced by this PR for wifi breaks it.

(the configuration also happens to use spiflash, which was just working by luck i guess. maybe because LPWORK stack is allocated early in the boot. maybe it helps to have a debug option to make the malloc pick memory regions in an unusual order.)

@yamt yamt dismissed their stale review July 24, 2025 02:08

i tested and commented the result.

@tmedicci
Copy link
Contributor Author

please let me test a bit.

this breaks my configuration.

my configuration assumes spiram is available for text heap. (for wamr) the configuration also uses wifi. as text heap for esp32s3 is currently backed by kmm, kmm separation forced by this PR for wifi breaks it.

(the configuration also happens to use spiflash, which was just working by luck i guess. maybe because LPWORK stack is allocated early in the boot. maybe it helps to have a debug option to make the malloc pick memory regions in an unusual order.)

Can you apply the following diff and re-test your config?

diff --git a/arch/xtensa/src/esp32s3/esp32s3_textheap.c b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
index a0695200f7..1ebcb57f90 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_textheap.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
@@ -87,7 +87,7 @@ void *up_textheap_memalign(size_t align, size_t size)
 
   if (ret == NULL)
     {
-      ret = kmm_memalign(align, size);
+      ret = memalign(align, size);
       if (ret)
         {
           /* kmm_memalign buffer is at the Data bus offset.  Adjust it so we

If not successful, can you please share (part of it, if preferable) your config?

@tmedicci tmedicci closed this Jul 24, 2025
@tmedicci
Copy link
Contributor Author

Sorry, closed by accident.

@tmedicci tmedicci reopened this Jul 24, 2025
@tmedicci
Copy link
Contributor Author

please let me test a bit.

this breaks my configuration.
my configuration assumes spiram is available for text heap. (for wamr) the configuration also uses wifi. as text heap for esp32s3 is currently backed by kmm, kmm separation forced by this PR for wifi breaks it.
(the configuration also happens to use spiflash, which was just working by luck i guess. maybe because LPWORK stack is allocated early in the boot. maybe it helps to have a debug option to make the malloc pick memory regions in an unusual order.)

Can you apply the following diff and re-test your config?

diff --git a/arch/xtensa/src/esp32s3/esp32s3_textheap.c b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
index a0695200f7..1ebcb57f90 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_textheap.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
@@ -87,7 +87,7 @@ void *up_textheap_memalign(size_t align, size_t size)
 
   if (ret == NULL)
     {
-      ret = kmm_memalign(align, size);
+      ret = memalign(align, size);
       if (ret)
         {
           /* kmm_memalign buffer is at the Data bus offset.  Adjust it so we

If not successful, can you please share (part of it, if preferable) your config?

Also, please note that kernel heap is enabled, it's only used by the idle thread and the work queues (about allocating the stack, I meant). So it makes sense not allocating the text heap from the kernel heap on ESP32-S3.

acassis
acassis previously approved these changes Jul 24, 2025
@yamt
Copy link
Contributor

yamt commented Jul 25, 2025

please let me test a bit.

this breaks my configuration.
my configuration assumes spiram is available for text heap. (for wamr) the configuration also uses wifi. as text heap for esp32s3 is currently backed by kmm, kmm separation forced by this PR for wifi breaks it.
(the configuration also happens to use spiflash, which was just working by luck i guess. maybe because LPWORK stack is allocated early in the boot. maybe it helps to have a debug option to make the malloc pick memory regions in an unusual order.)

Can you apply the following diff and re-test your config?

diff --git a/arch/xtensa/src/esp32s3/esp32s3_textheap.c b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
index a0695200f7..1ebcb57f90 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_textheap.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
@@ -87,7 +87,7 @@ void *up_textheap_memalign(size_t align, size_t size)
 
   if (ret == NULL)
     {
-      ret = kmm_memalign(align, size);
+      ret = memalign(align, size);
       if (ret)
         {
           /* kmm_memalign buffer is at the Data bus offset.  Adjust it so we

this approach might work for my config. but i suspect it can break others.
note that text heap api is used for the kernel stuff as well. (mod_insmod.c)
i suspect it needs an api tweak for kmem/umem separation.

If not successful, can you please share (part of it, if preferable) your config?

i provide a full config here anyway. it isn't a secret. (ignore mbedtls and jsonsink stuff. they are wip.)
16756.zip

@tmedicci
Copy link
Contributor Author

tmedicci commented Aug 14, 2025

I'm sorry for the late response to this PR.

As @yamt suggested, I continued testing this implementation and reached some conclusions.

I'm convinced that we should allocate memory from the user heap (if available) for up_textheap_memalign as suggested at #16756 (comment). Please check the discussion at #16768: even with flat build, there are parts of the code that belong to the kernel while others are used by the applications. This applies to the ELF-related files: the mentioned insmod function (from mod_insmod.c) calls libelf_insert whose files are not built with __KERNEL__.

Just for the sake of sanity, this can be checked by building with --trace:

CC:  elf/elf_load.c xtensa-esp32s3-elf-gcc -c -fno-common -Wall -Wstrict-prototypes -Wshadow -Wundef -Wno-attributes -Wno-unknown-pragmas -Wno-psabi -Os -fno-strict-aliasing -fomit-frame-pointer -ffunction-sections -fdata-sections "-g" -fno-strength-reduce -mlongcalls -isystem /home/tiago/Documents/work/espressif/projects/nuttx/nuttxspace_alfa/nuttx/include -D__NuttX__ -Wno-cpp -Werror -I /home/tiago/Documents/work/espressif/projects/nuttx/nuttxspace_alfa/nuttx/libs/libc    elf/elf_load.c -o  bin/elf_load.o

Furthermore, it's easy to conclude that a code that should run from the userspace (just like a ELF file being loaded in a non-flat build), should allocate its text heap from the user heap.

Talking about the ELF loader...

After running some testing, I conclude that we couldn't run any ELF files from the external PSRAM on ESP32-S3 at all... we never caught this issue because the external PSRAM was being allocated along with the internal RAM in a single heap and the testing applications didn't require allocating from the external memory (internal memory was enough). This issue can be reproduced by just enabling the external PSRAM and enabling a separate heap for it. Also, to force the firmware to use the user heap, we need to apply the following patch:

diff --git a/arch/xtensa/src/esp32s3/esp32s3_textheap.c b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
index a0695200f7..1ebcb57f90 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_textheap.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_textheap.c
@@ -87,7 +87,7 @@ void *up_textheap_memalign(size_t align, size_t size)
 
   if (ret == NULL)
     {
-      ret = kmm_memalign(align, size);
+      ret = memalign(align, size);
       if (ret)
         {
           /* kmm_memalign buffer is at the Data bus offset.  Adjust it so we

Built with:

make -j distclean && ./tools/configure.sh esp32s3-devkit:elf && kconfig-tweak -e DEBUG_FEATURES && kconfig-tweak -e DEBUG_ASSERTIONS && kconfig-tweak -e DEBUG_SYMBOLS && kconfig-tweak -e ESP32S3_SPIRAM && kconfig-tweak -e ESP32S3_SPIRAM_USER_HEAP && kconfig-tweak -e ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK && make olddefconfig && make EXTRAFLAGS="-Wno-cpp -Werror" bootloader && make flash EXTRAFLAGS="-Wno-cpp -Werror" ESPTOOL_PORT=/dev/ttyUSB0 ESPTOOL_BINDIR=./ -s -j$(nproc) --trace && picocom -b 115200 /dev/ttyUSB0

The above issue can be checked against the master branch: whenever we force the device to allocate from the PSRAM, it fails... that would happen even without the applied patch once the internal memory runs out...

And, finally...

The update PR (I also updated the description) fixes it: if the external PSRAM is disabled (or allocated to a common heap whenever this is possible), it doesn't matter from where the ELF file's allocates its memory. If we have a separate heap (which is mandatory when SPI flash or Wi-fi are enabled), it will allocate from the external PSRAM. Also, it will ensure that any data being copied to the memory is copied using the data bus. Finally, we still needed to ensure that the cache status is cleaned before running the ELF file.

@tmedicci
Copy link
Contributor Author

@yamt , @acassis and @xiaoxiang781216 , can you please reconsider this patch after #16756 (comment)?

@tmedicci
Copy link
Contributor Author

Fixing the failing jobs... (not directly related, but it's worth fixing it)

@tmedicci tmedicci force-pushed the bugfix/psram_stack branch from 5678918 to 51630fc Compare August 15, 2025 22:12
@github-actions github-actions bot added the Size: L The size of the change in this PR is large label Aug 15, 2025
@tmedicci
Copy link
Contributor Author

Fixing the failing jobs... (not directly related, but it's worth fixing it)

Done. There were missing APIs. Already implemented...

@xiaoxiang781216
Copy link
Contributor

xiaoxiang781216 commented Aug 16, 2025

please fix the build and check error:

/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_conn.o):(.literal.tcp_free+0x8): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_conn.o): in function `tcp_free':
tcp_conn.c:(.text.tcp_free+0x15): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_timer.o):(.literal.tcp_update_timer+0x8): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_timer.o): in function `tcp_update_timer':
tcp_timer.c:(.text.tcp_update_timer+0x2f): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: tcp_timer.c:(.text.tcp_update_timer+0x5a): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_timer.o): in function `tcp_stop_timer':
tcp_timer.c:(.text.tcp_stop_timer+0x8): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_close.o):(.literal.tcp_close_eventhandler+0x4): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_close.o): in function `tcp_close_eventhandler':
tcp_close.c:(.text.tcp_close_eventhandler+0x83): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wlan.o): in function `wlan_txavail':
esp_wlan.c:(.text.wlan_txavail+0x14): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wlan.o): in function `wlan_txtimeout_expiry':
esp_wlan.c:(.text.wlan_txtimeout_expiry+0x14): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wlan.o): in function `wlan_sta_rx_done':
esp_wlan.c:(.text.wlan_sta_rx_done+0x8e): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wifi_utils.o):esp_wifi_utils.c:(.text.esp_event_post+0x6c): more undefined references to `work_queue' follow
make[1]: *** [Makefile:179: nuttx] Error 1
make: *** [tools/Unix.mk:552: nuttx] Error 2
make: Target 'all' not remade because of errors.
/github/workspace/sources/nuttx/tools/testbuild.sh: line 385: /github/workspace/sources/nuttx/../nuttx/nuttx.manifest: No such file or directory
  [1/1] Normalize esp32s3-devkit/mbedtls
36d35
< CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK=y
Saving the new configuration file
HEAD detached at pull/16756/merge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   boards/xtensa/esp32s3/esp32s3-devkit/configs/mbedtls/defconfig

@tmedicci
Copy link
Contributor Author

please fix the build and check error:

/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_conn.o):(.literal.tcp_free+0x8): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_conn.o): in function `tcp_free':
tcp_conn.c:(.text.tcp_free+0x15): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_timer.o):(.literal.tcp_update_timer+0x8): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_timer.o): in function `tcp_update_timer':
tcp_timer.c:(.text.tcp_update_timer+0x2f): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: tcp_timer.c:(.text.tcp_update_timer+0x5a): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_timer.o): in function `tcp_stop_timer':
tcp_timer.c:(.text.tcp_stop_timer+0x8): undefined reference to `work_cancel'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_close.o):(.literal.tcp_close_eventhandler+0x4): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libnet.a(tcp_close.o): in function `tcp_close_eventhandler':
tcp_close.c:(.text.tcp_close_eventhandler+0x83): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wlan.o): in function `wlan_txavail':
esp_wlan.c:(.text.wlan_txavail+0x14): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wlan.o): in function `wlan_txtimeout_expiry':
esp_wlan.c:(.text.wlan_txtimeout_expiry+0x14): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wlan.o): in function `wlan_sta_rx_done':
esp_wlan.c:(.text.wlan_sta_rx_done+0x8e): undefined reference to `work_queue'
/tools/xtensa-esp-elf-gcc/bin/xtensa-esp-elf-ld: /github/workspace/sources/nuttx/staging/libarch.a(esp_wifi_utils.o):esp_wifi_utils.c:(.text.esp_event_post+0x6c): more undefined references to `work_queue' follow
make[1]: *** [Makefile:179: nuttx] Error 1
make: *** [tools/Unix.mk:552: nuttx] Error 2
make: Target 'all' not remade because of errors.
/github/workspace/sources/nuttx/tools/testbuild.sh: line 385: /github/workspace/sources/nuttx/../nuttx/nuttx.manifest: No such file or directory
  [1/1] Normalize esp32s3-devkit/mbedtls
36d35
< CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK=y
Saving the new configuration file
HEAD detached at pull/16756/merge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   boards/xtensa/esp32s3/esp32s3-devkit/configs/mbedtls/defconfig

Fixed that, thanks!

Now the sim-02 test is falling and I couldn't figure out why. Perhaps something related to the CI itself?

@jerpelea jerpelea changed the title esp32s3: Fix bug related to the PSRAM-allocated task stack arch/xtensa/esp32s3: Fix bug related to the PSRAM-allocated task stack Aug 18, 2025
This commit adds the missing `board_memorymap.h` file for all the
ESP32-S3's boards. This header file is necessary whenever Wi-Fi
is enabled, for instance.

Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
If both SPI Flash support (`CONFIG_ESP32S3_SPIFLASH`) and PSRAM
(`CONFIG_ESP32S3_SPIRAM`) are enabled, the PSRAM can only be
assigned to the user's heap (`CONFIG_ESP32S3_SPIRAM_USER_HEAP`).
Additionaly, `CONFIG_ESP32S3_SPI_FLASH_SUPPORT_PSRAM_STACK` must be
set because the system will end up allocating tasks' stacks from
the external PSRAM. This has an impact when dealing with SPI flash
operations because the cache must be disabled and the running task
should not rely on any data from the PSRAM. To accomplish that, It
offloads the SPI flash operation to a work queue (which, by
definition, allocates its heap from the kernel heap).

The same (assigning the PSRAM to the user's heap) is valid when the
Wi-Fi is enabled because the lower-half driver requires data being
allocated from the internal memory (which can only be achieved by
allocating from the kernel heap when both the kernel and user heaps
exists).

Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Prior to this commit, it wasn't possible to load ELF modules from
the external PSRAM. There were two main issues about it: 1) copying
data using the instruction bus was being used instead of the data
bus (this, per si, isn't a problem, but requires special attention
regarding data alignment), and 2) the cache was not being properly
cleaned and flushed to properly access the loaded data using the
instruction bus.

Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
@tmedicci tmedicci force-pushed the bugfix/psram_stack branch from a8a9009 to bc74366 Compare August 19, 2025 11:28
@xiaoxiang781216 xiaoxiang781216 merged commit d250808 into apache:master Aug 19, 2025
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: xtensa Issues related to the Xtensa architecture Area: OS Components OS Components issues Board: xtensa Size: L The size of the change in this PR is large Size: M The size of the change in this PR is medium State: Needs more testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants