Closed elagil closed 1 year ago
Interesting, these Stall EP0
shouldn't happen. Have you tried stock example without modification ?
Have you tried other classes ?
Seems like caused by newly added tu_memcpy_s
https://github.com/hathach/tinyusb/blob/34798ff85ec819bafc09da57f7853a1d116a7fff/src/class/audio/audio_device.c#L2293
Just tested the HID composite example, works fine.
[17504.035119] usb 1-1.3: new full-speed USB device number 27 using xhci_hcd
[17504.324266] usb 1-1.3: New USB device found, idVendor=cafe, idProduct=4004, bcdDevice= 1.00
[17504.324282] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[17504.324294] usb 1-1.3: Product: TinyUSB Device
[17504.324305] usb 1-1.3: Manufacturer: TinyUSB
[17504.324316] usb 1-1.3: SerialNumber: 123456
[17504.429244] input: TinyUSB TinyUSB Device Keyboard as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:CAFE:4004.0001/input/input8
[17504.488030] input: TinyUSB TinyUSB Device Mouse as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:CAFE:4004.0001/input/input9
[17504.488482] input: TinyUSB TinyUSB Device Consumer Control as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:CAFE:4004.0001/input/input10
[17504.488772] input: TinyUSB TinyUSB Device as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/0003:CAFE:4004.0001/input/input11
[17504.489058] hid-generic 0003:CAFE:4004.0001: input,hidraw0: USB HID v1.11 Keyboard [TinyUSB TinyUSB Device] on usb-0000:01:00.0-1.3/input0
and the log output: hid_log.txt
I tried your suggested fix in https://github.com/hathach/tinyusb/pull/1852#issuecomment-1455102835, but it runs into an assertion in dcd_dwc2.c:658
:
if(dir == TUSB_DIR_OUT)
{
// Calculate required size of RX FIFO
uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count);
// If size_rx needs to be extended check if possible and if so enlarge it
if (dwc2->grxfsiz < sz)
{
>> TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4);
// Enlarge RX FIFO
dwc2->grxfsiz = sz;
}
Here, for the rhs value, _dwc2_controller[rhport].ep_fifo_size = 1280
, so the rhs value is 320.
For the lhs value sz = 411, _allocated_fifo_words_tx = 16
, so 427.
Thus, it fails.
I tried your suggested fix in https://github.com/hathach/tinyusb/pull/1852#issuecomment-1455102835, but it runs into an assertion in dcd_dwc2.c:658
I think F411's USB FIFO is not enough for high-res format like 24bit/96kHz, could you try to reduce sample rate/bit res like how #define __RX__
did in tusb_config.h
and main.c
?
So, I just added #define __RX__
which changes the point at which it locks up. It now runs into the default
case of handle_rxflvl_irq
with pktsts == 11
and hangs at TU_BREAKPOINT()
in dcd_dwc2.c:1085
.
By the way, it's an F401.
However, I don't see as many stalls. There are three: changes_log.txt
The log suddenly stops when I hit TU_BREAKPOINT()
.
In Windows, the device is even detected correctly, but I can't play sound. It will jump into the TU_BREAKPOINT()
immediately.
Edit: Sometimes, I can play a bit of sound. Then it fails after a short while. I guess it is somehow FIFO related.
Another piece of information: The STM32F401 has the same total FIFO size as all the other F4 series parts, namely 1280 bytes for the full speed port. It shouldn't be too small then. Could it be that the device is too slow in emptying the FIFO buffer? I only run at 48 MHz SYSCLK.
I tested the 4-channel microphone example, and it somewhat works (only with your fix, replacing sizeof(...)
).
Two channels show a sawtooth, two are empty. Also, I had to drastically increase the level of the sawtooth, otherwise it appeared to be zero.
I increased the dataVal
increment from 1 to 200.
// Generate dummy data
for (uint16_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++)
{
uint16_t * p_buff = i2s_dummy_buffer[cnt]; // 2 bytes per sample
dataVal = 1;
for (uint16_t cnt2 = 0; cnt2 < AUDIO_SAMPLE_RATE/1000; cnt2++)
{
for (uint8_t cnt3 = 0; cnt3 < CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; cnt3++)
{
*p_buff++ = dataVal;
}
dataVal+=200;
}
}
@hathach
I think there is an issue in dwc2 Rx FIFO allocation.
In uac2_headset
example the max Rx packet size is 24(96+1) = 776 which can be hold in 1280 bytes FIFO.
However calc_grxfsiz(776, 4)
will return 411 which is larger than FIFO size.
At least 2*(max_ep_size/4)
seems wrong.
which is larger than FIFO size.
since this is in units of 32 bit words, right?
It says in the F401 reference manual:
Program the OTG_FS_GRXFSIZ register, to be able to receive control OUT data and setup data. If thresholding is not enabled, at a minimum, this must be equal to 1 max packet size of control endpoint 0 + 2 words (for the status of the control OUT data packet) + 10 words (for setup packets).
I don't see the calculation matching this, but it was probably derived from a different reference manual.
There is more in the source code, which cites the reference manual (I don't know which): https://github.com/hathach/tinyusb/blob/34798ff85ec819bafc09da57f7853a1d116a7fff/src/portable/synopsys/dwc2/dcd_dwc2.c#L191
Edit: I just checked. In the headphone example, calc_grxfsiz
is called with
max_ep_size = 64
ep_count = 4
55
Latest testing with completely unchanged firmware was seemingly successful. I changed the debugger!
I can even start up the device in 96 kHz mode
But, at 96 kHz, it fails during use, at dcd_dwc2.c:658
, which seems to be expected.
if(dir == TUSB_DIR_OUT)
{
// Calculate required size of RX FIFO
uint16_t const sz = calc_grxfsiz(4*fifo_size, ep_count);
// If size_rx needs to be extended check if possible and if so enlarge it
if (dwc2->grxfsiz < sz)
{
>>> TU_ASSERT(sz + _allocated_fifo_words_tx <= _dwc2_controller[rhport].ep_fifo_size/4);
// Enlarge RX FIFO
dwc2->grxfsiz = sz;
}
dwc2->epout[epnum].doepctl |= (1 << DOEPCTL_USBAEP_Pos) |
(desc_edpt->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) |
(desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) |
(xfer->max_size << DOEPCTL_MPSIZ_Pos);
dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum);
}
At 48 kHz, it plays fine, but I did not do long-term testing. I have to get the data out via I2S first, for actually listening.
Does not seem to be quite reliable yet, it does run into the same TU_BREAKPOINT()
sometimes.
Seems stable during operation now, but I am hitting a new issue. See https://github.com/hathach/tinyusb/issues/1949
Prerequisites
I want to use an STM32F401 as a UAC2 sound card. For that, I start with the
uac2_headset
example.Operating System
Linux
Board
Custom, based on STM32F401RBT. I tested the ST USB stack (Audio device) on it, and it works as expected.
Firmware
My firmware is custom, and based on STM32CubeMX. It builds as a simple Makefile project.
The following steps were taken to include the tinyusb library and build it:
tinyusb
as a submoduledcw2
component, as I understand that it supports the STM32F401Sources
Includes
osThreadId_t usbTaskHandle; const osThreadAttr_t usbTask_attributes = { .name = "usbTask", .stack_size = USBD_STACK_SIZE, .priority = (osPriority_t) osPriorityHigh, };
int main(void) { // Other initialization usbTaskHandle = osThreadNew(usbTask, NULL, &usbTask_attributes); // ... }
void usbTask(void *argument) { tusb_init();
while (true) { tud_task(); } }
usb_descriptors.c
andusb_descriptors.h
are taken without changesmain.c
in a separate file. Find it here: https://github.com/elagil/usb-uac2/blob/main/Core/Src/audio_main.c. The callbacks are called without issues, as I can see with my debugger. For example, I stepped into thetud_audio_clock_get_request()
, and I can see that it reaches the point where it transfers the supported sample rates.tusb_config.h
is located here: https://github.com/elagil/usb-uac2/blob/main/Core/Inc/tusb_config.h. Debugging is enabled, as well as the device configuration for the OTG FS port. Most importantly, I setand
BOARD_TUD_MAX_SPEED = OPT_MODE_FULL_SPEED
in the Makefile. This resolves correctly.The full code is here: https://github.com/elagil/usb-uac2/. My implementation is located in
Core/Src
andCore/Inc
.What happened ?
On a linux machine, the USB device connects, but fails to report its capabilities (sample rate, volume range). See the
dmesg
output below:Find the log below.
How to reproduce ?
Debug Log as txt file
I don't see anything obvious in the log output, logged at level 3. Most notably, the requested capabilities (sample rates, volume ranges) are reported fine here. They just don't make it to the PC.
log.txt
Screenshots
No response
I have checked existing issues, dicussion and documentation