Main Site Documentation

USBC_CDC 64 bytes issue


#1

When writing 64 byte buffer to CDC serial port, it does not send anything to other side. Less or greater then 64 bytes works fine. Is 64 a magic number somehow? Internal buffer size or something? tia


#2

We always appreciate a small program demonstrating the issue :slight_smile:


#3

I was hoping you did not say that :slight_smile:
Problem is, your program is never simple when you run into these issues. I will have to do a min app, but it will just be sending (or not sending) a 64 byte[].


#4

99.9% of the times we see these cases is because of a bug in the user code so once we ask for a small program to show the issue they quickly find the bug and fix it in their code.

…plus if it turned out to be a bug on our side, we get you a fix in very short time…sometimes withing hours since you already showed us where the problem is :wink:

This seem to workout for everyone :slight_smile:


#5

I don’t think it is on our side.
Our example sends “Hello World” every second. That is a lot less than 64.


#6

Mike,

William said it worked with less then 64 and more then 64 bytes, but not with exactly 64 bytes. I guess you read his post wrong.


#7

oh…If this is true, this is something we have look into. When the PC receives 64 bytes exactly, it may think that there are more bytes coming and waits for them…
What are using on Windows? Different serial port drivers may treat this differently. So try other programs, like try TeraTerm, Hyper terminal…etc


#8

It seems as if the Fez side is not sending any bytes if the write buffer is 64 bytes exactly. The client side times out and can not even read 1 byte and the BytesToRead buffer on the client says 0.
So it ~looks like a Fez side write buffer issue, but it could be some strange confluence of the two sides. The driver on both sides is the new CDC driver. hth

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.USBClient;

namespace Test64Serial
{
    public class Program
    {
        static USBC_CDC port;

        public static void Main()
        {
            port = InitCDC();

            // Read 1 byte.
            byte[] readBuf = new byte[1];
            int read = port.Read(readBuf, 0, 1);
            Debug.Print("Fez: Read bytes: " + read);

            // Write 64 bytes.
            byte[] buf = new byte[64];
            try
            {
                int write = port.Write(buf, 0, buf.Length);
                Debug.Print("Fez: Wrote bytes: " + write);
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
        }

        private static USBC_CDC InitCDC()
        {
            Debug.Print("Hit Break All in VS to reattach debugger to port, then F5/Continue.");
            USBC_CDC port = USBClientController.StandardDevices.StartCDC_WithDebugging();
            port.ReadTimeout = -1; // Block waiting for chars.
            port.WriteTimeout = 3000;

            while (true)
            {
                if (USBClientController.GetState() != USBClientController.State.Running)
                {
                    Debug.Print("Waiting to connect.");
                    Thread.Sleep(600);
                }
                else
                {
                    Debug.Print("CDC comm port connected: ");
                    break;
                }
            }
            return port;
        }
    }
}

// Windows Side - Send 1 byte and try to read 1 byte.
private void button1_Click(object sender, EventArgs e)
{
    SerialPort port = new SerialPort("COM18", 9600, Parity.None, 8, StopBits.One);
    port.ReadTimeout = 3000;
    port.Open();

    // Write 1 bytes.
    byte[] writeBuf = new byte[]{1};
    port.Write(writeBuf, 0, 1);
    Console.WriteLine("Client: Wrote bytes: " + writeBuf.Length);

    // Try read 1 byte.
    byte[] buf = new byte[1];
    try
    {
        int read = port.Read(buf, 0, buf.Length);
        Console.WriteLine("Client: Read bytes: " + read);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        Console.WriteLine("Bytes to read: " + port.BytesToRead);
    }
}

#9

The PC thinks that more data is expected so it is waiting… This only happens when you send a multiple of 64 bytes.
Use this method to write data for now. We will fix it for next release.


public static int USBC_CDC_Write(USBC_CDC cdc, byte[] buffer, int offset, int count)
{
    int retVal = cdc.Write(buffer, 0, buffer.Length);

    if ((retVal > 0) && (retVal % 64 == 0))
    {
        USBC_Stream s = (USBC_Stream)(typeof(USBC_CDC).GetField("stream", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cdc));
                
        int i = (int)(typeof(USBC_Stream).GetField("streamIndex", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(s));

        byte[] dummy = new byte[0];

        typeof(USBClientController).GetMethod("Write_Helper", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { i, dummy, 0, 0 });
    }

    return retVal;
}


#10

Hey. Thanks Mike!


#11

Just in case, that code goes into production, there is 1 changed needed.

Change first line to below. As written, it ignores the args passed.

int retVal = cdc.Write(buffer, offset, count); //(buffer, 0, buffer.Length);