Kaynağa Gözat

webusb working without disconnect

Jari 3 ay önce
ebeveyn
işleme
5cc0703e1b

+ 1 - 1
.github/workflows/build.yml

@@ -44,7 +44,7 @@ jobs:
             --clean \
             --build-path build/cache/openpuck \
             --output-dir build/openpuck \
-            --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64" \
+            --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64 -DCFG_TUD_VENDOR_TX_BUFSIZE=256" \
             OpenPuck
 
       - name: Generate UF2 (OpenPuck)

+ 2 - 2
.github/workflows/release.yml

@@ -45,7 +45,7 @@ jobs:
             --clean \
             --build-path build/cache/openpuck \
             --output-dir build/openpuck \
-            --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64" \
+            --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64 -DCFG_TUD_VENDOR_TX_BUFSIZE=256" \
             OpenPuck
 
       - name: Generate UF2 (standard)
@@ -73,7 +73,7 @@ jobs:
             --clean \
             --build-path build/cache/openpuck-recovery \
             --output-dir build/openpuck-recovery \
-            --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64 -DOPK_FACTORY_RESET=1" \
+            --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64 -DCFG_TUD_VENDOR_TX_BUFSIZE=256 -DOPK_FACTORY_RESET=1" \
             OpenPuck
 
       - name: Generate UF2 (recovery)

+ 7 - 1
Makefile

@@ -21,6 +21,9 @@ FORMAT_FILES := $(shell find OpenPuck ReversePuckFirmware puck_sniffer pairtui \
 #   CFG_TUD_HID=4            -- four HID interfaces (Steam mode exposes four puck slots); core default is 2.
 #   CFG_TUD_TASK_QUEUE_SZ=64 -- deeper usbd event queue; the default 16 deadlocks the loop task under comms
 #                               load -> watchdog reset (see OpenPuck.ino + docs/BUILD_AND_DEPLOY.md).
+#   CFG_TUD_VENDOR_TX_BUFSIZE=256 -- the WebUSB status blob is ~118 B; the core default 64 can't hold it whole,
+#                               so the panel send (which drops rather than blocks when the FIFO is full) could
+#                               never fit a frame -> blank panel. Sized to hold a full blob with headroom.
 # They're baked in here so a normal build is just `make build` -- no need to remember the flags. Override any
 # on the command line, e.g.   make build CFG_TUD_HID=6 CFG_TUD_TASK_QUEUE_SZ=128
 # or add your own defines:     make build EXTRA_FLAGS="-DOPK_LOG=1"
@@ -29,9 +32,12 @@ CFG_TUD_HID ?= 4
 # Deep so a loop()-context sendReport never blocks on a full usbd event queue (the watchdog path). Sends run
 # from loop() now (usbTxPump) for stable RF timing, so this depth is what keeps that block from happening.
 CFG_TUD_TASK_QUEUE_SZ ?= 512
+# Must hold a whole WebUSB status blob (~118 B) so the drop-on-full panel send can fit one; core default 64 is
+# too small and would silently drop every frame (blank panel / stale mappings).
+CFG_TUD_VENDOR_TX_BUFSIZE ?= 256
 EXTRA_FLAGS ?=
 # {build.flags.usb} is expanded by arduino-cli (VID/PID/strings); pass it through verbatim.
-USB_EXTRA_FLAGS = -DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=$(CFG_TUD_HID) -DCFG_TUD_TASK_QUEUE_SZ=$(CFG_TUD_TASK_QUEUE_SZ) $(EXTRA_FLAGS)
+USB_EXTRA_FLAGS = -DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=$(CFG_TUD_HID) -DCFG_TUD_TASK_QUEUE_SZ=$(CFG_TUD_TASK_QUEUE_SZ) -DCFG_TUD_VENDOR_TX_BUFSIZE=$(CFG_TUD_VENDOR_TX_BUFSIZE) $(EXTRA_FLAGS)
 
 # `flash`/`deploy` take the serial port as a REQUIRED POSITIONAL arg: `make flash /dev/cu.usbmodem1101`.
 # (No auto-detect -- uploading to a guessed serial port risks writing to the wrong device. List with

+ 26 - 4
OpenPuck/webusb_config.cpp

@@ -32,6 +32,13 @@ static volatile bool g_blobRequest = false;
 // browser reads with transferIn(128) to span the two USB-FS packets.
 //                [diag: crc/s][noRx/s][rfStallRecover count]
 #define WB_PAYLEN 116
+// The blob send is drop-on-full (never blocks loop), so the vendor TX FIFO MUST be able to hold a whole blob
+// -- otherwise tud_vendor_write_available() never reaches the frame size and EVERY frame is dropped (blank
+// panel / stale mappings). The Makefile sets -DCFG_TUD_VENDOR_TX_BUFSIZE=256; guard it here so a build without
+// that flag (or a future blob that outgrows the FIFO) fails loudly instead of shipping a dead panel.
+static_assert(CFG_TUD_VENDOR_TX_BUFSIZE >= 2 + WB_PAYLEN,
+	      "CFG_TUD_VENDOR_TX_BUFSIZE too small to hold a WebUSB blob in one "
+	      "write -- build via `make build` (sets 256), or raise the flag.");
 static void webusbSendBlob()
 {
 	if (!usb_web.connected())
@@ -155,8 +162,18 @@ static void webusbSendBlob()
 	p[115] = (uint8_t)(g_crcps > 255 ? 255 : g_crcps);
 	p[116] = (uint8_t)(g_norxps > 255 ? 255 : g_norxps);
 	p[117] = (uint8_t)(g_rfStallRecover > 255 ? 255 : g_rfStallRecover);
-	usb_web.write(p, sizeof p);
-	usb_web.flush();
+	// CRITICAL: usb_web.write() SPINS (`while (remain && _connected) yield();`) until the IN FIFO drains or the
+	// panel disconnects. If the panel holds the WebUSB interface open but stops reading its IN endpoint -- a
+	// backgrounded tab, or the host briefly not servicing transferIn under load -- the FIFO never empties and
+	// that spin hangs loop() until the ~8s watchdog resets us (RESETREAS=watchdog/hang). This is the ONE
+	// cross-task tud_ call the marshalling refactor left able to block loop() (HID goes through the drop-oldest
+	// ring; this didn't). So DROP the blob whenever the FIFO can't take it whole -- a status panel missing an
+	// occasional frame is invisible, and loop() can never stall here again. (Matches the closing-the-panel
+	// "fix": that just flips _connected=false to break the same spin.)
+	if (tud_vendor_write_available() >= sizeof p) {
+		usb_web.write(p, sizeof p);
+		usb_web.flush();
+	}
 }
 
 // Runs on the usbd task (registered via usbTxRegisterDrain -> tud_sof_cb). Sends the blob if loop() asked for
@@ -215,9 +232,14 @@ static void webusbDrainCapture()
 	uint32_t ms = 0;
 	uint8_t slot = 0, rid = 0, nb = 0, b[16];
 	uint16_t budget = 128;
-	while (budget-- && hapLogPull(&ms, &slot, &rid, &nb, b))
+	// Same anti-hang rule as the blob: webusbCapFrame's usb_web.write() spins until the FIFO drains, so stop
+	// pulling the moment the FIFO can't hold a max-size frame (2+9+16=27 B) -- the panel resumes the drain on
+	// its next 0x06 poll. Never let a backed-up panel hang loop() here.
+	while (budget-- && tud_vendor_write_available() >= 27 &&
+	       hapLogPull(&ms, &slot, &rid, &nb, b))
 		webusbCapFrame(ms, slot, rid, nb, b);
-	webusbCapEnd();
+	if (tud_vendor_write_available() >= 3)
+		webusbCapEnd();
 }
 #endif // OPK_LOG
 void webusbPoll()

+ 2 - 1
docs/BUILD_AND_DEPLOY.md

@@ -56,6 +56,7 @@ That's the whole command — the USB flags the firmware needs are baked in, so y
 
 - `CFG_TUD_HID=4` — Steam mode exposes four HID interfaces (the Adafruit nRF core defaults to 2).
 - `CFG_TUD_TASK_QUEUE_SZ=64` — a deeper TinyUSB device event queue; the default of 16 can deadlock the firmware's loop under heavy USB traffic and trip the watchdog.
+- `CFG_TUD_VENDOR_TX_BUFSIZE=256` — the WebUSB status blob (~118 B) must fit the vendor TX FIFO in one write; the default 64 is too small and the panel (which drops frames rather than block the loop) would send nothing — a blank dashboard.
 
 **Overriding the defaults** (only if you need to) — pass them as `make` variables:
 
@@ -69,7 +70,7 @@ make build FQBN=adafruit:nrf52:somethingelse          # a different nRF52840 boa
 `#error`s without them (so a forgotten flag fails loudly instead of shipping a broken/deadlock-prone image):
 
 ```bash
-arduino-cli compile -b adafruit:nrf52:feather52840 --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64" OpenPuck
+arduino-cli compile -b adafruit:nrf52:feather52840 --build-property "build.extra_flags=-DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=4 -DCFG_TUD_TASK_QUEUE_SZ=64 -DCFG_TUD_VENDOR_TX_BUFSIZE=256" OpenPuck
 ```
 
 ## 5. Upload the firmware