2

As serial data bytes are being read from the serial buffer by Serial.read(), are they removed from the Arduino's 64-byte serial buffer altogether?

In my current situation I'm using SoftwareSerial, but this question applies to both software and hardware serial connections.

EDIT: Based on a comment from @dandavis, I'd like to further clarify my question

How does Serial.read() interact with Serial.available()? Let's say that I have the usual setup:

while( Serial.available() ) { 
    Serial.read();
} 

What causes Serial.available() to become false?

EDIT 2: Changed question title for even further clarification...

  • 1
    the only way you can "remove" a byte, is to overwrite it. ... i do not think that the library code does that, because that would be a waste of resources. ... i'm sure that the pointer into the buffer is the only thing that has changed. – jsotola Feb 6 '18 at 3:23
  • 1
    yes, you read() until available() is false, at which point the buffer is considered empty. – dandavis Feb 6 '18 at 3:53
  • 1
    What do you mean by "removed"? – user31481 Feb 6 '18 at 8:08
  • 2
    See the Wikipedia article Circular buffer. It has some figures and an animation that should help you understand how it works. – Edgar Bonet Feb 6 '18 at 8:41
  • If they weren't, you would only ever be able to receive 64 bytes. Does that sound logical? – Nick Gammon Feb 6 '18 at 10:12
0

Calculating how many bytes are available for reading:

int HardwareSerial::available(void)
{
  return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail))
}

It's so simple.

Have a look at the Arduino subdir (in your disk) hardware/arduino/avr/cores/arduino. The HardwareSerial.cpp is where you have to look at.

2

It is an internal buffer and only the pointer gets increased. It it visible in the source code off the project, located on github:

// Read data from buffer
int SoftwareSerial::read()
{
  if (!isListening())
    return -1;

  // Empty buffer?
  if (_receive_buffer_head == _receive_buffer_tail)
    return -1;

  // Read from "head"
  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  return d;
}

This third line from the bottom is the important part, it wraps back to the beginning if the buffer space has run out. If you call Serial.read(), the pointer is moved to the next position. So with the next Serial.read(), you'll get the next byte, if available. The byte itself gets overwritten only after the wrap (circular buffer).

  • 1
    That's call a circular buffer. – user31481 Feb 6 '18 at 8:29
  • 1
    You wrote: “The byte itself gets never overwritten”. It does, eventually, when that buffer cell is reused for storing a new incoming byte. – Edgar Bonet Feb 6 '18 at 8:47
  • @EdgarBonet. The moment the pointer advanced, the byte disappears, it's not longer there, it doesn't exists anymore from the perspective of the running code. – user31481 Feb 6 '18 at 8:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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