mem(ncm): move USB-NCM tether RX copy to PSRAM (relieve internal SRAM) - #85
Closed
iliabaranov wants to merge 1 commit into
Closed
mem(ncm): move USB-NCM tether RX copy to PSRAM (relieve internal SRAM)#85iliabaranov wants to merge 1 commit into
iliabaranov wants to merge 1 commit into
Conversation
The on_usb_rx per-frame copy handed to lwIP was malloc'd from internal SRAM on the device-side USB-NCM path — the scarcest heap on the S3, and the pool that dipped to an ~8 KB low-watermark on the tethered device. The buffer is filled by a plain CPU memcpy on the TinyUSB task (never DMA, never ISR) and consumed on the TCPIP thread, so the flash-cache- disable hazard does not apply; move it to PSRAM via heap_caps_malloc. This removes per-frame internal-heap alloc/free churn (fragmentation of the last few internal KB) from the tether RX hot path. netif_l2_free()'s free() handles a PSRAM pointer unchanged. The dominant USB-NCM consumer (the ~19.3 KB NTB DMA block) is pinned to internal SRAM by the S3 USB-OTG DMA engine and cannot move; reclaiming it via NTB count/size trim is tracked separately, gated on the USB-NCM stability regression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UJz4ZB7WcPErDqKLWDq3ht
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
on_usb_rxincomponents/ml_dev_tether/src/ml_dev_tether.ccopies each inbound USB-NCM frame into a fresh buffer handed to lwIP. That copy wasmalloc'd from internal SRAM — the scarcest heap on the ESP32-S3, and the pool observed dipping to an ~8 KB low-watermark on the tethered device during the 12 h soak. This moves the copy to PSRAM viaheap_caps_malloc(len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT).Why it's safe (flash-cache-disable hazard does NOT apply)
The buffer is filled by a plain CPU
memcpyon the TinyUSB task (the code comment above the call confirms "not an ISR") and consumed on the TCPIP thread — it is never a DMA target and never touched in ISR context. So the usual "PSRAM buffer inaccessible while flash cache is disabled" hazard doesn't apply here.netif_l2_free()'sfree()handles a PSRAM pointer unchanged.Effect
Removes per-frame internal-heap alloc/free churn (fragmentation of the last few internal KB) from the device-side USB-NCM RX hot path — the exact path on the device that showed the low internal watermark.
Scope / what this does NOT do
The dominant USB-NCM internal consumer — the ~19.3 KB
ncm_epbufNTB block — is a live bus-master DMA target and the S3 USB-OTG DMA engine can only address internal SRAM, so it cannot move to PSRAM (verified in-tree:tusb_config.hDRAM_ATTR,dcd_dwc2.cinternal-DMA arch gate; matches ESP-IDF external-RAM docs). Reclaiming that block by trimming NTB count/size is a separate, gated change (must re-run the USB-NCM stability regression that set IN-buffers to 4).Verification
idf.py buildexit 0);ml_dev_tether.c.objconfirmed to referenceheap_caps_malloc(change compiled in, not a stale object).heap_min_intrises /pstop_sf_nomemstays 0 (deferred until the in-flight 12 h zero-disconnect soak completes so it isn't perturbed).One-line change to a Polymath-owned file; no managed-component or safety-path edits.
🤖 Generated with Claude Code