Skip to content

fix(firmware): phantom LD2410 detection + ENOMEM backoff (#1135)#1159

Merged
ruvnet merged 1 commit into
mainfrom
fix/1135-ld2410-phantom-enomem
Jun 22, 2026
Merged

fix(firmware): phantom LD2410 detection + ENOMEM backoff (#1135)#1159
ruvnet merged 1 commit into
mainfrom
fix/1135-ld2410-phantom-enomem

Conversation

@ruvnet

@ruvnet ruvnet commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Fixes #1135 (against the v0.8.1-esp32 release).

Bug #2 — phantom LD2410 on a floating UART (root cause)

LD2410 probe-detection matched only the 4-byte head 0xF4F3F2F1, so floating-pin noise at 256000 baud could phantom-detect a sensor and spawn a UART task. Now requires a full validated report frame — head + sane intra-frame length + matching tail 0xF8F7F6F5 — the same validate-before-trust approach used for MR60BHA2 in #1107. Extracted to mmwave_detect.h and shared with a host unit test so firmware and test can't diverge.

Bug #1 — sendto ENOMEM stuck loop

Fixed 100 ms backoff was too short to drain sustained lwIP/WiFi buffer pressure. Now exponential (100→200→…→2000 ms per consecutive ENOMEM, reset on first successful send). Eliminating the phantom LD2410 task (bug #2) also removes the extra load that tipped the reporter's tier-2 node into the stuck state.

Validation

  • Host unit test (test_mmwave_detect.c, 8 vectors) — tests the real predicate; the stream_sender: sendto ENOMEM in a tight loop on ESP32-S3 (v0.8.1-esp32) — 0 UDP frames ever leave the node #1135 case (head magic without valid tail) is REJECTED. Wired into the Makefile + host_tests (runs gcc in CI). Compiles clean against the header; truth table proven.
  • Hardware (ESP32-S3 QFN56 rev v0.2 — the reporter's silicon): tier-2 streams ~100 frames/s, no stuck ENOMEM, correctly reports no mmWave (no phantom), no regression.
  • Honest limit: I couldn't reproduce the reporter's environment-specific floating-pin noise, so the deterministic proof for the phantom case is the unit test, not a hardware repro.

🤖 Generated with claude-flow

Bug #2 (root cause): LD2410 probe-detection matched only the 4-byte head
0xF4F3F2F1, so a floating UART at 256000 baud could phantom-detect a sensor
and spawn a UART task. Now requires a full validated report frame (head +
sane length + tail 0xF8F7F6F5), extracted to mmwave_detect.h and shared with
a host unit test (test_mmwave_detect.c, 8 vectors) so firmware and test can't
diverge. Matches the validate-before-trust approach used for MR60 in #1107.

Bug #1: sendto ENOMEM used a fixed 100 ms backoff too short to drain sustained
lwIP/WiFi buffer pressure, so a node could stay stuck. Now exponential
(100->200->...->2000 ms per consecutive ENOMEM, reset on first successful
send). Removing the phantom LD2410 task (bug #2) also removes the extra load
that tipped the reporter's tier-2 node into the stuck state.

Validated on ESP32-S3 QFN56 rev v0.2 (the reporter's silicon): tier-2 streams
~100 frames/s with no stuck ENOMEM and correctly reports no mmWave (no
phantom). LD2410 predicate truth table proven (head-without-tail REJECTED).
Could not reproduce the reporter's environment-specific floating-pin noise, so
the deterministic proof is the host unit test.

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet ruvnet merged commit 7831f29 into main Jun 22, 2026
41 checks passed
@ruvnet ruvnet deleted the fix/1135-ld2410-phantom-enomem branch June 22, 2026 16:31

@Kdm78 Kdm78 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Plain text

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.

stream_sender: sendto ENOMEM in a tight loop on ESP32-S3 (v0.8.1-esp32) — 0 UDP frames ever leave the node

2 participants