UART binary issue - might help others
-
I recently moved some code over from a project I had running on HLK-7688A devices.
It uses RS485 to communicate with other devices.I simply re-compiled the code using the Onion cross-compiler and it all seemed to work nicely.
Except one thing...
Every now and then I would get a corrupt message from a remote device. A chksum embedded in the protocol would not match, and ocasionally a length byte in the received bytes would be wrong too.
I thought it might be just a noisy RS485 line but when probing the actual RX line going into the Omega showed a perfectly valid signal.On the wire the bytes would look something like this (in hex):
21 24 56 58 0D 00 01 00
But in the app the bytes being read() from the port would be something like:
21 24 56 58 0A 00 01 00
Thing is that the error was consistently the same error. Not like noise or random bits being flipped. Always the exact same corruption. I had never seen this before, this code had run fine on the HLK-7688A
It turns out that it was the terminal options I was setting on the file descriptor of the port I opened using open().
After opening the port withfd = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
I then use tcgetattr and tcsetattr to get the port options and modify things like the baudrate, parity, flow-control etc. I was using this:
options.c_iflag &= ~(IXON | IXOFF | IXANY);
But I had to change it to :
options.c_iflag &= ~(IXON | IXOFF | IXANY | ISTRIP | ICRNL);
To stop the pre-parser stripping the 8th bit from bytes and to stop it converting 0D to 0A (ie. CR to NL).
This is a bit of a simplified explanation, but it shows it pays to be careful with the options flags!
Funny how this never came up on the HLK-7688A - but they do use a very different build from OpenWRT.