Main Site Documentation

CDC sending issue


#1

Hi all,

well i have been searching the forum and found quite some cdc issues / quirks, but no real solution for the problem we are facing over here now. My colleague has changed our code to be able to do debugging and use a virtual serial port through the usb connection. Works almost ok… It is receiving and sending data on the cdc. Butt… some of the data that we are sending doesn’t get send correctly. It only sends about half of the data and then everything becomes quiet. If we check the string for the amount of bytes that we are going to send it is around 49500 bytes and it only send 21300. I have read the posts about the issues with 64 bytes and tried the solutions provided there, but that doesn’t help. Anybody else has got this problem?

Regards,

Per


#2

We are not aware of any issue like you are describing.

Make a very small test app that only has CDC and test it out, it could be a bug somewhere in your code?


#3

Hi gus,

this is the code we use. We pass a string that holds xml data, If i print the string to the debug window and then paste it in my xml editor then it is also shown complete. If i pass the same string to a procedure that writes to a real serial port (from which the code is the same, since the writes are compatible) then it works just fine.

Regards,

Per

using System;
using System.Collections;
using System.Text;
using System.Threading;
using GHIElectronics.NETMF.USBClient;
using Microsoft.SPOT;

namespace VMC3.Classes.Connections
{
    public delegate void MessageFunc(string value);
    public delegate void Action();

    public class CDC_Driver
    {
        public event MessageFunc MessageReceived;
        public event Action Stopped;
        USBC_CDC port;
        int isRunning = 0;
        bool _Use_USB_Debugging = false;

        public bool IsRunning
        {
            get { return isRunning == 1; }
        }

        public bool Use_USB_Debugging
        {
            get { return _Use_USB_Debugging; }
            set
            {
                _Use_USB_Debugging = value;
            }
            

        }

        public void Start()
        {
            if (Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
            {
                InitCDC();
            }
        }

        public void Stop()
        {
            if (Interlocked.CompareExchange(ref isRunning, 0, 1) == 1)
            {
                USBClientController.Stop();
                MessageReceived = null;
                Debug.Print("USB Virtual com port Stopped.");
                var ev = Stopped;
                if (ev != null) ev();
            }
        }

        /// <summary>
        ///Start the CDC (virtual comm) port on the current debug session.
        ///This will stop the current session and restart with a new driver which will create the dual channel.
        ///To reattach debugger channel, you need to hit "Break All" and then Continue. You should then have
        ///a new V-Comm port on the PC and a comm port on the fez.
        /// </summary>
        private void InitCDC()
        {
            Debug.Print("Hit Break All in VS to reattach debugger to port, then Run Continue.");
            if (_Use_USB_Debugging == true)
            {
                //Virtuele com poort + usb debugging aanmaken
                port = USBClientController.StandardDevices.StartCDC_WithDebugging();
            }
            else
            {
                //Alleen virtuele com poort aanmaken
                port = USBClientController.StandardDevices.StartCDC();
            }

            //port.ReadTimeout = -1; // Block waiting for chars.

            while (true)
            {
                if (USBClientController.GetState() != USBClientController.State.Running)
                {
                    Debug.Print("waiting to connect.");
                    Thread.Sleep(600);
                }
                else
                {
                    Debug.Print("CDC connected.");
                    break;
                }
            }
            // Start read loop on new thread.
            new Thread(ReadLoop).Start();
        }

        private void ReadLoop()
        {
            isRunning = 1;
            while (isRunning == 1)
            {
                string line = ReadLine(); // Blocking call.

                var ev = MessageReceived;
                if (ev != null)
                {
                    ev(line);
                }
                
                Thread.Sleep(200);
            }
        }

        /// <summary>
        /// Simple loop that reads single chars until delim byte
        /// and returns the string. We could improve perf by reading more chars per read.
        /// </summary>
        /// <returns></returns>
        private string ReadLine()
        {
            //Read and buffer chars until a newline char.
            ArrayList line = new ArrayList();
            byte[] buf = new byte[1];
            int count = 0;
            while ((count = this.port.Read(buf, 0, 1)) > 0)
            {
                //if (buf[0] == delim)
                //break;
                line.Add(buf[0]);
            }

            //Convert ArrayList to char[] using UTF8 encoding.
            byte[] bytes = new byte[line.Count];
            for (int i = 0; i < bytes.Length; i++)
                bytes[i] = (byte)line[i];

            char[] chars = Encoding.UTF8.GetChars(bytes);
            return new string(chars);
        }

        /// <summary>
        /// We write messages, not lines, using delim and message marker.
        /// </summary>
        /// <param name="message"></param>
        /// <returns>Number of bytes written.</returns>
        public int WriteMessage(string message)
        {
            if (message == null) throw new ArgumentNullException("message");
            if (this.isRunning != 1) return 0;

            // Write reply appending newLine delim.
            byte[] buffer = System.Text.UTF8Encoding.UTF8.GetBytes((char)1 + message + (char)4);
            this.port.Write(buffer, 0, buffer.Length);

            return buffer.Length + 1;
        }
    }
}

#4

Yes I understand you see a problem but we need to narrow it down which requires having a small app that only tests CDC, no XML, nothing else that is not absolutely needed.


#5

Hi Gus,

i will create a small test app tomorrow (my workday is over now :slight_smile: ) that passes a long string to the function.

Regards,

Per