Solved QSerialPort on Raspberry Pi 4, PL011 vs. mini-UART problem
-
Dear all,
I need to read binary data packets with my Raspberry Pi 4 from a third party device. The packets have the following structure:
- start tag '#'
- length byte
- data bytes
- checksum
- end tag '\r'
The format of the data packets cannot be changed.
When I use the mini-UART of the Raspberry Pi 4, everything is fine, even if every read operation returns only one byte at once. However, when I change to UART5 of the PL011 UARTs (/dev/ttyAMA*), reading stops when the end tag '\r' is received and the end tag itself is not returned. As data is sent in binary form by the device, the data packet may contain '\r' at a position different from the end of the packet and stopping there leads to errors.
I have not found an option in QSerialPort to change this behaviour (setTextModeEnabled(false) does not help). Does anybody know how I can change this and read binary data correctly using the PL011 UARTs on a Raspberry Pi 4? Or what am I missing here?
Thank you very much for your help!
Kind regards,
Ralf
-
Dear all,
of course it was my fault (again) :-)
For those who might experience the same problem, here is the explanation and the solution.
In my program, for whatever reason, when QSP reads data from the mini UART of the Raspberry Pi 4, waitForReadyRead() is triggered by every single byte and by pure coincidence my program works. However, the UART of the PL011 (or the driver) works differently. Here, data are delivered in chunks. When I want to read a packet of e.g. 27 bytes, I get 16 bytes with the first read(), then 11 with the second and waitForReadyRead() is only triggered twice. The terminating '\r' is already in the buffer and after having read 26 bytes, waitForReadyRead() fails, because it has already been triggered by the 17th byte. Using bytesAvailable() together with waitForReadyRead() solves the problem.
Once again, a problem between the keyboard and the chair :-)
Thanks to all who helped me!
Kind regards,
Ralf
-
QSP interprets the data only as a 'binary', it don't care about '\r' or any other characters, it operates with a data stream.
Or what am I missing here?
Most likelly, yes, try to find out a problem in your code.
setTextModeEnabled(false)
This does not work for QSP, because it always open in 'binary' mode, the QIODevice::Text flag will cause an opening error:
"Warning: The mode has to be QIODevice::ReadOnly, QIODevice::WriteOnly, or QIODevice::ReadWrite. Other modes are unsupported."
-
yes, you need to read and buffer characters until you see an end of message \r and then validate what is in the buffer to see if it is a conforming message. If so then you're good, otherwise keep reading until the next \r and repeat. When you find a complete message process and dispose of the characters leading up to and including the \r but save those after and assume start of next message.
Lots of very amateurish serial protocols out there and you make no mention of message spacing...and intermessage gaps required?
At least your protocol includes prudent information to aid in proper framing: header, length, crc, and end of message.
-
Dear all,
I used setTextModeEnabled(false) because I wanted to be sure that binary mode is selected (even if this is the default and only valid mode for QSP). The port is opened with QIODevice::ReadWrite (only option).
As far as the format of the data packet is concerned, things are easy: I have not developed the protocol and cannot change it, so I have to live with it. All I can say about the protocol is what I have already written in my first post. No information about spacing or intermessage gaps.
Fact is that for whatever reason my program works (== reads '\r') as long as I use the mini UART of the Raspberry Pi 4. This might be pure coincidence, I don't know. However, it does not read the '\r' when I use UART5 of the PL011 UARTs (what most likely is my fault).
I have taken a look at the data in the buffer with peek() and the '\r' is there as the last byte in the buffer. Conclusion: in the buffer, data are complete and I will have to continue my debugging sessions :-) When I have found the reason for my problems I will post it here.
Kind regards,
Ralf
-
Dear all,
of course it was my fault (again) :-)
For those who might experience the same problem, here is the explanation and the solution.
In my program, for whatever reason, when QSP reads data from the mini UART of the Raspberry Pi 4, waitForReadyRead() is triggered by every single byte and by pure coincidence my program works. However, the UART of the PL011 (or the driver) works differently. Here, data are delivered in chunks. When I want to read a packet of e.g. 27 bytes, I get 16 bytes with the first read(), then 11 with the second and waitForReadyRead() is only triggered twice. The terminating '\r' is already in the buffer and after having read 26 bytes, waitForReadyRead() fails, because it has already been triggered by the 17th byte. Using bytesAvailable() together with waitForReadyRead() solves the problem.
Once again, a problem between the keyboard and the chair :-)
Thanks to all who helped me!
Kind regards,
Ralf