Reading from a serial port
The code you posted contains no error-recovery at all. It's a bit off-topic on this site to ask how to implement a new feature (error-recovery); but I'll try.
It's not clear what your communication protocol looks like. It might be:

A continuous stream of bytes, to be split into packets of 10
10-byte packets, with a measurable delay between packets, no reply expected
10-byte packets, after which silence until there is a reply, perhaps with a retry if there no reply

I'll assume it isn't 1. because that has little opportunity for error-recovery: if a byte were ever lost then you wouldn't know where the boundary is between &quot;packets&quot;, if it's a continuous stream of bytes, unless you use 'framing' and 'escape sequences' in the data.
So I'll assume that it's 2. or 3.. In either case, what's important is:

There are 10 bytes received (probably received quickly with little or no delay between bytes)
There is then a delay (no bytes received) after those 10 bytes.

Setting Read Timeouts looks interesting. It may be your best algorithm: set VMIN to say that you want to receive no more or less than exactly 10 bytes when you read.
However that may have a problem:

However, the timeout only applies to the first character read, so if for some reason the driver misses one character inside the N byte packet then the read call could block forever waiting for additional input characters.

You don't say why you want error-recovery after losing a character: perhaps you sometimes get overruns in the driver, or bit parity errors from the serial port?
&quot;Setting Input Parity Options&quot; talks about handling the parity errors:

Replace/mark the byte with an error byte
If you do this then you can be more sure that you will get 10 bytes; but you can only do it if the protocol allows you to recognize an illegal byte value.

Or remove the error byte
If you do this then you must be able to recover from getting 9 bytes sometimes.



The data I receive should be always 10 bytes in length but I want to be sure that, if there is any error (more or less bytes received), reading will clear buffer before the next data arrive, so that there is always proper data in the buffer to be processed.

Reading should empty the buffer, if your sizeof(tmp_buffer) is bigger is the number of bytes queued in the driver. However:

It depends on the read mode (e.g. a read may block forever instead of clearing the buffer, if VMIN is set to non-zero)
If there are, somehow, very many received bytes enqueued in the driver, then you may have to read repeatedly until the driver is empty.
Immediately after you read, there may be more bytes in the driver: for example if the serial port is flow-controlled, reading from the driver allows the device to send again / send more.

Whether you can clear the buffer &quot;before the next data arrive&quot; is difficult to say: I don't know when the next data is supposed to arrive.
Depending on how you handle parity errors, maybe bytes are never lost. If bytes are sometimes lost then you may want to implement logic like:
read_10_bytes:
  read (waiting forever) until some bytes are returned
  if 10 bytes were read then return
  if less than 10 bytes were read, then:
    set an expiry timer
    loop doing the following
  read more bytes
  if you read 10 bytes before the timer expires, then clear the timer and return
  if the timer expires before you read 10 bytes, then discard the bad bytes and return

Instead of actually setting a timer, above, perhaps loop doing a blocking-read-with-timeout (which either reads the bytes, or expires).
As well as handling too few bytes (above), you could modify the above to check for receiving more than 10 bytes: after you receive 10 bytes, do another blocking-read-with-small-timeout to verify that there are no more bytes to receive. If there are extra bytes, then read them all before returning to the 'waiting-for-next-10-bytes' state (otherwise, these extra bytes will mess up your next 10-byte packet).

I think there's an obvious bug in the code. After you read 16 bytes, you completely clear your serial_buffer by zeroing si_processed, and you then think &quot;success!&quot; after each next 10 bytes you read.
Instead you should:

If you read too much data, don't discard the extra bytes: instead use memmove to move them to the beginning of the buffer (assuming they're the start of the next packet), and then read the subsequent bytes into the vacant space after them.

Something like:
// after reading and processing a 10-byte packet
if (si_processed &gt; 10) // already have the start of the next packet
{
     // move start of next packet to start of buffer
     memmove(serial_buffer, serial_buffer+10, si_processed - 10);
     // not 0: remember how many start bytes we already have
     si_processed -= 10;
}


After you read any bytes, verify whether the start byte is your 0xA5 value, and discard the bytes if not.

Something like:
if (si_processed &gt; 0) // have some bytes
{
    int i;
    for (i = 0; i &lt; si_processed; ++i)
        if (serial_buffer[i] == 0xA5) // found start of packet
            break;
    if (i &gt; 0)
    {
        // start of packet is not start of buffer
        // so discard bad bytes at the start of the buffer
        memmove(serial_buffer, serial_buffer+i, si_processed - i);
        si_processed -= i;
    }
}