Main Site Documentation

UART Receive Dropped Data...Can you replicate?


#1

I have the UART Com2 setup with RTS handshake. I am sending data from a host to the Usbizi at 115200 baud. Upon sending large datasets (>50K) the Usbizi appears to dump its buffers and stop firing the recieve event in the middle of the transfer. No errors and nothing noted in the debug…just stops. The UART remains open and functioning after this, but its just not allowing all the data to pass. The handshake is working as I can see the RTS/CTS pins working using portmon and the data is being throttled. No data loss occurs up to the point in time that the transfer stops.

I replicated this on my Rhino and Domino boards using the following stripped down code. If you remove the Thread.Sleep(100) it does not appear to have a problem processing all the data, but even a sleep of 10ms will cause this issue. The dropping of the data does not always occur after the same number of bytes. Sometimes its ~40K, others more or less. Longer Thread.Sleep of 1 second or more does not appear to affect where in the transfer it decides to stop.

The GC runs normally and memory is well in check. Here is a dump in the middle of the transfer:

GC: 2msec 13764 bytes used, 50616 bytes available
Type 0F (STRING ): 108 bytes
Type 11 (CLASS ): 1200 bytes
Type 12 (VALUETYPE ): 36 bytes
Type 13 (SZARRAY ): 396 bytes
Type 15 (FREEBLOCK ): 50616 bytes
Type 17 (ASSEMBLY ): 8736 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 24 bytes
Type 1B (DELEGATE_HEAD ): 216 bytes
Type 1D (OBJECT_TO_EVENT ): 72 bytes
Type 1E (BINARY_BLOB_HEAD ): 288 bytes
Type 1F (THREAD ): 768 bytes
Type 20 (SUBTHREAD ): 96 bytes
Type 21 (STACK_FRAME ): 816 bytes
Type 27 (FINALIZER_HEAD ): 96 bytes
Type 31 (IO_PORT ): 108 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 684 bytes



using System;
using System.Threading;
using System.IO;
using System.IO.Ports;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;

namespace FEZ_Rhino_Application1
{
    public class Program
    {

        static SerialPort sp;
        static int tot = 0;

        public static void Main()
        {

            sp = new SerialPort("COM2", 115200, Parity.None, 8, StopBits.One);
            sp.Handshake = Handshake.RequestToSend;
            sp.Open();

            sp.DataReceived += new SerialDataReceivedEventHandler(OnRecvUARTData);
            sp.ErrorReceived += new SerialErrorReceivedEventHandler(OnUARTError);

            Thread.Sleep(Timeout.Infinite);

        }

        static void OnUARTError(object sender, SerialErrorReceivedEventArgs e)
        {
            Debug.Print("UART Error:" + e.EventType.ToString());
        }

        static void OnRecvUARTData(object sender, SerialDataReceivedEventArgs e)
        {

            int count = 0;
            Thread.Sleep(100);
            byte[] data = new byte[sp.BytesToRead];
            count = sp.Read(data, 0, data.Length);
            tot += count;
            Debug.Print(tot.ToString());
     
        }

    }
}


Any ideas? I tried moving to data processing to another thread and not use the Receive event, but it had no effect.

Thanks -AP


#2

Why the sleep? When you get the data event get the bytes that are ready and exit.


#3

The sleep is simulating work that would be done in my app. I just created this as an example using the sleep for others to see.


#4

Best not to do a lot of processing in event handler. Move data to a queue and process in separate thread.

Doing a sleep in an event handler may cause funny things to happen.

At high data speeds may be overflowing internal com buffers.


#5

Correct, even handlers shouldn’t be a place to do processing or sleep.


#6

nuf said. I appreciate the handler is not the place to do heavy processing, but let me tell you what I am ultimately trying to do and you might be able to point me in the right direction…

So, I basically have about 25K to work when my app is running normally. I use the UART to receive a file that gets put on to an SD card. Just the overhead of writing to the SD card is enough to cause this issue descrbied earlier. The thread.sleep was just a way to demonstrate.

If I write directly to the SD in the Receive event I have this issue. If I offload this processing to another thread by queing the data in a separate buffer, there is sometimes not enough memory to keep me from running out while the SD card is writing.

I know I could make a protocol such as ZModem, but I was trying to avoid slowing th transfer down.

Can you point me to a queing strategy that would work? I was hoping the Hardware handshake would be enough to deal with this, but apperantly there are some other buffers filling up? Buffers that I can not see?


#7

Use double buffering for SD data. When you fill the first buffer, set an auto reset object, which will wake up the SD writing thread. While the first buffer is being written, fill the second buffer.

The buffers should be multiples of 1024. You can play with the buffer size for best performance.

First you should work on tuning your SD write to get the speed you need. This will help determine the size of the borders. You should not run out of memory.


#8

Nice, thats a much cleaner way to do it for sure. So I implemented a double buffer, then tried a FIFO buffer. I still had the issue. I set the Debug.EnableGCMessages(false); so I could clean up my output window and would’nt you know it…the problem disappeared. I turned GC messages back on and the problem came back.

What does this mean?

-AP


#9

Ah! The debug messages must be causing a delay in the system. At your high data rate it was enough to cause an overflow.

Read about the “observer principle”.


#10

Yea, I remember that now from Physics class.

Still frustrating me however…removing the GC messages certainly helped, but as soon as I added the write operation back for the SD card the problem surfaced again. I guess I can keep banging my head against a wall or do what I did late last night after giving up…I bought a Cobra. Sometimes a good substitute for coding patience is more memory :slight_smile:

-AP


#11

How fast have you been able to write to the SD? You should not be losing data.


#12

I have played around with a lot of different chuck sizes, but I can write 8k of data to the SD card in about 375ms and that includes flushing it. I don’t think its so much the time it takes to write to the SD as it is there is some negative effect on the ability of the UART receive event to populate the buffer that the SD uses to write data with. The SD write routine is on a separate thread and I have tried using both FIFO and double buffering techniques.

Again, if I remove the SD stream write operation the UART can receive all the data and report that to the debugger. If I use the same code but just include a stream write operation on a separate thread then the UART will not process all the inbound data.

Please note that I incorrectly stated earlier that there is no data loss up to the point that the data transfer stops. This is not the case. Data loss occures during the data transfer and results in not all the bytes of data getting transferred. The amount of data loss and the timing of the missing packets are not clear, but it seems to be after the first ~10k of data and its about a 20% loss.

-AP