Windows serial port data lost
-
Hi,
I send data from USB full speed CDC ACM device (USB serial port, bulk endpoint with packet size = 64 bytes) to Windows 10 Qt app.In Qt app on QSerialPort's readyRead signal I do serialPort->readAll(). When the transfer rate is > 64 kB/s I can see some 64 byte long chunks of data (which is size of the bulk packet) were dropped. It happens when Qt thread is busy (e.g. when I move the window so it is forced to redraw).
QSerialPort has unlimited read buffer set.
Is there anything I can do with this issue?
-
Hi,
I send data from USB full speed CDC ACM device (USB serial port, bulk endpoint with packet size = 64 bytes) to Windows 10 Qt app.In Qt app on QSerialPort's readyRead signal I do serialPort->readAll(). When the transfer rate is > 64 kB/s I can see some 64 byte long chunks of data (which is size of the bulk packet) were dropped. It happens when Qt thread is busy (e.g. when I move the window so it is forced to redraw).
QSerialPort has unlimited read buffer set.
Is there anything I can do with this issue?
@MartinD said in Windows serial port data lost:
I do serialPort->readAll()
This is the problem, readyRead is emitted when some data is available not when all data is available. use QDataStream. for example, assuming you are getting 32bits signed integers from the port, in the slot connected to readyRead() use:
DataStream serialStream(serial); qint32 singleValue; for(;;){ // keep reading for as long as there is data serialStream.startTransaction(); serialStream >> singleValue; if(serialStream.commitTransaction()) qDebug() << "received: " << singleValue; else break; //stop when you tried to read more than you received }
-
@MartinD said in Windows serial port data lost:
I do serialPort->readAll()
This is the problem, readyRead is emitted when some data is available not when all data is available. use QDataStream. for example, assuming you are getting 32bits signed integers from the port, in the slot connected to readyRead() use:
DataStream serialStream(serial); qint32 singleValue; for(;;){ // keep reading for as long as there is data serialStream.startTransaction(); serialStream >> singleValue; if(serialStream.commitTransaction()) qDebug() << "received: " << singleValue; else break; //stop when you tried to read more than you received }
@VRonin said in Windows serial port data lost:
This is the problem, readyRead is emitted when some data is available not when all data is available. use QDataStream. for example, assuming you are getting 32bits signed integers from the port, in the slot connected to readyRead() use:
No, that's not my problem. Let's say I send sequence of bytes 0x00 0x01 0x02 ... 0xFF 0x00 0x01 ........ at rate > 64 kB/s (trying to reach at least 512 kB/s) from my USB device.
I can detect a missing chunk in the middle of data in Qt app, I receive e.g. 0x00 0x01 .... 0x3F 0x80 0x81 .... 0xFF 0x00 0x01 .... (so 0x40 up to 0x7F = 64 bytes is missing) when the Qt thread is busy.
-
could you move the serial in another thread and see if you get the same problem? just after you create
serial
QThread* serialThread = new QThread; serial->moveToThread(serialThread); connect(serialThread,SIGNAL(finished()),serialThread,SLOT(deleteLater())); connect(serialThread,SIGNAL(finished()),serial,SLOT(deleteLater())); connect(serialThread,&QThread::started,[=]()->void{ if(!serial->open(QIODevice::ReadWrite)) // possible race condition but shouldn't cause any problems at this stage serialThread->quit(); }); serialThread->start();
-
could you move the serial in another thread and see if you get the same problem? just after you create
serial
QThread* serialThread = new QThread; serial->moveToThread(serialThread); connect(serialThread,SIGNAL(finished()),serialThread,SLOT(deleteLater())); connect(serialThread,SIGNAL(finished()),serial,SLOT(deleteLater())); connect(serialThread,&QThread::started,[=]()->void{ if(!serial->open(QIODevice::ReadWrite)) // possible race condition but shouldn't cause any problems at this stage serialThread->quit(); }); serialThread->start();
Thanks. That helped quite a lot. However, some data are still lost which is bad....
Just checked that my USB CDC device is sending data without a single error (all transfers are confirmed by USB protocol on the device side) so it really seems Windows or Qt is silently dropping the data.
-
That helped quite a lot. However, some data are still lost which is bad....
You can try to increase the driver's IO queues, using SetupComm function and see to result (use QSP::handle for this).
Also you can try to increase a FIFO size by clicking on a desired serial port from the Device Manager (as I remember).It happens when Qt thread is busy (e.g. when I move the window so it is forced to redraw).
Similar problem was untill Qt 5.5, but now isn't present any more.
I send data from USB full speed CDC ACM device
If you have your own custom CDC device (with custom firmware), then please look on your code of firmware. Because usual, many issues related to the user's microcode (maybe you are something missing in CDC ACM specification). Sdandard USB/serial adaptors works fine.
When the transfer rate is > 64 kB/s
I personally have checked QSP with FTDI on speeds up to 500BK/s, and all be fine.
-
That helped quite a lot. However, some data are still lost which is bad....
You can try to increase the driver's IO queues, using SetupComm function and see to result (use QSP::handle for this).
Also you can try to increase a FIFO size by clicking on a desired serial port from the Device Manager (as I remember).It happens when Qt thread is busy (e.g. when I move the window so it is forced to redraw).
Similar problem was untill Qt 5.5, but now isn't present any more.
I send data from USB full speed CDC ACM device
If you have your own custom CDC device (with custom firmware), then please look on your code of firmware. Because usual, many issues related to the user's microcode (maybe you are something missing in CDC ACM specification). Sdandard USB/serial adaptors works fine.
When the transfer rate is > 64 kB/s
I personally have checked QSP with FTDI on speeds up to 500BK/s, and all be fine.