[Interest] Interest Digest, Vol 91, Issue 12

Roland Hughes roland at logikalsolutions.com
Sat Apr 6 19:47:04 CEST 2019

On 4/5/2019 5:00 AM, Denis Shienkov

Sorry for the quoting. Thunderbird wasn't cooperating this morning and I 
didn't have much time before starting work.

>Never ever ever do I/O in the main GUI thread of a Qt application.

>>Why not? It is an asynchronous. You can do I/O in a main thread, but handle
data in a separate thread (e.g. to parse it). Of course, it depends on the
used communication protocol and etc.
A main limitation is that on Windows all I/O stops when a user hold-on the
application window (ot to drag it, or do resizing). It is a Windows

>>So, yes, in a common case it is makes sense to move the QSerialPort object
to the different thread (a concept of workers).

Thank you for agreeing with me.

> Real world serial comm is fraught with peril. I've been doing it since

the days of DOS 3.1.

>It's not true.

It's completely true. There are any number of things, many of which beyond a programmer's control which can cause lost data. If you are just writing a chat program so you and a buddy can sit and type to each other in a dorm or something, no biggie. When you are pulling or pushing data feeds it's a real issue. An even bigger issue if you are controlling manufacturing or medical devices.

Ordinarily Wikipedia is untrustworthy in the best of times, but whoever wrote this about the 16550 UART actually knew something.


Ahhh the days when people bought that shiny new 14.4 modem then claimed it was junk because zip file transfers using Procomm kept getting corrupted or failed if they tried to use it above 9600. They blamed the modem when it was their UART. In case readers haven't heard of Procomm
http://procomm-guide.com/  wouldn't click on any download found there. The VT100 emulation was Linux/Windows quality VT100 not even close to real VT100 but dramatically closer than what Linux and Windows currently have (assuming one didn't purchase a commercial VT-100 terminal emulation package like Reflections or what Ericom has.)

That was back when everybody tried to run their own Bulletin Board System (BBS). Yes, even with the Internet, BBS hosts still exist today.


Today we have UARTs with blinding speed and the ability to perform DMA transfers. Digiboard made a name for themselves with 4, 8, 16 and 32 port add-in cards. Today I see they are down to 4/8 port cards. These now support 921.6Kbps


Other vendors are making 32-port USB appliances.

We will skip speaking of the USB appliances because that adds several more potential failure layers. All of the hardware involved in USB communications has to be able to handle the maximum throughput of all ports at any given moment. Somewhere, in a commodity desktop or laptop you will have USB hardware unable to live up to the task.

> Unless something has dramatically changed in QSerialPort, readyRead is

>only emitted for the first character in the buffer because there is no
concept of block or packet. A UART handles one byte at a time.

>It's not true too. The readyRead() will be triggered when the device's
handle/descriptor becomes 'signalled/activated' (when something comes into
FIFO of driver), in this case the QSerialPort reads all data which are in
this time in the FIFO (there are may be some bytes). So, no any
byte-per-byte handling as you say.

Thank you for agreeing with me again. It is true.

Yes, unless significant improvements have happened with QSerialPort (not even sure the class itself could fix the problems) the intricate little dance from UART to FIFO to driver to your application can get interrupted at such a point with some bytes left behind and the readyRead not firing again. Usually happens at higher data rates, 115K or higher. Might not even be Qt's fault. See note about 921.6Kbps communications above.

>> I don't know about what you say... It is trash for my opinion.. For you has
been provided a good code example how to read the lines:

>      QSerialPort * port;
>      QObject::connect(port, &QIODevice::readyRead, port, [port] () ->

void  {

>          while (port->canReadLine())  {
>              QByteArray data = port->readLine();
>              // emit with data as argument and do the parsing
>          }
>      });

No. I have been provided a student type example suitable for two friends and their chat window program. Even in a chat program, if one of the users types quickly, this will stutter and sputter. Every read will be a varying number of characters. Even if the other end is only sending bytes after the return key has been hit this reading will sputter characters onto the screen.

Most terminal software, by default, disables local echo. What that means is when you press a key the representation does not show up in your window until it has gone to the target and been echoed back. When connecting a terminal to a host computer such as a midrange or mainframe this was done for visual verification of the communications channel. BBS software continued that protocol (for lack of a better term) as did Procomm and the other communications packages of the day.

In today's Internet world most chat utilities send only when the send is pressed. They will generally use a low level transport (UDP or something like that) which allows for full packet transmission leaving the application completely oblivious to the mechanics of that.

Serial comm requires you to do all of that work and mistakes get made. Noise on the line isn't handled properly and a host of other perils.

The original "user story" from interest Digest, Vol 91, Issue 1
I'm trying to implement a serial connection with QIODevice (SerialPort). I
would like to parse line by line (each line consists of multiple columns of
data) and for this I found canReadLine().
But as I understand I have to use startTransaction, because otherwise the
buffer will not be used. I'm I correct?

This topic thread is a shining example of why AGILE is a completely fraudulent methodology. Nobody read the "user story." Everybody provided a slam-bam-thank-you-mam answer because that was easiest and they believed it "solved the story."

Context is everything someone else sputtered on here. In this case, everybody but me chose their own "context" completely ignoring the context of the user story.

(each line consists of multiple columns of data)

Everybody chose to ignore that portion of the "user story."

This __isn't__ a chat program. There is a device of some kind feeding this data. Most likely a production system unless someone is just collecting smarthome data locally for their own interest.

This device has an unknown baud rate. Is it 300 BAUD or 921.6Kbps or something in between?

We have an unknown transmission rate. Is it one line per hour, day, second? How many "columns" in a line? How many, on average, bytes in each column? Does each line really end with a newLine character or does this have the traditional <STX>text data<ETX>  No, those aren't XML or any other kind of tag, they are ASCII protocol bytes.  STX is used to indicate Start of Text and ETX used for End of Text.

This communication, if for a production system, needs to be in its own thread. It has to algorithmicly assemble each line THEN signal out a complete line for the main (or another) thread to process.
Keep in mind that Windows and Linux have been more tightly integrating network communication with the kernel. It is now possible for a completely unrelated application to hang the kernel while it waits for some kind of network timeout. Like many OpenSource bugs they are being fixed by rotting until expiration.


While your kernel is hung your particular UART, if it is hardware only and only needs power, will continue putting characters into its internal buffer. If your kernel hasn't de-hung itself by the time an interrupt or other configured "full FIFO" needs to fire, you are now losing transmission data.

Yes, there are software UARTs.


Roland Hughes, President
Logikal Solutions
(630)-205-1593  (cell)

More information about the Interest mailing list