<feed xmlns='http://www.w3.org/2005/Atom'>
<title>tinyusb.git/examples/device, branch etmtrace-rp2350</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.</subtitle>
<id>http://cgit.235523.xyz/tinyusb.git/atom/examples/device?h=etmtrace-rp2350</id>
<link rel='self' href='http://cgit.235523.xyz/tinyusb.git/atom/examples/device?h=etmtrace-rp2350'/>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/'/>
<updated>2026-08-25T02:46:42Z</updated>
<entry>
<title>ci: an empty selection must build nothing, plus selector follow-ups (#3845)</title>
<updated>2026-08-25T02:46:42Z</updated>
<author>
<name>Ha Thach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-25T02:46:42Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=da255b1d2db10b8f31332a779b2a526f579acee1'/>
<id>urn:sha1:da255b1d2db10b8f31332a779b2a526f579acee1</id>
<content type='text'>
ci: an empty selection must build nothing, plus selector follow-ups

A PR whose build axis legitimately selected nothing rebuilt everything.
build.yml reads .build.families twice - as a |-joined regex, and implicitly
as "is anything selected" - but tested only -z "$FAMILY_REGEX", which an
empty list and a charset-rejected one both satisfy while meaning opposite
things. ci_set_matrix had already returned the correct all-empty matrix;
the fall-open branch discarded it. #3842 and #3840 each spent 74 cmake legs
on it. Branch on the two cases instead, rename FAM_* to FAMILY_*, and cover
the block with a test that extracts it from build.yml and executes it - it
had no test at all, which is how this shipped through two merges.

Follow-ups to the same machinery: glob.escape the repo root at five sites,
so a checkout path containing [ or * stops failing closed; drop the ci-full
label, read after the matrix was already computed and so never functional;
delete 13 mcu:MKL25ZXX / mcu:SAME5X skip tokens matching no board; carry the
rule table in the module docstring, guarded against drift; and pin six
selection behaviours a mutation pass proved untested.

Cut the selector's cost 1.8x (26.0s -&gt; 14.6s) with 0 divergences over 260
paths, and stop scoping the membrowse upload by the PR example filter.</content>
</entry>
<entry>
<title>examples: document and work around the i.MX RT and LPC55 USB errata</title>
<updated>2026-08-18T15:07:49Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:02:54Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=19ff2ed615e4a97984aab5551ac8835ead53b9e7'/>
<id>urn:sha1:19ff2ed615e4a97984aab5551ac8835ead53b9e7</id>
<content type='text'>
ERR050101: while an isochronous IN endpoint is active, an IN token addressed to
that same endpoint number on ANOTHER device sharing the host can silently
unprime one of this device's OUT endpoints - control, bulk, interrupt or
isochronous alike. NXP states it cannot be detected by software and raises no
interrupt, so the endpoint simply stops answering and the transfer never
completes.

The workaround is a uniqueness requirement rather than a particular number: the
isochronous IN endpoint must not share its number with any IN endpoint in use on
the bus. One family-wide constant therefore defeats it, since two affected
boards on the same hub then pick the same number and each becomes the other's
aggressor. CFG_TUSB_MIMXRT1XXX_ERRATA_ERR050101 is set only for the parts whose
errata list it - RT1015, RT1020, RT1024 and RT1050, where it is marked no fix
scheduled, plus RT1060 and RT1064 rev A - so RT1010 and the RT11xx family keep
the ordinary number and cannot collide with an affected board beside them.
Several affected boards on one hub can still be given distinct numbers with
-DEPNUM_ISO_IN.

The guard covers every example that has an isochronous IN endpoint: audio_test,
audio_4_channel_mic, uac2_headset, cdc_uac2, usbtest, video_capture and
video_capture_2ch. The video examples move the endpoint only when streaming
isochronously, since the bulk configuration is unaffected, and video_capture_2ch
takes two numbers because it has two streams.

The macro name follows CFG_TUSB_RP2_ERRATA_E2/E4/E15 already in tree, and its
is fixed, and which cannot be told apart at compile time - a way to define it to
0.

device_issues.rst records ERR050101 against every affected part with a link to
each errata sheet, and adds the LPC55S2x USB.3 speed-detection and USB.5
isochronous IN entries, neither of which TinyUSB works around. The branch's
design notes are included under docs/superpowers.

Verified: 340 wedge-free runs on mimxrt1064_evk, which previously wedged within
hours, and the macro resolving to endpoint 0x87 on mimxrt1064_evk against 0x83
on mimxrt1010_evk and stm32f407disco.
</content>
</entry>
<entry>
<title>example(midi2): report device identity in midi2_device</title>
<updated>2026-08-14T18:21:24Z</updated>
<author>
<name>Saulo Veríssimo</name>
<email>sauloverissimo@gmail.com</email>
</author>
<published>2026-08-14T18:21:24Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=3c9e92c60abf3959ef0367f5965b53b2def28d58'/>
<id>urn:sha1:3c9e92c60abf3959ef0367f5965b53b2def28d58</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Enable APM32F0 dependency fetching and CI</title>
<updated>2026-07-25T03:28:29Z</updated>
<author>
<name>Jie Feng</name>
<email>hjf3108@gmail.com</email>
</author>
<published>2026-07-25T03:25:05Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=7b9761f1919014152d3e9ee1aaf203d7fb0e762b'/>
<id>urn:sha1:7b9761f1919014152d3e9ee1aaf203d7fb0e762b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>misc fixes</title>
<updated>2026-07-19T12:38:54Z</updated>
<author>
<name>Jie Feng</name>
<email>hjf3108@gmail.com</email>
</author>
<published>2026-06-18T09:28:49Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=9418aba918d7c4107026c894e863d9ef0ec5db81'/>
<id>urn:sha1:9418aba918d7c4107026c894e863d9ef0ec5db81</id>
<content type='text'>
</content>
</entry>
<entry>
<title>examples now build</title>
<updated>2026-07-19T11:24:40Z</updated>
<author>
<name>Jie Feng</name>
<email>hjf3108@gmail.com</email>
</author>
<published>2026-06-10T10:49:07Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=6e0f455634126e7eba315ebc279e563aefbf5815'/>
<id>urn:sha1:6e0f455634126e7eba315ebc279e563aefbf5815</id>
<content type='text'>
</content>
</entry>
<entry>
<title>dcd_lpc17_40: address review findings in the iso paths</title>
<updated>2026-07-17T17:15:53Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-07-17T10:58:25Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=cb224400931b7fbc3477a87a258c0602092abe6b'/>
<id>urn:sha1:cb224400931b7fbc3477a87a258c0602092abe6b</id>
<content type='text'>
From a second max-effort review of the branch:

- Drop the dead TUSB_XFER_ISOCHRONOUS case in dcd_edpt_open: iso endpoints
  are armed via dcd_edpt_iso_alloc/activate (TUP_DCD_EDPT_ISO_ALLOC is
  defined for this IP), never through dcd_edpt_open, so the case and its
  dd-&gt;isochronous assignment were unreachable and asserted a false
  invariant. Only bulk/interrupt reach the switch now.

- Extend the iso compile gate to the classes that actually arm an iso
  endpoint: DCD_ISO_ENABLED now includes CFG_TUD_BTH (bth_device.c opens
  an iso voice endpoint). Without it a BTH build would compile the iso
  machinery out and fail SET_INTERFACE at runtime.

- Un-skip LPC175X_6X in the usbtest example: it shares dcd_lpc17_40.c with
  LPC40XX verbatim, so the "DCD has no isochronous support" skip reason no
  longer holds. Build-verified for lpcxpresso1769 (previously blocked by
  the skip).

- TU_ATTR_UNUSED on the ep_id_is_iso helper: every caller is under
  #if DCD_ISO_ENABLED, so non-iso builds don't reference it and clang's
  -Wunused-function (fatal in CI) rejected the build — gcc stays quiet.
  Verified with the full lpc17 and lpc40 example sets under arm-clang.

A fifth finding — bounding control_ep_read's PACKET_READY spin with a
timeout — was implemented and REVERTED: a naive 100k-iteration bound fires
on legitimately-slow control reads and intermittently drops the device
(hardware-proven by interleaved A/B testing against the pre-fix binary).
The infinite wait is retained; the read is only reached once out_received/
out_queued signal data is present, so the theoretical IRQ-off hang is not
reachable in practice.

Re-verified on ea4088_quickstart: usbtest 30/30 (repeated) + HIL 14/14.
</content>
</entry>
<entry>
<title>skill: add usb-sniffer — wire-level capture with the ataradov hardware tap</title>
<updated>2026-07-17T10:32:47Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-07-16T07:11:43Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=e5b47c9306471b41bd2d2ecbbe9ea8932028b380'/>
<id>urn:sha1:e5b47c9306471b41bd2d2ecbbe9ea8932028b380</id>
<content type='text'>
Fourth view in the USB debugging toolset (usbmon = host URBs, usb-debug =
host reasoning, usb-target-debug = device firmware, usb-sniffer = what
actually crossed D+/D-). Covers the ataradov/usb-sniffer analyzer:
headless pcapng capture (--speed ls/fs/hs, --fold, --limit self-exit),
Wireshark/tshark analysis recipes, and the wire realities that bite:
downstream broadcast, sniffer self-capture noise, xHCI devnum != wire
address, tap-point-dependent reset visibility (hub choreography anchors),
FS-behind-HS-hub splits. Every recipe hardware-validated on the rig,
including the capture-window floor (a 3 s window provably misses the
enumeration ladder; 3M packets minimum).

Two udev files with distinct audiences, not one:
- examples/device/99-tinyusb-examples.rules (renamed from 99-tinyusb.rules):
  the user-facing rules the examples need — cafe VID access, hidraw, the
  ModemManager blacklist, a couple of board probes. getting_started.rst,
  the webusb_serial README and its source comment point here.
- tools/88-tinyusb.rules: the HIL rig's private probe/analyzer allowlist,
  now with the sniffer (6666:6620 + blank FX2LP 04b4:8613). Installed on
  the rig only; the usb-sniffer skill references it.
</content>
</entry>
<entry>
<title>dcd_lpc17_40: fix stale EP0 out_received, add isochronous support</title>
<updated>2026-07-17T09:48:01Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-07-16T07:11:01Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=36cd9f9f46ca20be907ed57b874d9d1dc7b3bf64'/>
<id>urn:sha1:36cd9f9f46ca20be907ed57b874d9d1dc7b3bf64</id>
<content type='text'>
EP0 control-OUT fix (usbtest 14/21, errno 110/-74): usbd queues the
status-stage OUT ZLP of every control read with buffer=NULL, so the ISR's
`if (out_buffer)` check missed it and marked the arriving ZLP as
out_received instead. The stale flag poisoned the next control-OUT with
data: its first chunk "completed" instantly from an empty EP0 buffer and
the host's real DATA NAKed forever. Track queued transfers with an
explicit out_queued flag and void half-finished control state on a new
SETUP.

Isochronous support (UM10562 12.15.6): 5-word DMA descriptors with
per-packet size memory, buflen/present_count in packets, one packet per
FRAME (no DMARSet/EpIntEn involvement), completion at EOT for both
directions. Details that matter:
- the iso machinery (5th DD word + packet-size memory) is compiled only
  when an iso-capable class is enabled (CFG_TUD_AUDIO/VIDEO/VENDOR), so
  non-iso builds pay nothing: _dcd stays 648 B vs 1032 B with iso
- ISR dispatch keys on the hardware's fixed ep-number/type map
  (ep_id_is_iso), never on dd fields that thread mode rebuilds
- iso OUT honors Packet_valid (bit 16) and prefills the hardware
  writeback slots with 0, so a missed frame counts as 0 bytes instead of
  reading back stale buffer contents as data
- packet count is validated (tu_div_ceil &lt;= ISO_MAX_PACKETS) before the
  DD is touched, so an oversized transfer is refused without leaving a
  serviceable half-built descriptor armed for the frame engine
- dcd_edpt_iso_alloc and iso_activate both enforce the fixed iso endpoint
  numbers (3/6/9/12); classes ignore alloc's return value, so activate
  must not trust it

Un-skip LPC40XX in the usbtest example; tier 4 now enumerates and passes
iso cases 15/16/22/23. cdc_msc_throughput and printer_to_cdc had bulk on
iso-only EP3 (SET_CONFIGURATION failed with -32); add the LPC17/40 EPNUM
block (bulk on EP2/EP5) like other fixed-EP examples.

Verified on ea4088_quickstart: usbtest tier-4 battery 30/30 repeatedly
and the full device HIL suite 14/14 (incl. audio_test iso).
</content>
</entry>
<entry>
<title>test/hil: usbtest fleet enablement, shuffled scheduling, unique PIDs</title>
<updated>2026-07-14T06:22:48Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-07-13T10:53:34Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=e02f93158cc602ba6f20945a187172abf2546718'/>
<id>urn:sha1:e02f93158cc602ba6f20945a187172abf2546718</id>
<content type='text'>
Pool/config:
- record real uids (ra8m1_ek), enable usbtest for espressif s3/p4, then
  park ra6m5_ek and ra8m1_ek in boards-skip (ra6m5's usbtest/MSC traffic
  can kill the uPD720201 host on its ROM firmware; ra8m1 USBHS bring-up
  pending); max32666/nrf54lm20 stay enabled - their MosChip flakiness
  never wedges
- re-enable device/usbtest on HS boards (mimxrt1064, ch32v307) now that
  uPD720201 firmware 2.0.2.6 fixes the command-ring death; mimxrt1015
  stays skipped - its HS battery killed the controller on both ROM and
  2.0.2.6 firmware (board-specific); match the moved host-test bundles
  (f723 &lt;-&gt; rt1064); skip never-passing tests on the new
  nrf5340dk/nrf54lm20dk boards and the detached pico host bundle, each
  documented with a comment

Host-controller quirk gating in usbtest.py (auto-skip, self-heals on a
healthy xHCI):
- MosChip MCS9990 EHCI: case 25 (int-OUT never scheduled, FRINDEX bug)
  and case 11 (unlinked reads complete short/EREMOTEIO)
- Renesas uPD720201 xHCI: firmware-gated. The card must run firmware
  &gt;= 2.0.2.6 (RAM-uploaded - it reverts to ROM on every power cycle):
  on older firmware the command ring dies under unlink stress (a
  Configure Endpoint command stops completing; the hub worker deadlocks
  holding the device lock; only a host power cycle recovers; three
  boards reproduced it). usbtest.py reads the FW version register (PCI
  config 0x6c) and refuses to run at all on older firmware - hil_test
  surfaces that as a failed test with the reason. On current firmware
  the full 30-case battery runs (validated FS+HS: metro_m4, f723,
  f723-DMA all 30/30).

Scheduling (hil_test.py):
- Shuffle each (board, variant)'s test order with a seeded RNG
  (HIL_SHUFFLE_SEED to replay) so usbtest batteries and flash churn spread
  across the timeline instead of convoying on one controller.
- Per-controller usbtest + flash semaphores: HIL_USBTEST_PARALLEL
  (default 4) concurrent usbtest batteries and HIL_FLASH_PARALLEL
  (default 8) concurrent flashes per host controller. Profiled on
  uPD720201 firmware 2.0.2.6 across 8/1..12/8: wall time falls
  22.2/14.3/12.5/10.8 min at usbtest width 1/2/3/4 and plateaus there;
  zero controller errors everywhere; first battery case failures
  (leaf-hub bandwidth stretch) appear at 12/8, and flash width 12 only
  amplifies flasher-hub contention flakes - so 8/4 is the optimum. A
  separate battery-window flash throttle was profiled and dropped.
- Give every example a unique hardcoded USB PID (0x4001-0x4022, usbtest
  keeps 0x4010) instead of the PID_MAP interface bitmap: different
  examples now always re-enumerate back-to-back, even on boards whose
  CPU reset does not drop D+ (WCH CH58x), so the EXAMPLE_PID table and
  same-PID adjacency reordering in hil_test.py are gone; only the
  variant-boundary same-example repeat needs a swap.
- Report matrix: stable columns with the metric-bearing tests pinned
  first (usbtest, cdc_msc_throughput, msc_file_explorer[_freertos]),
  the rest alphabetical.

Fail fast:
- enum wait budget 8 s on the first attempt, 4 s on retries; dfu waits
  are deadline-based so dfu-util's own runtime counts against the
  budget.
  A device-absent failure now costs ~3-5x a passing test (20-30 s)
  instead of 10-30x (47-150 s).
- CI runs hil_test with --retry 1 and no in-run second pass: a broken
  fixture fails the job fast instead of holding the self-hosted runner
  for hours and blocking other PRs' HIL jobs. hil_test still writes the
  .skip sidecar, so a manual re-run attempt only retests what failed.

Review fixes (multi-agent adversarial review of this commit):
- tinyusb_win_usbser.inf: the PID rework moved five CDC examples onto
  even PIDs the INF's odd-only DeviceList never matched (legacy-Windows
  usbser binding) - appended 0x4006/4008/400a/4020/4022 to both lists.
- usbtest example: USBTEST_TIER is now overridable and the descriptors
  and pumps are tier-conditional, so a board whose DCD cannot serve a
  tier lowers it instead of skipping the whole example - RA2A1 (RUSB2
  with no isochronous pipe) builds at tier 3 via its BOARD_ define; the
  host battery follows the tier advertised in bcdDevice. Tier-4 output
  verified byte-identical after the refactor.
- dynamic_configuration's second config derived USB_PID + 11 = 0x4018,
  colliding with net_lwip_webserver - now USB_PID + 0x0100, outside the
  per-example space. tools/check_example_pids.py (pre-commit hook)
  enforces PID uniqueness incl. derived and literal idProduct values.
- usbtest.py firmware gate: matched by device ID (uPD720201/720202,
  both use the 0x6c FW register), and an unreadable version (setpci
  missing/denied) now refuses with its own message instead of
  masquerading as "firmware 0x00000000"; noted the gate is necessary
  but not sufficient (board-specific kills stay per-board skips).
- hil_test: deadline waits use time.monotonic(); multiprocessing
  context pinned to fork (raw semaphores in Pool initargs); flash and
  usbtest permits unified into one fail-closed, exception-safe
  ctrl_permit (unknown controller takes every slot and logs a warning
  instead of silently borrowing slot 0); an all-skipped battery
  reports as skip, not "0/0" failure; slow-body polls (mtp, printer,
  disk read) go through a shared deadline-based wait_until so their
  bodies count against the enum budget; throughput's FS detection
  compares serials case-insensitively like every other walk; a missing
  MSC read-speed line now fails the host msc_file_explorer test
  instead of passing with an empty metric.

Hardening:
- fail fast (15 s) when a driver-registry sysfs write blocks: a wedged
  device otherwise turns every subsequent battery into an unkillable
  D-state writer and silently hangs the whole run
- usb-recover skill: a VM reboot is not a reliable cure (MosChip hubs
  latch up across the PCIe reset); full host power cycle is

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
</content>
</entry>
</feed>
