# Using circular buffer over UART

I am setting up an UART protocol that allows the communication between 2 boards; A Master board and a Slave board. The communication between them is going to be like this:
Example 1 :
Master [Tx] -- GET_VALUE--> [Rx] Slave
Master [Rx] <-- 0x05 -------- [Tx] Slave

Example 2:
Master [Tx] -- GET_STATUS -----------> [Rx] Slave
Master [Rx] <-- I_AM_BUSY ------------ [Tx] Slave

Example 3:
Master [Tx] -- START_OPERATION --> [Rx] Slave
Master [Rx] <----------ACK------------[Tx] Slave

Data size is 1 Byte for most of data flow between the two card. That's why I am going to use macros to define these commands:

Example:

  #define GET_VALUE 0x05
#define START_OPERATION 0x06
etc ...


In addition to these 1-Byte-data, There is only one element that should be transmitted between the two boards that it's size is not 1 Byte. In fact, I am willing to use serialization to transmit a data structure over UART using a circular FIFO buffer

Example:
Master [Tx] -- GET_STRUCTURE ------------> [Rx] Slave
Master [Rx] <----------STRUCTURE------------[Tx] Slave

typedef struct{
uint8_t var1;
uint8_t var2;
uint8_t var3;
}MyStructTypeDef;


Shall be transmitted over UART in this format "variable_name:valueXXX":

var1:123XXXvar2:456XXXvar3:789XXX

XXX is a separator

My question is: If 99% of data flow is 1 Byte sized and only 1% of the data flow is not 1 Byte sized, Should I use circular buffer only to get the structure? Is there a better way to standardize the length of data passed over uart?

• You have two distinct difficulties here. The first is devising a 1-byte protocol that can also move arbitrary values without confusion. Unless you need speed you might consider letters and digits; or using a 7-bit number format with the 8th bit reserved for your special status codes. In terms of buffering that tends not to be about meaning but rather if you are able to process the data as it arrives. If so you might simply have a "struct being collected" buffer rather than a circular one. If not you'll probably want to pass everything through a buffer between the ISR and the consumer. – Chris Stratton Mar 8 '18 at 17:54
• is this lock-step or asychronous, with MASTER send more than one command before checking for responses? – Jasen Mar 8 '18 at 19:03
• @Jasen It's Asynchronous – Pryda Mar 8 '18 at 19:26
• It would be much easier to send your structure as 4 bytes: one byte saying what is happening (call it THIS_IS_MY_STRUCTURE or whatever) and then the 3 structure bytes. They are one-byte variables, just send the byte instead of converting it to decimal. – user253751 Mar 8 '18 at 21:59

Can the master busy-wait on the UART waiting for responses? Can it collect and process the received characters fast enough to avoid overruns? If not then you need a buffer.

If the longest message will fit in the buffer and you reset it when sending each command then it doesn't need to be circular.

I am willing to use serialization to transmit a data structure... in this format "variable_name:valueXXX"...

Is there a better way to standardize the length of data passed over uart?

I presume the 'XXX's pad the string out to a fixed length. It could be more efficient to create a variable length string with single character separators, or even send the numbers in raw binary, but if bandwidth isn't an issue then what you are doing is fine.

You might also want to think about what to do if the master and slave get out of sync. For example if the slave is sending a structure but the master is expecting a reply to a different command, some of the characters in the structure message might be misinterpreted as valid responses. Also this,

Master [Tx] -- GET_VALUE--> [Rx] Slave
Master [Rx] <-- 0x05 -------- [Tx] Slave


is troubling. Can the 'value' be any binary number? If so then how will you know it is not a response to some other command? Critical responses such as I_AM_BUSY and ACK should have unique values that cannot appear in other data.

you could have the ISR that services the serial receive interruot write directly to variables, it would need to tracs its own state so that it knows where to write.

you may need a mutex is update glitches could be a problem.

for sending it would need to know what things need to be sent