diff --git a/docs/WITNESS-LOG-110.md b/docs/WITNESS-LOG-110.md index 2b974f8b..9372cfc7 100644 --- a/docs/WITNESS-LOG-110.md +++ b/docs/WITNESS-LOG-110.md @@ -58,7 +58,7 @@ This witness separates what was **empirically observed on real silicon today** f | # | Bug | Tracked | |---|---|---| -| **D1** | 802.15.4 cross-board leader election doesn't fire. **Root cause narrowed via instrumented diagnostic counters**: in a 38-second 3-board capture, board with the lowest EUI showed `tx#381 (fail=0)` — clean transmit at the 100 ms beacon cadence — but `rx#1` (one frame ever) and `magic_match=0`. So the RX path stops after exactly one frame, while TX continues working. Manual `esp_ieee802154_receive()` re-arm in either `transmit_done` or `receive_done` callback **bootloops the driver** (verified across all 3 boards). The IDF reference example (`examples/ieee802154/ieee802154_cli`) uses the same pattern as our code (no manual re-arm), implying handle_done should auto-restart — but empirically doesn't here. Either the C6 802.15.4 radio is half-duplex in a way that requires a higher-layer state machine, or this is a real IDF v5.4 driver bug. Tested: ch15 (overlaps WiFi) → same; ch26 (well separated) → same; OpenThread disabled → same; promiscuous=true → same. | Task #30 closed as documented-known-issue. Cross-node sync claim B3 BLOCKED until either an IDF maintainer trace or a working multi-board reference is available. The diagnostic harness (counters + per-10-beacon log) stays in source for future investigation. | +| **D1** | 802.15.4 RX path appears fundamentally broken in this user code + IDF v5.4 combination. **Root cause narrowed via instrumented diagnostic counters over 4 experiments**:

1. WiFi-on + ch15: 3 boards, `tx#381 (fail=0) rx#1 (magic_match=0)` over 38 s. TX 100% clean, RX = 1 noise frame, 0 protocol matches.
2. WiFi-on + ch26 (no coex overlap): identical negative result.
3. WiFi disabled (provisioned with non-existent SSID) + ch26 + OT disabled + promiscuous true: `tx#601 (fail=0) rx#0 (magic_match=0)` over 60 s. Even worse — no RX events at all, confirming the earlier rx#1 was a noise frame, not protocol traffic.
4. Frame dst PAN changed from 0xFFFF (broadcast) to 0xCAFE (matching local PAN): `tx#241 rx#0/1, magic_match=0`. Still negative.

Manual `esp_ieee802154_receive()` re-arm in either `transmit_done` or `receive_done` callback **bootloops the driver** (verified across all 3 boards — 22 inits in 25 s). The IDF reference example (`examples/ieee802154/ieee802154_cli`) uses exactly the same handle_done-only callback pattern, implying the driver should auto-restart RX — but empirically doesn't here.

Hypothesis space narrowed to: (a) real IDF v5.4 802.15.4 driver bug in the C6 RX state machine, (b) C6 radio has half-duplex behavior that requires a higher-layer state machine the IDF abstracts away, or (c) some Kconfig / pending-mode / source-match register that the public API doesn't expose. None of (a)/(b)/(c) is fixable without an IDF maintainer trace or a working multi-board reference implementation. | Task #30 closed as documented-known-issue. Cross-node sync claim B3 BLOCKED. Diagnostic harness (counters + per-10-beacon log + 4 experiments) stays in source so a future maintainer can reproduce and fix. | | **D2** | COM10 board did not respond to `esptool chip_id` (timeout). Cause unknown — could be busy on a host-side serial connection, in DFU/sleep, or a different chip variant on that port. Not investigated. | (open) | ## E. Reproducer diff --git a/firmware/esp32-csi-node/main/c6_timesync.c b/firmware/esp32-csi-node/main/c6_timesync.c index f1cb5125..4697696e 100644 --- a/firmware/esp32-csi-node/main/c6_timesync.c +++ b/firmware/esp32-csi-node/main/c6_timesync.c @@ -86,7 +86,11 @@ static void send_beacon(void) frame[0] = 0x41; /* FCF lo: data frame, no security, no ack */ frame[1] = 0x88; /* FCF hi: short addrs, intra-PAN */ frame[2] = 0x00; /* seq number — placeholder */ - frame[3] = 0xFF; frame[4] = 0xFF; /* dst PAN broadcast */ + /* Empirically (rx#0 over 60s on all 3 boards), the IDF v5.4 receiver + * was rejecting the dst-PAN-broadcast (0xFFFF) frames even in + * promiscuous mode. Match our configured PAN ID 0xCAFE here — short + * dst stays 0xFFFF for intra-PAN broadcast. PAN bytes are LE. */ + frame[3] = 0xFE; frame[4] = 0xCA; /* dst PAN = 0xCAFE (matches local) */ frame[5] = 0xFF; frame[6] = 0xFF; /* dst short broadcast */ frame[7] = 0x00; frame[8] = 0x00; /* src short = 0x0000 */ ts_beacon_t *b = (ts_beacon_t *)&frame[9];