I am implementing a C# application which reads binary data from a microcontroller at a high baudrate (8 MegaBaud) using an USB-Serial adapter (FTDI FT232H). The problem is when the stream contains 0x1A, sometimes a big chunk of data (thousands of bytes) is lost after this byte.
I found on the forums that 0x1A is a special character (EOFCHAR) and Windows is doing a special handling for this. However this solution of decompiling SerialStream
and changing EOFCHAR
to another byte value doesn't help me, I need to use the entire byte range (0..255).
I created a small test application to reproduce my problem, sending repeatedly the same byte, using 2 serial adapters connected to the same computer and FT232R-TX connected to FT232H-RX
using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.Text;
namespace SerialPort_0x1A_Loss_Test
{
class Program
{
static void Main(string[] args)
{
const byte BYTE_FILL = 0x1A; // 0x1A is EOFCHAR
const int BAUD_RATE = 3000000; // 3 MegaBaud
const int BUFF_SIZE = 1000000;
SerialPort sp1_FT232R =
new SerialPort("COM3", BAUD_RATE, Parity.None, 8, StopBits.One);
SerialPort sp2_FT232H =
new SerialPort("COM6", BAUD_RATE, Parity.None, 8, StopBits.One);
sp1_FT232R.Encoding = Encoding.GetEncoding(1252);
sp1_FT232R.WriteBufferSize = 20000000;
sp1_FT232R.Open();
sp2_FT232H.Encoding = Encoding.GetEncoding(1252);
sp2_FT232H.ReadBufferSize = 20000000;
sp2_FT232H.ReceivedBytesThreshold = 20000000;
sp2_FT232H.Open();
byte[] bufferTx = new byte[BUFF_SIZE];
for (int i = 0; i < BUFF_SIZE; i++)
{
bufferTx[i] = BYTE_FILL;
}
Console.WriteLine("Sending ...");
sp1_FT232R.Write(bufferTx, 0, BUFF_SIZE);
Console.WriteLine("Sending finished. " +
"Press a key to view status, ESC to exit.");
// Receiving maybe not yet finished,
// query the status with a keypress
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
Console.WriteLine("TOTAL RX = " + sp2_FT232H.BytesToRead);
}
// A second test, using .Read() call
// This will be executed after pressing ESC for the previous test
int totalRX_Read_Call = 0;
var listBufferRx = new List<byte>();
int btr; // BytesToRead
while ( (btr = sp2_FT232H.BytesToRead) > 0)
{
var bufferRx = new byte[btr];
totalRX_Read_Call += sp2_FT232H.Read(bufferRx, 0, btr);
listBufferRx.AddRange(bufferRx);
Console.WriteLine("totalRX_Read_Call = " + totalRX_Read_Call +
"; listBufferRx.Count = " + listBufferRx.Count);
}
Console.ReadKey();
sp1_FT232R.Close();
sp2_FT232H.Close();
}
}
}
Test results (BUFF_SIZE = 1000000 for all tests):
1. BYTE_FILL = 0x55; BAUD_RATE = 3000000; TOTAL RX = 1000000 ( no loss)
2. BYTE_FILL = 0x1A; BAUD_RATE = 3000000; TOTAL RX = 333529 (66% loss)
3. BYTE_FILL = 0x1A; BAUD_RATE = 2000000; TOTAL RX = 627222 (37% loss)
4. BYTE_FILL = 0x1A; BAUD_RATE = 1000000; TOTAL RX = 1000000 ( no loss)
Also, the load on the CPU (i7-4770k at 4 GHz) is high (over 30%) for tests like 2, 3, 4, but low (3%) for test 1. For test 1, I tried with all other patterns for a byte (0x00..0x19, 0x1B..0xFF) and there is no loss.
Do you know if there is a solution for this? Thank you very much!