Rule: Fossil is the one and only arbiter of bench state. This file is the committed truth of the physical rig; update it in the same commit as any change that depends on the rig, and record findings in ticket comments. (Historical wiring recipe for the dogfood era: wiring.md.)
Last verified: 2026-08-23 night (0530 field-fix session; roster read
back live by top_fat32_test/top_0530drive). This board doubles as the
inspin bench (the self-hosted IDE lives in flash; harness tops are
RAM-loaded and a reset returns the board to inspin).
Active rig
- PropPlug P97gfytf (active since 2026-08-09; plugs P81svj44 and P7lrax5w are also attached to this machine — do NOT use for USB tests; older docs naming P81svj44 are historical).
- Build/run pattern:
pnut-ts -d -I ../src -D <gates> top_x.spin2thenpnut-term-ts --headless -r top_x.bin -p P97gfytf -b 2000000 --end-marker "<MARKER>". Logs land in./logs/beside the binary. - Default/validated clocks: 300 MHz (user default, storage validated,
ticket 1140) and 200 MHz. ALWAYS run
harness/top_txpat.spin2at any new clock or after any PHY change (TX gap is bit-period-scaled).
USB headers
| Header | LED | EN (VBUS) | D− | D+ | Bus |
|---|---|---|---|---|---|
| Serial host 1 | 16 | 17 | 18 | 19 | 0 |
| Serial host 2 | 20 | 21 | 22 | 23 | 1 |
- EN pins are active-high and FLOAT HIGH through P2 resets/downloads — port power persists across downloads; drive low to kill it.
- Z J-detector lies on a dead bus: reads J even unpowered/floating (hardware-proven 2026-08-09). J can never arbitrate attach/power; K has no such false positive.
- DS3231 RTC on I2C SCL=38 SDA=39 (chip clock set ~1 year ahead; jm_ds3231/jm_i2c vendored in harness/, do not modify).
Current plug map (2026-08-13 night)
- Bus 0 (base 16): 7.5 GB FAT32 thumb
$ABCD:$1234(now 'P2THUMB') DIRECT — the bus-0 root, single leaf. This is the 0530 field-drop specimen (the inspin bench drive): NAKs address-0 probes while booting, has wedged silent mid-session.top_rootplugP2–P5 run against it; EN 17 cuts its power programmatically. With EN low the bus reads SE0 (the device's pull-up dies with VBUS) — the floating-J note below applies to an EMPTY header, not to an attached-unpowered device. Its FAT was found CROSS-LINKED 2026-08-24 (files opened to other files' content) after sessions of mid-write resets;harness/top_mkfs32.spin2rebuilt the filesystem in place (label P2THUMB, 16 KB clusters). It still GC-crawls: multi-second NAK spans on writes and occasionally on reads - every USB op is bounded now, but a long file operation against it can honestly take minutes. Treat it as the flaky-storage specimen it is. - Bus 1 (base 20): Genesys hub
$05E3, 4 ports- p1: FTDI FT232R
$0403:$6001 - p2: FTDI FT-X
$0403:$6015— the inspin target PropPlug (second P2 load link) - p3: Logitech Unifying receiver
$046D:$C52B - p4: Sony DualShock 4
$054C:$09CC
- p1: FTDI FT232R
- Off-bench: dock combo ($0BDA root + PL2586 inner hub + $14CD reader
- Billboard + RTL8153), CM108 audio (loopback jumper still on it), Alicat FT-X, UTEK FT4232H, PL2303 HXD/TA, ASMedia SSD.
Device/quirk ledger (bench-proven; keep with the hardware they describe)
- $14CD:$1212 card reader #1: PHYSICALLY BROKEN (2026-08-11) — NAK-crawl/E_IO/STALL that survive power cycles. Out of rotation; treat nothing it did as driver evidence.
- $5E3:0751 reader: failing SD data lines (sense B/47/01 on every read at every LBA; capacity/TUR fine). Retired 2026-08-13.
- Vintage 32 MB card: DEAD (ACKs writes, discards them). Retired.
- ASMedia SSD: torn-write abuse wedges it into states that survive
PORT power cycles — recovery is FULL hub power-off ~3 s
(
top_1140clean.spin2;top_hubcycle.spin2= fast EN cycle). - SSD asserts hub-port connect ~6–9 s after hub power (same late-assert class as the new SanDisk).
- Old SanDisk
$0781:$5581: dead, removed 2026-08-11. - Flash holds a known-good community USB host driver: manual P2 reset (no download) boots it and re-enumerates — operator recovery path.
SECOND BOARD: P81svj44 — the 6000-QA regression rig (added 2026-08-25)
Dedicated board for the FAT32/USB regression mission (ticket df56b8e563). prompt.md pins this project to plug P81svj44 — do not run 6000-QA work on the inspin board above, and do not run inspin work here.
- PropPlug P81svj44; machine also shows P97gfytf (inspin board, above)
and Pa7hxvxs (unassigned); P7lrax5w is gone.
### Plug map as of 2026-08-25 midday (read back live by
top_rig_probe)
A powered 4-port Genesys hub $05E3 now sits at header 16, addr 1, and
carries all four storage devices. Every device below was identified read-only
(harness/top_rig_probe.spin2 rev 2 — mounts and lists, releases with
fs_abandon(), writes nothing). Log:
harness/logs/headless_260825-111804.log.
| Hub port | Device | Serial | Capacity | FS | Geometry |
|---|---|---|---|---|---|
| 1 | ASMedia $174C:$A89A SSD |
2L192LQ5ANU9 |
2 000 409 264 LBA (≈953 GiB) | exFAT, label P2SSDxf |
256 sec/clus (128 KB), heap LBA 65 536 |
| 2 | thumb $ABCD:$1234 |
2605191439082106343731 |
15 728 640 LBA (7.5 GB) | FAT32, label NO NAME |
64 sec/clus (32 KB), first data sec 3 904, align 0 |
| 3 | thumb $ABCD:$1234 |
2605191420212074960925 |
15 728 640 LBA (7.5 GB) | FAT32, label P2T4K |
8 sec/clus (4 KB), first data sec 30 728, align 0 |
| 4 | thumb $ABCD:$1234 |
2604192343393382809328 |
15 728 640 LBA (7.5 GB) | FAT32, label P2T4KOFF |
8 sec/clus (4 KB), first data sec 30 725, align 5 |
Ports 3 and 4 were reformatted on 2026-08-25 with harness/top_mkfs32.spin2
(operator-approved; both volumes were empty as received) because all three
thumbs arrived with geometry IDENTICAL to the old bench thumb, which would have
made the P1 ladder a redundancy test rather than new path coverage. The three
FAT32 volumes now differ deliberately:
- port 2 — 32 KB clusters, aligned. Untouched control; matches every result recorded before today, so a regression here is a real regression.
- port 3 — 4 KB clusters, aligned. Small clusters mean ordinary test files
span MANY clusters, so
compactFile/defrag and the A9 FAT pre-load paths actually execute. The 32 KB thumb never made them run. - port 4 — 4 KB clusters, cluster_offset 5. The data area starts five
sectors off the cluster grid. This is the first bench media ever to have a
nonzero cluster alignment, i.e. the first live exercise of the
entryOffsetInClustersign fix (commita359d54149), which until now was covered only by reasoning.
The formatter now SOLVES the reserved-sector count for a requested alignment
rather than accepting whatever falls out of the partition layout (the first 4 KB
attempt landed on alignment 4 by accident of plba=32 and a 15 330-sector FAT).
Geometry on a regression rig has to be stated, not discovered.
- The original wedge-canary thumb is NOT on this rig. Its serial is
2604180728561454082814; none of the three present match. The ~10–11k READ(10) firmware wedge threshold in the device ledger below belongs to THAT stick and must not be assumed of these three until measured. - All three thumbs are geometrically IDENTICAL to the old bench thumb
(64 sec/clus, first data sector 3 904, cluster alignment 0) and all three
roots are empty (raw root-sector confirmation: slot 0 marker
$00). The entry-offset sign fix (a359d54149) and the A9 multi-cluster compaction paths therefore still have NO live coverage from this media as delivered — reformatting is required to get it (ticket 059e2970 P1). - HUB PER-PORT POWER WORKS as a real detach/attach — but it does NOT cure
every wedge. Read both halves of this before planning around it.
- What is proven (
harness/top_hubrecover.spin2, logheadless_260825-112123.log; re-verified bytop_6070detach): CLEAR_FEATURE(PORT_POWER) takes the port status from$0000_0103to$0000_0000, the device leaves the roster, and SET_FEATURE brings it back in ~0.3–3.2 s at a new bus address, which is proof the device actually restarted. It cleared the SSD's transient BOT state. - The 2026-08-25 "dead thumbs" were NOT dead, and not a media fault at all
— see ticket
7516223d(6090). After a heavy 4 KB-cluster defrag run the thumbs on ports 3 and 4 stopped enumerating, survived P2 reboots, and did not come back from port power cycles at 3 s or 15 s. The operator reseated the hub and all four devices returned and mounted perfectly. The cause was ours: the hub had DISABLED those ports (USB 2.0 11.5.1.4, after a protocol error from a device left mid-BOT-transaction) — port status$0002_0101: CONNECTED, POWERED, not ENABLED,C_PORT_ENABLEset — andrescan()examined only CONNECTION and C_PORT_CONNECTION, so it never saw it. A disabled port passes no traffic and only a PORT RESET re-enables it; power cycling cannot. Reproduced in 16 s byharness/top_wedgewatch.spin2. - Read every earlier "the device stopped answering ep0" note in this file and
in ticket 6080 with that in mind:
rst=0 clrO=0 clrI=0is what a disabled port looks like from the host, not necessarily a dead device. - 6090 is FIXED AND VERIFIED ON HARDWARE (2026-08-25 evening, log
headless_260825-151925.log). The disable reproduced at op 25 and ordinaryusb.poll()alone recovered it in 3.1 s:DISABLED BY THE HUBfired, port 3 went$0002_0101→$0000_0103, the device left the roster at addr 4 and re-enumerated on the same port at addr 6, then remounted and round-tripped a 32 KB multi-cluster file verified by content. A disabled port is no longer a bench-ending event.
- What is proven (
- THE TWO WEDGE CLASSES ARE REAL AFTER ALL — but tell them apart by the PORT,
never by the recovery signature. 6090 correctly demolished the reasoning
behind the old two-class note; re-measuring it on 2026-08-25 evening with the
confound gone establishes it properly:
- Class A — the hub disabled the port. Port reads
$0002_0101(not ENABLED). All three recovery control transfers fail (rst=0 clrO=0 clrI=0) because nothing crosses a disabled port. Self-healing since 6090, in about 3 s, with no operator action. - Class B — the device's mass-storage state machine is wedged, port
healthy. Port reads
$0000_0103(CONNECT+ENABLE+POWER) throughout. Signaturerst=0 clrO=1 clrI=1(logheadless_260825-152111.log): both CLEAR_FEATURE(ENDPOINT_HALT) requests succeed, so ep0 is alive and the device answers standard requests — only the class-level Bulk-Only Mass Storage Reset fails. NOT recoverable by any software rung. The full ladder was walked on both wedged ports (headless_260825-153155.log): re-probe, bare port reset (never tried before 6090 exposedhub_port_reset()), 3 s power cycle, 15 s power cycle — all four fail, and the two power cycles are loggedrecycle -> 1, i.e.hub_port_recycle()confirmed PORT_POWER actually cleared and the device re-connected. A device that survives a verified 15 s VBUS removal is holding state no host-side action can reach. Only a physical hub reseat clears Class B. - The discriminator is the ENABLE bit, and only the ENABLE bit. Judging by
the
rst/clrO/clrItriple is what cost 2026-08-25 an afternoon.
- Class A — the hub disabled the port. Port reads
- A device that returns from a port power cycle re-enumerates at a NEW BUS
ADDRESS (measured: thumb 3→6, then 4→7; SSD 2→7). Address is not a name.
Match media by serial; see
usb_app.drive_select_sticky()(ticket 6070). - Both $ABCD:$1234 thumbs wedged mid-format under sustained write load
(2026-08-25, LBA 9 765 of the second back-to-back format on serial
...960925):BOT csw fail op=$2A hs=$D2 rxn=0— the device ACKed the CBW and went silent — and the MSC layer's inline BOT recovery then failed at the CONTROL level (rst=0 clrO=0 clrI=0), i.e. ep0 stopped answering too. This is the SAME firmware wedge the ledger records for the original canary thumb, on a DIFFERENT unit: it is the model's firmware, not one bad stick.drive_recover()(hub port power) is the cure;top_mkfs32now carries one such retry. - The SSD's first read after an exFAT mount failed once with
BOT data fail op=$28 hs=$D2and the MSC layer's inline BOT recovery ALSO failed (rst=0 clrO=0 clrI=0), latching "CBWs refused". A P2 reset cleared it and the same four LBAs then read fine, so it is transient, not a persistent wedge — but the recovery-failure path is real and unexplained.
Original single-leaf configuration (superseded 2026-08-25 midday)
- USB header at base 16 (LED 16, EN 17, D− 18, D+ 19), bus 0, single leaf, no hub. VBUS is NOT switchable on this board (proven + operator- confirmed 2026-08-25): EN 17 held LOW 10 s leaves the stick's D+ pull-up standing — every programmatic VBUS recycle is a no-op here, and recovery from a device wedge is a PHYSICAL replug. begin()'s VBUS-rescue rungs cannot help on this rig. Header 20–23 present but EMPTY. The socket-24 position was tried for the stick on 2026-08-25 and is electrically dead for USB — begin() ladders, EN sweeps (23/24/25/26/28/29 both polarities) and line watches all found no pull-up; the stick's LED never lit there. Stick lives at header 16, where its LED lights and it enumerates instantly.
- Media: "fresh" 7.5 GB thumb
$ABCD:$1234, serial2604180728561454082814— PC-formatted FAT32: labelNO NAME, 64 sec/clus (32 KB clusters), first data sector 3 904, cluster alignment 0 (both degenerate-case-safe for the entry-offset sign issue, commit a359d54149), 15 728 640 LBAs. Root as received: BOOKS/, TOOLS/, TRASH-~1/. NOT the old P2THUMB (that one: label P2THUMB, 32 sec/clus, GC-crawler, on the inspin board). - Clock for suites: 200 MHz (
_CLKFREQin tests/regression tops); runharness/top_txpat.spin2before trusting a new clock on this board. - Regression estate 2026-08-25 (after A5/A6/A8 backports): 142/142 — fatchain 2, write_integrity 13, read_write 49, subdir_ops 18, seek 38, multihandle 22 (logs in tests/regression/logs/).
- Device ledger — $ABCD:$1234 stick firmware hard-wedge (proven by reproducers, ticket 6030/3d99c25528, Fixed): the stick's firmware hangs (CBW-ACK-then-silence, then NAK-everything; ONLY a physical replug recovers) after ~10-11k single-sector READ(10)s per power session — ~6 full-FAT scans of this volume. Root cause on our side was freeSpace()'s per-call full-FAT scan storm, eliminated 2026-08-25 (FSInfo-tracked count; freeSpaceRescan() for audits). Post-fix the full 13-suite ladder runs on one power session with zero wedges. Treat any recurrence as a new 6030-class finding, not noise.
Low-speed campaign state (tickets 1210 closed / 1190 open)
- The old mouse (direct on base 20) is the local LS specimen.
- Proven 2026-08-13 (
top_lsprobe, commit29b27b759c): smart pin J/K detector is speed-aware; complete LS control transfer (GET_DESC@0 →$12 $01 $00 $02 …mps0=8, ACK'd status). Speed is currently GLOBAL to the PHY — no mixed FS+LS operation; see ticket 1190 for the remaining Phase A work list.