CDC not responding after large packet

Faced the problem of transferring large arrays via CDC.
For example, when transmitting a binary packet of 4096 bytes, it is accepted, but if you send it a second time, the device returns “IRP USBD_STATUS: USBD_STATUS_CANCELED (0xc0010000)”. Then there are endless attempts to resend the packet and return from the “USBD_STATUS_CANCELED” device. At the same time, TinyCLR does not see an error on the bus, and if such a situation arises, it is not clear how to react to it, because there is no feedback for the program…

Wireshark log:
Wireshark Log. Data starts from 40 frame.

Sample:

        static void Main()
        {
            var usbclientController = UsbClientController.GetDefault();
            var usbClientSetting = new UsbClientSetting()
            {
                Mode = UsbClientMode.Cdc,
                ManufactureName = "Manufacture_Name",
                ProductName = "Product_Name",
                SerialNumber = "12345678",
            };
            var cdc = new Cdc(usbclientController, usbClientSetting);

            var buffer = new byte[65536];
            cdc.DeviceStateChanged += (a, b) => Debug.WriteLine("Connection changed.");
            cdc.DataReceived += (a, count) =>
            {
                if (cdc.Stream.BytesToRead == 0) return;
                var readCount = cdc.Stream.Read(buffer, 0, buffer.Length);
                Debug.WriteLine("Data received:" + readCount);
            };
            cdc.Enable();

            while (cdc.DeviceState != DeviceState.Configured) ;
            Debug.WriteLine("UsbClient Connected");

            while (true)
            { }
        }

I believe the maximum packet size for CDC is 512 bytes. Try breaking up the send into 512 byte chunks.

2 Likes

Perhaps I put it wrong: I mean sending data from a PC to a TinyCLR device. Any terminal program can be used to send from a PC. And each of them can transmit data in its own way.
I’ve tested several of them. Some terminals split data into blocks of 64 or 100 bytes (the endpoint buffer size is exactly 64 bytes).
But TeraTerm and Eltima Serial Port Terminal throw such files in a single piece, loading all the handshake work onto the USB bus. Theoretically, when the USB input buffer is exhausted, the device should inform the host with a NAK token that the packet has been received, but there is nowhere to write - try again. Or NYET token that the next package will not fit. And resume reception when there is free space in the buffer.
Unfortunately I don’t have a hardware USB sniffer or logic analyzer, so I can’t tell exactly what’s going on. Some guesses.
In the description “CDC is typically limited to 64 KBytes/second”. When transferring from these terminals, the speed is 170 KBytes/second.
I am currently writing SCPI protocol. In general, data of this size is not expected. However, I included In-Field Update in the protocol, and this is a transfer of several megabytes. It will not always be possible to restrict the user in choosing a terminal or writing his own implementation.

Any ideas?

P.S .: By the way, when the same implementation receives data via UART at a speed of 921600 baud/second (90 KBytes/second), everything is accepted perfectly.

We have created an issues on GitHub to look into this

1 Like

OK. If you need more information, then tell me.

1 Like