Skip to content

x4prosim: USB-CDC host always looks plugged in - #3

Merged
prokrypt merged 2 commits into
prokrypt:x4prosimfrom
serialx:ext/usb-cdc-sof
Oct 9, 2026
Merged

prokrypt merged 2 commits into
prokrypt:x4prosimfrom
serialx:ext/usb-cdc-sof

Conversation

@serialx

@serialx serialx commented Oct 9, 2026

Copy link
Copy Markdown

Anything that attaches a host program to the USB-CDC console (CrossPoint's debugging_monitor.py / device_control.py over -chardev pty) got truncated writes from the guest: a 52 KB SCREENSHOT reply arrived as exactly 256 bytes. Nothing in the firmware is wrong; the USB Serial/JTAG model let IDF's plug watchdog decide the cable was out.

Cause

IDF's usb_serial_jtag plug watchdog clears the SOF status bit in every FreeRTOS tick hook and declares the host gone after five hooks that found it clear. The model only set that bit from its 1 ms SOF timer. Under -icount QEMU runs several ticks inside one virtual millisecond when timer deadlines bunch up, so the bit went missing often enough that Arduino's HWCDC marked the link down and routed writes through its 256-byte ring, dropping the rest.

Change

hw/misc/esp32s3_usb_jtag.c (one file, shared by the S3 and C3 machines):

  • The SOF status bit always reads as set in INT_RAW / INT_ST and is OR'd into the IRQ line. Unplugging isn't modeled; the model already assumed a host was present.
  • FRAM_NUM follows virtual time (qemu_clock_get_ms & 0x7ff) instead of the timer's own count, so the watchdog's frame-number comparison sees progress even when the main loop lags.
  • The 1 kHz SOF interrupt stays as it was.

X4PROSIM.md gains a note on driving the console from a host script: give it a pty (-chardev pty,id=cdc, QEMU prints the path on stdout) and point the monitor at that path.

Verified

CrossPoint develop plus the serial-device-control branch on -machine x3, console on a pty, driven through the branch's own monitor and device_control.py:

  • Before: screenshot payload stops at 256 bytes, SCREENSHOT_END still arrives, every capture fails the same way.
  • After: 35 screenshots in one boot, 0 retries, ~0.5 s each, and a 28-step scenario (Home, Browse Files, reader page turns, reader menu, hold/cancel, Settings, Library) completes on one boot with no reset.

Both qemu-system-riscv32 and qemu-system-xtensa build; the X4 Pro path is the same file and the same bit, but I had no X4 image to re-run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01T57W7AZf7tgmkuDMMSaWwz

serialx and others added 2 commits October 9, 2026 12:32
IDF's plug watchdog clears the SOF status bit in every FreeRTOS tick hook
and declares the host gone after five hooks that found it clear; Arduino's
HWCDC then routes writes through its 256-byte ring and a 52 KB screenshot
over the serial-control protocol arrived as 256 bytes. QEMU can run several
ticks within one virtual millisecond, so a SOF bit that only came from the
1 ms timer went missing often enough. The SOF status bit now always reads
as set and the frame counter follows virtual time; the 1 kHz SOF interrupt
stays. Unplugging isn't modeled.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T57W7AZf7tgmkuDMMSaWwz
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T57W7AZf7tgmkuDMMSaWwz
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@prokrypt
prokrypt merged commit 8e7d9de into prokrypt:x4prosim Oct 9, 2026
12 checks passed
@serialx
serialx deleted the ext/usb-cdc-sof branch October 9, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants