Closed jhbe closed 3 years ago
Hi.
Tried to build and test your code. I built and upload usbtest-device.axf
then built and run usbtest-host
.
Can't reproduce the problem.
Setup:
From my experience, if your device has a strange behavior, check the device power first for unexpected spikes and drops.
Huge thanks for trying the code!
Swapped the USB cable for another and powered the device from a bench power supply; no change.
I did notice that, with constant power to the device, it was enough to pull the USB cable and put it back in again on the PC side to get the device to enumerate and send another few hundred strings before it failed as before. What does libusb_stm32 do the the cable is pulled and put back in? Something is clearing some state somewhere...
In general, the STM USB HW engine doesn't support a special disconnect event, so no special actions performed when the cable unplugged. When you plug the cable, the host will issue "BUS RESET" first and the USB engine will be resetted and reconfigured.
I also noticed that longer packets fail quicker. 64 bytes packets fail after ~100 transactions. 5 byte packets last for ~4000 transactions. 4 byte packets never fails. Almost smells like a FIFO problem.
Is there any device or EP status register that I can check for STALL/HALT or whatever is causing this?
Checked with a logic analyzer on the bad transaction.
Really, i don't understand WTF is going on. Why It issues BAD_CRC in the middle of the packet.
This is the normal transaction.
Looks like this is a false EOP (see chapter 8.7.3 USB2.0) but why? And why I see no similar with CDC loopback demo at heavy load.
/dev/ttyACM1: count for this session: elapsed=2030 sec, rx=1231213440, tx=1231224832, rx err=0
/dev/ttyACM1: transfer rate rx=606509 cps, 4852072 bps, tx=606514 cps, 4852112 bps.
/dev/ttyACM1: TIOCGICOUNT: ret=0, rx=0, tx=0, frame = 0, overrun = 0, parity = 0, brk = 0, buf_overrun = 0
I found a possible root cause of this issue. Since your code uses USB interrupt for the events and async USB EP write call in the main thread, a conflict with shared access to the USB registers may be possible. I just disabled IRQs till the writing finished and see no more errors on the bus.
I'll try that! What's the correct way of disabling and re-enabling the interrupt?
I used this code for the test.
__disable_irq();
usbd_ep_write(&usbdDevice, EP1_IN, buffer, 40);
__enable_irq();
This is not a good idea to disable all interrupts, it was done just for the test. I think you need to redesign the code to avoid switching to OTG_FS_IRQHandler
when usbd_ep_write()
in progress.
OTG_FS_IRQ
for a time orusbd_poll()
to the main thread and don't use this interrupt, orusbd_ep_write()
to the interrupt routine.USB_OTG_GINTSTS_SOF was the one interrupt that came in while I was writing AND it came in just as the pipe broke. When I define USBD_SOF_DISABLED, the problem goes away. I can't say I understand why; we only clear the interrupt bit and move on...
Is the problem that we are writing to a register while writing (like you said) or is it a SOF issue?
I think this is the hardware internals. For example, writing to GINTSTS or maybe other registers when pushing to the EP FIFO not yet completed will break a correct writing sequence and may corrupt an internal state. And when you disabled SOF you reduced the probability of this error but did not exclude.
Closing this issue. The workaround (disable interrupt white writing or write from the interrupt scope) works. Thank you so much for your help @dmitrystu , you have written an excellent stm32 USB library!
My F405 firmware sends bytes over a BULK IN endpoint to a PC every 10ms. If it send more than four bytes, then after a few hundred successful sends the USB pipe stops with a PROTOCOL_ERROR; see the attached pcap file line 470. This was captured on a Debian 10 host. The device is a Matek F405STD board.
I'm using the usbd_stm32f429_otgfs "driver". The otgfs BULK endpoint is not in a stalled state, according to ep_isstalled(). The device is not stuck. The protocol error is sent to the host exactly when I would expect the normal byte transfer to take place, so it seems the call to usbd_ep_write() caused the condition. My EP1 size is 64, as is my EP0.
I am at a loss as to what to look at next, please advise. The device and host code can be found here.