Skip to content

usbhost: 9.9 KB of the ESP32-S3's internal RAM back - #158

Merged
bdbarnett merged 1 commit into
mainfrom
fix/usbhost-internal-ram
Oct 21, 2026
Merged

bdbarnett merged 1 commit into
mainfrom
fix/usbhost-internal-ram

Conversation

@bdbarnett

Copy link
Copy Markdown
Contributor

On an ESP32-S3 build with every module, usbhost took 18.5 KB of internal
RAM. Most of it held nothing that needs to be there:

  • The 3 KB event queue and the 1 KB of isochronous stream slots were static.
    They now come from the heap, PSRAM first, the first time a host starts or
    a stream opens, and stay. Neither is touched from an interrupt. The stream
    gates stay static: they use read-modify-write atomics, which the S3 can't
    do on PSRAM. usbhost's .bss goes from 5,134 to 1,077 bytes.
  • The linker fragment put all of TinyUSB's device controller, device core,
    FIFO code and DWC2 common code in IRAM. TinyUSB registers its interrupt
    without ESP_INTR_FLAG_IRAM, so none of it has to run with the cache off;
    IRAM only saves the interrupt path its cache misses. It now holds that
    path alone: the interrupt and event handlers, the endpoint re-arm a
    streaming endpoint makes from the interrupt, and the FIFO copies. Set-up,
    tear-down, control transfers and tud_task() go back to flash: 5.8 KB.

On the Waveshare ESP32-S3-Touch-LCD-4.3, a host started and stopped twice,
its event queue from PSRAM (starting the host costs the same internal RAM as
before), and the board's native USB CDC answered the PC both before and
after the host had it.

On an ESP32-S3 build with every module, usbhost took 18.5 KB of internal
RAM. Most of it held nothing that needs to be there:

- The 3 KB event queue and the 1 KB of isochronous stream slots were static.
  They now come from the heap, PSRAM first, the first time a host starts or
  a stream opens, and stay. Neither is touched from an interrupt. The stream
  gates stay static: they use read-modify-write atomics, which the S3 can't
  do on PSRAM. usbhost's .bss goes from 5,134 to 1,077 bytes.
- The linker fragment put all of TinyUSB's device controller, device core,
  FIFO code and DWC2 common code in IRAM. TinyUSB registers its interrupt
  without ESP_INTR_FLAG_IRAM, so none of it has to run with the cache off;
  IRAM only saves the interrupt path its cache misses. It now holds that
  path alone: the interrupt and event handlers, the endpoint re-arm a
  streaming endpoint makes from the interrupt, and the FIFO copies. Set-up,
  tear-down, control transfers and tud_task() go back to flash: 5.8 KB.

On the Waveshare ESP32-S3-Touch-LCD-4.3, a host started and stopped twice,
its event queue from PSRAM (starting the host costs the same internal RAM as
before), and the board's native USB CDC answered the PC both before and
after the host had it.
@bdbarnett
bdbarnett merged commit 1d54b99 into main Oct 21, 2026
5 checks passed
@bdbarnett
bdbarnett deleted the fix/usbhost-internal-ram branch October 21, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant