usb_audio: refill the mic FIFO from tud_audio_tx_done_isr() - #11195
Conversation
TinyUSB services audio transfer completions in ISR context, so they never queue a USB event. On ports that pump the optional class tasks from a task loop sitting behind tud_task() (espressif), tud_task() blocks on a permanently empty queue and usb_audio_task() never runs. The mic FIFO is filled once, drains in a few frames, and the device emits zero length packets until the host gives up. Refill from tud_audio_tx_done_isr() instead, which TinyUSB invokes from the transfer complete path. usb_background_schedule() uses background_callback_add(), which is ISR safe and already called from usb_irq_handler() on other ports. No port changes are needed. Also enable usb_audio by default on esp32s3. The descriptor is gated on usb_audio_enabled(), so compiling it in claims no endpoints until enable() is called from boot.py. Tested on Metro ESP32-S3 and Metro ESP32-S2.
tannewt
left a comment
There was a problem hiding this comment.
Thank you! Not sure why some board builds are failing though.
|
Six of them use a CH340C or CP2102 serial chip instead of native USB, so |
a55558c to
1fb4196
Compare
tannewt
left a comment
There was a problem hiding this comment.
This is going to make it really confusing to have one place seemingly set it and the global force it off. Instead, make the port-level setting conditional on the other USB settings. Generally more specific settings should override general ones global > port > board.
The port-level default for esp32s3 now checks the settings usb_audio needs, so a board that turns off the TinyUSB device stack or audiocore keeps it off. Six S3 boards use a CH340C or CP2102 serial chip and set CIRCUITPY_USB_DEVICE = 0, and adafruit_esp32s3_camera sets CIRCUITPY_AUDIOBUSIO = 0, which leaves CIRCUITPY_AUDIOCORE at 0 since the S3 has no AUDIOIO or AUDIOPWMIO.
1fb4196 to
faa9d77
Compare
|
Moved it into the port setting, so Checked with |
Jumped in on a usb_audio PR# 11102 that @relic-se @FoamyGuy had been working on. This is to add ESP32-S2 and S3 usb_audio support. It already worked on
RP2040, RP2350 and nRF52840. On ESP32 the device enumerated as a correct UAC2
microphone, the host opened the stream, and then nothing came out.
I put a Cynthion on the bus to see what the host was actually doing. It was
behaving perfectly:
arecord -d 4The host polled every 1 ms for 578 ms and only then gave up. Nothing was corrupt.
The device sent 8 real frames and then zero length packets for the remaining 565.
TinyUSB handles audio completions in the ISR, so they never wake
tud_task(). Onespressif the class tasks run after
tud_task(), so they never run either and theFIFO is filled once.
tud_audio_tx_done_isr()is TinyUSB's hook for exactly this,and refilling from there needs no port changes.
Also here:
CIRCUITPY_USB_AUDIO ?= 1on esp32s3, which claims no endpoints untilenable()is called. esp32s2 stays off by default.S2 and S3 allow five IN endpoints including EP0 and the default build uses all
five, so one has to be freed:
Tested on Metro ESP32-S3 and Metro ESP32-S2 against this branch.
writes 384044 bytes on both.