2
\$\begingroup\$

I have two boards:
Board M: Master board
Board S: Slave board
I am trying to implement an UART communication (data length=8bits) protocol between them. Master board M shall send requests to the slave board S and the latter shall answer.

Example 1:
M board (Tx) --> GET_VALUE --> (Rx) S board
S board (Tx) --> 150 --> (Rx) M board

Example 2:
M board (Tx) --> GET_STATUS --> (Rx) S board
S board (Tx) --> I_AM_READY --> (Rx) M board

Example 3:
M board (Tx) --> GET_STATUS --> (Rx) S board
S board (Tx) --> I_AM_BUSY --> (Rx) M board

I have some questions:
1. Is it a good choice to use a FIFO ring buffer in UART ISR?
2. How to choose the number of Bytes exchanged between the two boards?
3. How to choose the buffer size?
4. Which mode is better for this type of communication? Half duplex or Full duplex ?
5. which type of data should I use ? Should I define some macros like this:

#define GET_VALUE  0x01
#define GET_STATUS 0x02

or I just use this implementation:

#define BUFFER_LENGTH = x;
uint8_t buffer[BUFFER_LENGTH] = "GET_VALUE\n";
\$\endgroup\$

closed as too broad by Andy aka, Chris Stratton, laptop2d, Sparky256, Finbarr Feb 20 '18 at 11:34

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ There is a lot more that could be said. However, since you accepted the single answer within minutes, you are clearly not interested in a wide range of opinions. Answering here is not a good way to spend limited volunteer time. \$\endgroup\$ – Olin Lathrop Feb 16 '18 at 12:15
  • \$\begingroup\$ Well, I am really interested in all your opinions! I am just a new member and I thought that accepting an answer doesn't mean that the user is not interested others opinions. My bad I am sorry about this. \$\endgroup\$ – Pryda Feb 16 '18 at 13:02
2
\$\begingroup\$
  1. Seems good, just make sure you check for a fully filled buffer (means you will lose bytes). Or have to prevent sending more.
  2. This depends how much is the difference between receiving and handling them. If there can be some difference, you need a bigger buffer. If you can make sure you process incoming bytes almost immediately, the buffer can be small.
  3. It should be the maximum (or reasonable) size of data you want to store before you are able to process it. Or to prevent the sender to send more.
  4. I don't have experience with this.
  5. Definitely the first, instead of having to send multiple bytes, you only send one byte, and you don't have to check for the end of a command, just every value (0x00, 0x01) is a single command. Only send texts through communication channels if you really need the text, otherwise decode it to a unique number. I would do the same for the return value, e.g. I am ready is 0x00, and I am busy ix 0x01.
\$\endgroup\$
2
\$\begingroup\$
  1. Yes, absolutely. In fact, use two ring buffers -- one for received bytes and another for bytes to be transmitted.
  2. You have to define a protocol that specifies the number of bytes contained in each message. The purpose of the protocol is so that both sides can be programmed to recognize and interpret the messages correctly. The number of bytes should not be less than necessary. The number of bytes will depend on whether you choose a binary or ASCII protocol. For example if the range of VALUE is +/- 2^15 then you could send that message with just two bytes in a binary protocol but an ASCII protocol could require as many as seven bytes ("-32768\n"). For binary protocols you have to define the byte order (endianness) of mult-byte values.
  3. The buffer size should be at least big enough to hold the largest message. But why not make it much bigger? You probably have plenty of RAM that you're not going to use. If the buffer size is a power of two then you can reset the buffer pointers more quickly with a bit-wise mask operation (instead of compare and set operations). So make your buffer 64, 128 or 256 bytes.
  4. The master/slave protocol you described is half-duplex -- only one device is transmitting at any given time. Why would you consider full-duplex? If I told you that you should use full-duplex what would you do differently?
  5. If you want the protocol to be human readable then use an ASCII protocol. You might want it to be human readable so that you can easily partake from a terminal application or view it on a serial port monitor/snooper. Or maybe you're going to publish the protocol and you want it to be easy for the public to understand. But a binary protocol will be easier to program. So if human readability is not important then use a binary protocol.

  6. What you haven't considered yet is error handling. What are the chances that a byte is dropped or corrupted by noise on the wire? How will your programs recognize and handle a protocol error? If error handling is important then you should consider message framing. Frame delimiters allow your programs to recognize when a message begins/ends. And a frame check sequence allows your programs to verify that the message was received correctly.

\$\endgroup\$
  • \$\begingroup\$ Can you please give me an example for an ASCII protocol and a Binary based protocol ? \$\endgroup\$ – Pryda Feb 16 '18 at 16:14
  • 1
    \$\begingroup\$ You already gave examples in your question. A binary protocol would send the code 0x01 meaning "get value" whereas an ASCII protocol would send the text "GET_VALUE\n". If value equal 10000 decimal then the binary protocol might send two bytes representing the hexadecimal equivalent in little endian order (0xE8, 0x03), whereas the ASCII protocol would send the text "10000\n". \$\endgroup\$ – kkrambo Feb 16 '18 at 16:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.