Replies: 8 comments 9 replies
-
|
Digging deeper - and using a different session decode window ('Line View') shows that the application writes a block of 3365 bytes, then polls for completion (see excerpt below) in the CP2102 session:
I definitely don't have a 4K buffer in the MCU (and later in the CP2102 sequence a 16K block transfer occurs), so unless USB parcels the block into significantly smaller packets (and then uses XON/XOFF or some protocol to throttle delivery), this may be the source of my problem. |
Beta Was this translation helpful? Give feedback.
-
|
The CP2102 has the same issue (640 byte Tx buffer, and 576 byte Rx buffer), so clearly there is some mechanism for USB to parcel & throttle... |
Beta Was this translation helpful? Give feedback.
-
|
I need to better understand USB protocol. Clearly, the data is not copied if there is no room in the FIFO, but all that happens is the endpoint is released. Shouldn't a flag be set to ensure the packet just received is NAK'd so the host will retry? If so, how is this accomplished? Or is the NAK triggered elsewhere somehow? |
Beta Was this translation helpful? Give feedback.
-
|
From your description I think there are some problem about how did you integrate TinyUSB into your project, especially how did you handle hardware UART transmit when data received from USB host. Without more information is hard to know what happened, please provide at least your MCU/moard, minimal source.
It's fully handled by TinyUSB, you could try cdc_msc example and compare data written and data echoed. |
Beta Was this translation helpful? Give feedback.
-
|
So what I think would happen is:
|
Beta Was this translation helpful? Give feedback.
-
|
@mws-rmain which board/mcu you are testing with, this info should always be presented in each issue/discussion. Each port will behave differently, but most user often forget this. hardware endpoint will always NAK if not having any data queued up. There is zero chance tinyusb won't send NAK. You should look at other direction to troubleshoot this. If the issue occur with preempted rtos and/or multiple core mcu with fast enough data rate, there is a high chance it is a race. I just fixed an hard to find one with nrf52 If you are certain it is a bug/race you could open an issue for it, make sure you add your own minimal example based on stock example (such as cdc_msc) to make sure we all testing the same firmware on the same hardware. Don't forget the steps/software to reproduce it. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the response, @hathach. My implementation is a CDC device, so for packet reception to an OUT endpoint the NAK should occur when a packet is received that the device cannot accept at the current time (i.e. the FIFO has no room for another packet). Since the FIFO is defined as 64 bytes, and the maximum packet size is 64 bytes, this will occur until the FIFO is empty. During my investigations, I found that SAM D21 processor has a mechanism defined to NAK a packet when the device is not ready, which is NOT being used by the TinyUSB device driver. I could not find any mention of 'default NAK' or 'implicit NAK' behavior. Specifically, in the SAMD21 Family Datasheet (DS40001882G), section 32.6.2.7 'Management of OUT Transactions', states: TinyUSB does implement explicit STALL condition handling (usbd.c:1341, usbd_edpt_stall()) which manipulates the STALLRQ# bits in EPSTATUS register (dcd_samd.c:287, dcd_edpt_stall()), but I can't find any similar explicit handling of the NAK condition (which should be manipulating the BK#RDY bit in the EPSTATUS register). TinyUSB does implement a 'busy' routine (usbd.c:1331, usbd_edpt_busy()), but this only sets internal flags - it does not call down to MCU specific functions - and it is not used at all by the CDC device. I don't have a USB bus analyzer to verify it, but I believe TinyUSB CDC device will just fail to ACK the packet (i.e., the RED path in the image below, instead of the GREEN path), and the (windows USB) HOST driver may (by default) retry the packet anyway, and keeps doing so until all packets of a large block transfer are complete. If this is the case, the end result will be the same (all packets transferred), although there might be some side effects, such as unnecessary delays, etc. Since I have something working, I'm moving ahead on my project. If you feel this is something that should be flagged for investigation, I can add it as an issue & document as suggested (please let me know). |
Beta Was this translation helpful? Give feedback.
-
|
I'd certainly like to correct course if I'm navigating down the wrong path! |
Beta Was this translation helpful? Give feedback.



Uh oh!
There was an error while loading. Please reload this page.
-
I'm having problems using the TinyUSB CDC device as a replacement for a hardware USB UART. I've found that communication begins fine, in both directions (Tx & Rx), but it seems the TinyUSB CDC implementation is missing a few features that cause ultimate communication failure.
I'm using a serial port monitor program ( https://www.eltima.com/products/serial-port-monitor/ ) to capture & compare communications from a standard application (bootloader app running on Windows 10) on one board that uses a CP2102 USB-Serial converter, compared to another board that uses a MCU running a TinyUSB CDC instance (which maps to a hardware UART in the MCU). The serial monitor highlights several differences early on (IOCTL_SERIAL_GET_/SET_ CHARS/HANDFLOW, UP & DOWN). The main difference looks like XonLimit=32768, XoffLimit=8192 in the IOCTL_SERIAL_GET_HANDFLOW, which is zero under TinyUSB.
Also, in IOCTL_SERIAL_SET_TIMEOUTS (UP) ReadTotalTimeoutConstant=300, WriteTotalTimeoutConstant=300.
After numerous exchanges involving the above IOCTLs, the session trace shows a significant difference. The CP2102 configuration sees a large block of IOCTLs (SERIAL_GET/SET TIMEOUTS, WAIT_MASK, BAUD_RATE, LINE_CONTROL, CHARS, etc.), which is missing in the TinyUSB/MCU session trace. I can supply the session traces if it helps, but the (non-free) program would be required to read them.
I can't be sure, but I suspect the issue is lack of XON/XOFF support in TinyUSB. Do you have any plans to add this, or could you point me to required info to implement? I know TinyUSB supports DTR/RTS for down-stream flow control, but I don't see any implementation for up-stream flow control (e.g., DSR/CTS). For that matter, I don't know how you'd go about 'stalling' USB transfers if the MCU UART FIFOs were full anyway. XON/XOFF is another way to handle up & down-stream flow control, so might (?) be easier to implement.
Beta Was this translation helpful? Give feedback.
All reactions