Skip to content

fix: waterfall OOM + mesh init diagnostics + WiFi connect (45 KB heap freed) - #10

Open
hellasleeper108 wants to merge 6 commits into
GeneralDussDuss:masterfrom
hellasleeper108:master
Open

fix: waterfall OOM + mesh init diagnostics + WiFi connect (45 KB heap freed)#10
hellasleeper108 wants to merge 6 commits into
GeneralDussDuss:masterfrom
hellasleeper108:master

Conversation

@hellasleeper108

Copy link
Copy Markdown

Summary

Three fixes for the Cardputer-Adv (ESP32-S3FN8, no PSRAM):

1. Waterfall OOM — lora_spectrum.cpp

Reduced ring buffer from 60x200 (24 KB) to 40x120 (9.6 KB). The single malloc(24000) was failing after WiFi/BLE/sub-GHz features fragmented the heap.

2. Mesh init diagnostics — meshtastic_node.cpp

Added Serial.printf at every failure point in mesh_begin(): heap level, calloc results, RadioLib error codes, and xTaskCreate return value. Also added missing error check on xTaskCreatePinnedToCore (previously unchecked — s_up was set true even if the RX task failed to spawn).

3. WiFi connect — system_tools.cpp + 4 heap-00x conversions

Root cause chain:

  • 220 KB of static BSS (67% of 320 KB SRAM) left only ~7.5 KB free at runtime
  • WiFi WPA2 handshake needs ~20-30 KB — AUTH_EXPIRE infinite retry loop
  • Previous failed connect left driver stuck in "connecting" state — ESP_ERR_WIFI_STATE on retry

Fixes applied:

  • WiFi.disconnect() + esp_wifi_stop() before WiFi.mode(WIFI_STA) to break the AUTH_EXPIRE loop and reset driver state
  • Heap check with user-facing toast warning when less than 20 KB free
  • Converted 4 static BSS arrays to malloc-on-demand (45 KB freed):
Array File Size Pattern
g_wdr_aps[256] wifi_wardrive.cpp 20 KB Persistent — g_wdr_aps_init(), never freed
s_capq[8] triton.cpp 8 KB Feature-scoped — entry/exit
active[PAYLOAD_COUNT] wifi_ciw.cpp 7 KB Feature-scoped — 4 exit paths
s_before/s_after/hits usb_guard.cpp 11 KB Feature-scoped — cleanup label

Result: RAM usage dropped from 67.2% to 53.1% (static BSS: 220 KB to 174 KB). Expected free heap at runtime: ~56 KB (up from ~7.5 KB).

Testing

  • Waterfall loads without OOM
  • Mesh features show diagnostic serial output
  • WiFi connect tested on Cardputer-Adv (pending final verification with 56 KB free)

Notes

  • ncm_epbuf (6.3 KB, TinyUSB) was not converted — it is in an external library
  • All null guards added for converted pointers (ISR callbacks, cross-feature seeding)
  • free(nullptr) is safe per C standard — cleanup paths are correct

hellasleeper108 and others added 6 commits June 14, 2026 16:15
…rdputer-Adv

The ESP32-S3FN8 has no PSRAM — just ~320KB internal SRAM. After
WiFi/BLE/sub-GHz features fragment the heap, a 24KB contiguous
malloc fails. Reduced waterfall from 60x200 to 40x120 (2.5x
smaller) while keeping the same visual style.

Also adds diagnostic logging to mesh_begin() to identify which
step fails when 'mesh init failed' toast appears. Logs free heap,
alloc pointers, RadioLib error codes, and xTaskCreate result.

Refs: rf-013, Cardputer-Adv PSRAM-less S3FN8
WiFi.begin() could fail silently when called after esp_wifi_stop()
left the driver in a 'hot but stopped' state from a previous radio
domain. Added WiFi.disconnect(true, true) before WiFi.mode(WIFI_STA)
to ensure a clean slate.

Also added Serial.printf diagnostics for WiFi connect flow: ssid,
password length, mode, status before/after connect attempt.

Refs: wifi-connect-accurate-creds-fail
WiFi.disconnect() was called before WiFi.mode(WIFI_STA), but the
WiFi driver was stopped by radio teardown (esp_wifi_stop). Calling
disconnect on a stopped driver returns ESP_ERR_WIFI_NOT_STARTED (0x3002)
and then WiFi.begin() also fails.

Fix: WiFi.mode(WIFI_STA) first (calls esp_wifi_start internally),
then disconnect(false,false) to clear stale state, then begin.

Also reordered AUTH_EXPIRE was from stale connection attempts
queued before our connect function ran.
Three stacked issues causing 'accurate creds but no connect':

1. AUTH_EXPIRE infinite loop: previous failed connect left the STA
   driver stuck retrying authentication. New WiFi.begin() rejected
   with ESP_ERR_WIFI_STATE (0x3006) because driver thinks it's
   'already connecting'. Fix: esp_wifi_stop() + WiFi.mode(STA)
   to break the loop and restart the driver clean.

2. Heap starvation: only 7.5 KB free when WiFi needs ~20-30 KB
   for the 4-way handshake. The AUTH_EXPIRE loop was consuming
   memory. Added heap check with user-facing toast warning.

3. Missing esp_wifi.h include for direct esp_wifi_stop() call.
ESP32-S3FN8 has no PSRAM — just ~320 KB internal SRAM. 220 KB was
consumed by static BSS, leaving only ~7.5 KB free after WiFi/BLE
framework overhead. WiFi connect requires ~20-30 KB for the 4-way
handshake and was failing with AUTH_EXPIRE on every attempt.

Converted 4 feature-local static arrays from BSS to malloc-on-demand:

1. g_wdr_aps[256] (wardrive AP table) — 20 KB
   Persistent across sessions (Triton/PMKID seed from it).
   Allocated on first wardrive call via g_wdr_aps_init(), never freed.
   Null guards in ISR callback, Triton seeding, PMKID seeding.

2. s_capq[8] (Triton capture queue) — 8 KB
   Allocated at feat_triton() entry, freed on exit.
   Null guard in capture_enqueue().

3. active[PAYLOAD_COUNT] (CIW beacon payloads) — ~7 KB
   Allocated at feat_wifi_ciw() entry, freed on all 4 exit paths.
   Uses local pointer (function-scoped, no file-level static).

4. s_before/s_after/hits (USB Guard scan buffers) — ~11 KB total
   Allocated at feat_usb_guard() entry, freed at cleanup label.
   Null guards in ug_seen_before() and hit scanning loop.
   Also converted stack-local pass2[64] (~3 KB) to malloc.

Expected free heap after boot: ~52 KB (up from ~7.5 KB).
WiFi connect should now have enough headroom for WPA2 handshake.

Refs: heap-001, heap-002, heap-003, heap-004
Three new Meshtastic features for the Cardputer-ADV:

1. Channel Configuration (mesh_channel.cpp):
   - NVS-stored channel name and PSK
   - UI for setting custom channels (e.g. 'Op0-COMNET')
   - Meshtastic channel hash algorithm for frequency selection
   - Menu entry in LoRa submenu

2. ACK/Retry (mesh_chat.cpp + meshtastic_node.cpp):
   - want_ack flag set on outgoing messages
   - 8-entry pending ACK ring buffer with portENTER_CRITICAL
   - Automatic retry (3 attempts, 3s timeout)
   - ACK status API: mesh_ack_status(packet_id)
   - UI shows delivery confirmation in chat

3. Traceroute (mesh_traceroute.cpp + meshtastic_pb.cpp):
   - RouteDiscovery protobuf encode/decode (portnum 70)
   - Hop-by-hop path display with SNR values
   - 10s timeout with 'no response' feedback
   - Node picker UI (reuse roster pattern)

RAM impact: +1.8 KB (53.1% → 53.7%). All three features
compile and link on ESP32-S3FN8 (no PSRAM).

Co-authored-by: Sub-agent (channel config)
Co-authored-by: Sub-agent (ACK/retry)
Co-authored-by: Sub-agent (traceroute)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant