I managed to get the rpi and crius boards to talk over the serial port at 500000 baud.
All I had to do is add init_uart_clock=16000000 in /boot/config.txt on the rpi and that’s it – I can send data over. Now the problem is getting data across reliably. This proved more problematic and I ended up spending 3 days on it.
I’m using a simple wrapper class that packs arbitrary messages and passes them through a socket. The packet structure used to be this:
[msg] -> uint8_t
[payload size] -> uint8_t
[crc] -> uint16_t. This is the crc of the whole package, including the msg and the size
This allowed me to detect corrputed packages and ignore them.
The packets are processed like this:
- read the first byte if data – this is assumed to be the message
- read the size
- read the crc
- zero out the crc byted in the data stream
- compute the crc for the data stream up to [size] bytes
- if crc is ok – we have a message
- if the crc is wrong, pop the first byte and reiterate
It’s done like this because I avoid using message markers to save bandwidth – so I have to assume that any byte can be the beginning of a message.
Problem is that when a 200 byte message is corrupted the code skips each byte and treats the rest as a potential new message and so on, until all the 200 bytes are exhausted. This takes too long.
Second problem is that in order to detect a corrupted message, I need the whole message to compute its crc. This is an issue as the corrupted byte might be its size – which will result in waiting for bytes that might never come (or come very slowly).
To fix these I changed the message structure to this:
[magic] – 0x3F – early out for corrupted messages
[msg] – uint8_t
[size] – uint8_t
[header crc] – uint8_t – this is the crc for the header only so a crc8 is sufficient. Also quick to compute.
[payload crc] – uint16_t
The header crc allows me to detect and discard very quickly corrupted messages – only 4 bytes are needed to discard any message of any size.
This added 2 bytes of overhead though but for now it’s ok.