Skip to content

bledev on the P4: writes without response are sometimes lost while the P4 is notifying #79

Description

@bdbarnett

Found while proving bledev.webble (PR stacked on #78): writes without response from a central to the P4 panel (BLE through its C6) are sometimes lost when the P4 is sending notifications at the same moment. Nothing on either side reports it.

What you'd see. The nus gate's ECHO phase stalls. The central sends all 16,384 bytes, and the P4's nus_gate_server.py logs ECHO echoed 15904 of 16384. Everything the P4 sends does arrive.

The evidence, 2026-09-24, MicroPython 1.29 kitchen-sink + speaker-usermod image with micropython-pydevices#10, aioble 0.6.2, bledev from #78 (the webble branch's tests/bledev_web/):

Central Runs ECHO stalls Bytes lost
Chrome on the S21, page MTU 23 (820 writes of 20 bytes) 3 2 480, 960
Chrome on the S21, page MTU 247 5 0
Chrome on Windows, page MTU 247 (board's MTU stuck at 23, #80) 11 2 3,172, and one run whose count I didn't read
  • UP (writes only, no notifications going the other way) never lost a byte in any run.
  • On the phone, Android's log shows every write sent with status 0, the 4-byte tail included, so the writes left the phone.
  • The S3-to-S3 runs in bledev v1, first half: contract, fake, mpble, auto, nus #78 never lost anything in ECHO.
  • With mpftp monitor on the P4's UART for four Windows runs, nothing was printed, but none of those four lost data either.

Not established: where the writes go. Candidates are the ESP-Hosted HCI path to the C6, NimBLE dropping ATT write commands when it's out of buffers while notifying, or the MicroPython IRQ path (invoke_irq_handler prints and swallows an exception from the handler, and mpble copies each captured write inside that handler). The next step is to count _IRQ_GATTS_WRITE events on the board beside the bytes received, which separates "never reached Python" from "reached Python and was dropped".

This breaks bledev's "nothing is dropped quietly" rule on the P4, so a stream over nus needs its own check (or writes with response) there until it's understood.

Activity

  1. bdbarnett commented on Sep 25, 2026

    @bdbarnett
    ContributorAuthor

    Same cause as #87, and fixed by the same line: micropython-pydevices#12. ESP-Hosted's receive path on the P4 drops writes when NimBLE's ACL buffers are full. They fill while the host task waits on Python, which is busy notifying. Each lost write logs E vhci_drv: Rx: alloc_acl_from_ll failed on the UART, but only outside the raw REPL. That's why the monitored runs here showed nothing.

    The test was the laptop (bleak, Windows) running nus_client.py's 16 KB up, down and echo against nus_server.py on the P4, with a hard reset before each run.

  2. bdbarnett commented on Sep 25, 2026

    @bdbarnett
    ContributorAuthor

    Fixed by micropython-pydevices#12, merged 2026-09-25: NimBLE host flow control (CONFIG_BT_NIMBLE_HS_FLOW_CTRL=y) stops ESP-Hosted dropping ACL packets on the P4. The echo-while-notifying gate from the laptop went from 8 of 10 failing to 0 of 10, and reverting the line brought the failures back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions