<feed xmlns='http://www.w3.org/2005/Atom'>
<title>tinyusb.git, branch fix-ci-hs</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.</subtitle>
<id>http://cgit.235523.xyz/tinyusb.git/atom/?h=fix-ci-hs</id>
<link rel='self' href='http://cgit.235523.xyz/tinyusb.git/atom/?h=fix-ci-hs'/>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/'/>
<updated>2026-08-18T13:51:21Z</updated>
<entry>
<title>examples: document and work around the i.MX RT and LPC55 USB errata</title>
<updated>2026-08-18T13:51:21Z</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=895f77f5534230f0264de881554f89cf6f66a506'/>
<id>urn:sha1:895f77f5534230f0264de881554f89cf6f66a506</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>bsp(lpc55): run lpcxpresso55s28 as a high-speed device, add it to the ci pool</title>
<updated>2026-08-18T13:51:21Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:02:39Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=2eaafa9d90c3fe1942e2633998767a4c87d2e6de'/>
<id>urn:sha1:2eaafa9d90c3fe1942e2633998767a4c87d2e6de</id>
<content type='text'>
Flip the board to device-highspeed/host-fullspeed, matching lpcxpresso55s69
and the way it is cabled on the test rig, and add it to the rig pool with
the unique id read from its flash PFR. This is the first hardware coverage
the ip3511 high-speed device path has ever had, and it immediately exposed
the clear-stall type-bit bug fixed separately.

The port swap also exposed a build gap: family.mk only linked a host
controller for port 1, so make host builds on port 0 failed with undefined
references - mirror family.cmake and link the OHCI driver there. The board's
rhport defaults now come from family.cmake's guarded ones rather than a
duplicate copy, so a -D override on the command line wins.
</content>
</entry>
<entry>
<title>bsp(lpc11u37): move the main stack to the USB SRAM bank</title>
<updated>2026-08-18T13:51:21Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:02:38Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=840e9a917a8a110878e1bce9d731888261172292'/>
<id>urn:sha1:840e9a917a8a110878e1bce9d731888261172292</id>
<content type='text'>
The 8 KB main bank is packed tightly enough that only ~280 bytes remained above
.bss, and interrupt frames overflowed into the topmost task stack - a hard fault
in cdc_msc_freertos. Put the MSP at the top of the 2 KB USB SRAM bank, which
nothing else uses in either build system, so the stack no longer shrinks as .bss
grows. The Make build's CFG_TUSB_MEM_SECTION placement of endpoint buffers into
that bank is dropped so both build systems agree on the layout.

The headroom assert is written as an addition rather than a subtraction, since
linker script arithmetic is unsigned and an overflowing bank would underflow the
difference into a huge positive value and pass silently.
</content>
</entry>
<entry>
<title>dcd(ip3511): fix DEVCMDSTAT write-1-to-clear handling and EP0 setup races</title>
<updated>2026-08-18T13:51:21Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:02:22Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=8e9db1d1a37b221a055c1c8621e5ee430ccdac14'/>
<id>urn:sha1:8e9db1d1a37b221a055c1c8621e5ee430ccdac14</id>
<content type='text'>
DEVCMDSTAT mixes read/write fields with write-1-to-clear latches, so a blind
read-modify-write writes a pending latch back as a one and silently clears it -
a setup consumed that way strands EP0. Mask the latches on every update.

The setup path follows the manual's order: acknowledge the latch, then read the
payload. The EP0 IN interrupt is cleared along with EP0 OUT, as the control
endpoint flowchart requires - a control IN completion latched before the setup
must not reach usbd after it, where it would be applied to the request the setup
just started and arm its status stage early.

The payload is copied a byte at a time out of a buffer now declared volatile:
the controller DMAs a new setup packet into it as soon as the latch is cleared,
and C orders volatile accesses only against each other, so gcc sinks a plain
memcpy below the guard read that follows at -O2 and -O3 - leaving only -Os, the
level CI builds, correct.
</content>
</entry>
<entry>
<title>usbd: handle a refused transfer without halting, and report it</title>
<updated>2026-08-18T13:51:21Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:02:07Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=1576aba0e7e2f3c833b6ef157fa7aebc1faa5500'/>
<id>urn:sha1:1576aba0e7e2f3c833b6ef157fa7aebc1faa5500</id>
<content type='text'>
A refused transfer is a recoverable condition - a new setup superseding a
control response, for instance - rather than a bug, but every failure path
treated it as one. TU_ASSERT carries TU_BREAKPOINT, which is gated on a debugger
being attached rather than on CFG_TUSB_DEBUG, so on a rig where a probe is
always attached it halted the CPU even in release builds. Use TU_VERIFY on the
control transfer paths, including the multi-packet data stage continuation, and
drop the breakpoint from the endpoint transfer failure arm, which already marks
the endpoint ready again so the next transfer can proceed.

The result of usbd_control_xfer_cb() was separately dropped on the floor,
leaving EP0 neither armed nor stalled and nothing recorded. It is logged now,
and deliberately not stalled: a DCD refuses an EP0 prime when a newer setup is
already latched, and EP0 stalls are cleared by hardware when that setup arrives,
so a stall issued here would land after the auto-clear and stall the transfer
that superseded this one. The pending setup re-drives EP0 by itself.
</content>
</entry>
<entry>
<title>dcd(ci_hs): rework bus reset handling and bound the register waits</title>
<updated>2026-08-18T13:51:21Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:01:54Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=d0574784936e5c40a88850d32d2cfd2fdc7246df'/>
<id>urn:sha1:d0574784936e5c40a88850d32d2cfd2fdc7246df</id>
<content type='text'>
A bus reset was detected only from the port change that ends it, which is late:
the manual asks the DCD to clear the endpoint semaphores, cancel every prime and
free the dTDs while the reset is still being driven. Enable the reset interrupt
and do all of that there, in the manual's order (IMXRT1060RM 42.5.6.2.1,
p.2394), including the two steps that were missing - confirming the port is
still being reset, and freeing the dTDs. A failed check means the cleanup
arrived late and the controller may be in an undefined state, so the manual's
remedy is carried out rather than noted: a controller reset, followed by the
full re-initialisation it then requires, since the reset detaches the device.

The port change that ends the reset is left with what the manual gives it, the
negotiated speed, which the new BUS_RESET_END event carries. A port change is
classified by the interrupt that preceded it: a suspend raises no port change of
its own, the resume that ends it does.

Every unbounded register spin is now bounded. They waited on bits the hardware
clears within a frame, but each could hang an interrupt handler outright on a
controller that had stopped responding. The endpoint flush follows all three
steps of IMXRT1060RM 42.5.6.6.5 (p.2413), repeating a flush the controller
refuses while a packet is in progress - previously reported as success.

EP0 setup handling is hardened alongside: the payload is copied out of the queue
head through the volatile qualifier before ENDPTSETUPSTAT is cleared, since that
clear releases the setup lockout and a back-to-back setup can overwrite the
buffer immediately after, and C orders volatile accesses only against each
other, so a plain memcpy may legally be sunk past the store.

There is deliberately no unplug detection. IMXRT1060RM 42.7.31 (p.2470) states a
zero Current Connect Status means the device "did not attach successfully or was
forcibly disconnected by the software writing a zero to the Run bit ... It does
not state the device being disconnected or suspended", so a cable pull raises no
port change at all; VBUS via OTGSC is the manual's disconnect indicator and is
board dependent.

Verified on mimxrt1064_evk: 30 forced bus resets each re-enumerating at high
speed with no descriptor errors, plus repeated full usbtest batteries at 30/30
across the series.
</content>
</entry>
<entry>
<title>usbd: split bus reset into start/end edge events</title>
<updated>2026-08-18T13:51:21Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-16T18:01:37Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=073942589355676980ba401cb88c0eb9f065e468'/>
<id>urn:sha1:073942589355676980ba401cb88c0eb9f065e468</id>
<content type='text'>
A driver that can see reset signalling begin has no way to say so: the only
event carries the negotiated speed, which does not exist until the reset
ends. On ChipIdea that left the stack believing it was still configured for
the whole reset window - 3 ms at minimum, tens of milliseconds in practice -
while the controller had already torn its endpoints down, so a class driver
writing in that window primed a disabled endpoint over a zeroed queue head.

Add DCD_EVENT_BUS_RESET_START for the leading edge and rename the existing
event to DCD_EVENT_BUS_RESET_END, keeping DCD_EVENT_BUS_RESET as an alias.
START is optional and END stays self-sufficient, so every other driver and
the unit tests are untouched.
</content>
</entry>
<entry>
<title>Merge pull request #3829 from hathach/claude/read-doc-calibre-db</title>
<updated>2026-08-18T11:07:05Z</updated>
<author>
<name>Ha Thach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-18T11:07:05Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=af7d199e73461c25555abbdc72441ab79eb74245'/>
<id>urn:sha1:af7d199e73461c25555abbdc72441ab79eb74245</id>
<content type='text'>
read-doc skill: search the document library's database instead of the filesystem</content>
</entry>
<entry>
<title>skill(read-doc): search the Calibre database instead of the filesystem</title>
<updated>2026-08-18T09:58:58Z</updated>
<author>
<name>hathach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-18T08:28:58Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=f59c8948729debc6d57c4dfade5486176468edbf'/>
<id>urn:sha1:f59c8948729debc6d57c4dfade5486176468edbf</id>
<content type='text'>
Finding documents by walking the library tree misses anything the filename
does not carry - Calibre stores only a truncated title and the author there, so
the tags, series, publisher and description that hold most part numbers and
errata IDs are invisible to it. A zero-result tree search then reads as "the
document does not exist" rather than as a bad search; that happened here, and
led to a confident claim that a fully populated 14,000-file library was empty.

search.py queries metadata.db, ANDs its keywords across every metadata field
(including the stored filename), and prints the best matches first with the
exact path to read. Matching is NFKC + casefold, so a typed ASCII apostrophe or
mu reaches the titles that store the typographic ones.

Every printed path is checked on disk. Calibre renames &lt;author&gt;/&lt;title&gt; (&lt;id&gt;)
when metadata is edited and leaves the old directory behind, so a miss retries
by the stable book id before reporting MISSING - which distinguishes "the file
is not here right now" from "no such document". The gate tests for metadata.db
rather than the directory, since an unmounted or half-synced mountpoint is
still a directory.

Consumers that prescribed their own tree search - driver-reviewer, port-dev,
the driver-review workflow, and the calibre-library references in CLAUDE.md,
usbtest, etm-trace and target-debug - now point at the skill, which owns the
library's location.
</content>
</entry>
<entry>
<title>Merge pull request #3803 from hathach/claude/hil-wedge-containment</title>
<updated>2026-08-18T07:33:01Z</updated>
<author>
<name>Ha Thach</name>
<email>thach@tinyusb.org</email>
</author>
<published>2026-08-18T07:33:01Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/tinyusb.git/commit/?id=11bdbc3eac085e4a946e25a8a614bcbf62e41fa2'/>
<id>urn:sha1:11bdbc3eac085e4a946e25a8a614bcbf62e41fa2</id>
<content type='text'>
hil, ci: contain a wedged USB stack instead of stranding the runner</content>
</entry>
</feed>
