0
\$\begingroup\$

I have two MCUs: one running embedded Linux and the other FreeRTOS and I want to be able to send variable-sized payloads between them and large amounts of data (probably upto 5K bytes or so). Ideally, the receiver should determine the number of bytes received rather than the transmitter sending a separate field indicating the number of bytes sent.

The main concern is around determining the physical protocol (e.g UART) given the larger max size of the payload, and allocating a 5K long buffer may be a bit of an overkill on an embedded system perhaps given the payload is not always maxed out.

Also, Linux device uses POSIX APIs including read(), write() that need to know how many bytes need to be received/sent and in my case, the sender isn't specifying the amount of bytes to be sent. The only way I could think of is to read each byte until an end-of-byte char is received but not sure how practical this approach would be

One idea could have been the use of pipes but FreeRTOS and Linux use different mechanisms?

\$\endgroup\$
2
  • 3
    \$\begingroup\$ how would the receiver know that all data was successfully received? \$\endgroup\$
    – jsotola
    Oct 18, 2021 at 4:15
  • \$\begingroup\$ this may or may not help ... pjon.org \$\endgroup\$
    – jsotola
    Oct 18, 2021 at 4:18

2 Answers 2

0
\$\begingroup\$

SPI at 10 MHz is a good choice.

Use fixed payload size, 1024 for example, in order to use DMA interrupt. You don't want to fire an interrupt each time one byte is received or transmitted.

Use DMA on both Linux and FreeRTOS.

\$\endgroup\$
2
  • \$\begingroup\$ SPI because of high data transfer rate? and why specifically 10MHz? also the payload size isn't supposed to be fixed \$\endgroup\$
    – xyf
    Oct 18, 2021 at 4:37
  • \$\begingroup\$ SPI is a synchronous interface and it is much faster than UART. 10 MHz is a pretty low bit rate for an SPI interface and I suggest you to start your tests from that value. DMA interfaces are meant for fixed size data transfer and I suggest you to start your tests from 1024 bytes chunks. \$\endgroup\$ Oct 18, 2021 at 17:10
0
\$\begingroup\$

Partial answer: a typical way to read variable-length data packets in Linux is to buffer a certain number of bytes in the application. You create a buffer of, say, 16 kilobytes, then you call read to fill up the whole buffer. read won't wait for 16 kilobytes; it'll just return however many bytes have already been received by the kernel. But it does wait for at least 1 byte, so it's not busy-waiting and wasting CPU cycles.

Let's say read returns 5000. So now you have 5000 bytes in your buffer. Then you look at the start of your buffer and somehow figure out if you got the whole packet (that part is up to you). Suppose you got a 3000-byte packet; then you do whatever you want with the packet, and you check the next 2000 bytes. Suppose they aren't a whole packet, because this packet is 2500 bytes long but you've only got the first 2000. Then you shift the 2000 bytes to the start of the buffer, and go back to read. When you call read, you only ask it to read into the last 14k bytes of empty space, so it doesn't overwrite the 2000 bytes you haven't processed yet. And you repeat this forever.

It looks something like this:

char buf[BUF_SIZE];
int bytes_in_buffer = 0;
while(true) {
    int bytes_read = read(..., buf + bytes_in_buffer, BUF_SIZE - bytes_in_buffer);
    // add error checking here
    char *pos = buf;
    while(is_whole_packet(pos, bytes_in_buffer - (pos - buf))) {
        int packet_size = get_packet_size(pos);
        process_packet(pos, packet_size);
        pos += packet_size;
    }
    int bytes_processed = pos - buf;
    memmove(buf, pos, bytes_in_buffer - bytes_processed);
    bytes_in_buffer -= bytes_processed;
}
\$\endgroup\$
2
  • \$\begingroup\$ how are you determining the start of the packet though? I was thinking of clearing out the buffer once the end-of-byte char is received so any new data will be a part of the next new packet \$\endgroup\$
    – xyf
    Oct 18, 2021 at 18:46
  • \$\begingroup\$ @xyf The start of a packet is right after the end of the previous packet. \$\endgroup\$
    – user253751
    Oct 19, 2021 at 9:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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