HardwareSerial::_rx_complete_irq()

Abstract

The _rx_complete_irq() is called from an interrupt handler, USART_RX_vect, which is called when a serial data is received. This function copies data from the receive buffer of ATmega328P to the receive buffer of Arduino.

Source Code

The _rx_complete_irq() is defined in hardware/arduino/avr/cores/arduino/HardwareSerial_private.h as below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void HardwareSerial::_rx_complete_irq(void)
{
  if (bit_is_clear(*_ucsra, UPE0)) {
    // No Parity error, read byte and store it in the buffer if there is
    // room
    unsigned char c = *_udr;
    rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;
 
    // if we should be storing the received character into the location
    // just before the tail (meaning that the head would advance to the
    // current location of the tail), we're about to overflow the buffer
    // and so we don't write the character or advance the head.
    if (i != _rx_buffer_tail) {
      _rx_buffer[_rx_buffer_head] = c;
      _rx_buffer_head = i;
    }
  } else {
    // Parity error, read byte but discard it
    *_udr;
  };
}

It has no input and no output.

1
2
void HardwareSerial::_rx_complete_irq(void)
{

First it checks if there is a parity error. To do that, it checks the UPE0 bit of _ucsra(UCSR0A) using bit_is_clear(). If the value is 0, there is no parity error, go on to receive data.

 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
if (bit_is_clear(*_ucsra, UPE0)) {
  // No Parity error, read byte and store it in the buffer if there is
  // room
  unsigned char c = *_udr;
  rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;
 
  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != _rx_buffer_tail) {
    _rx_buffer[_rx_buffer_head] = c;
    _rx_buffer_head = i;
  }

The _udr(UDR0) is a register that holds received data.

The _rx_buffer_head is a variable to indicate the position where the received data to store in the receive buffer. Calculating the next position(this is the reason of +1), if it is same as _rx_buffer_tail, it means buffer overflow, so the data is not stored. This means at least one byte is not used in the receive buffer. If not, the data is stored in the receive buffer. Then updates the _rx_buffer_head.

17
18
19
20
21
  } else {
    // Parity error, read byte but discard it
    *_udr;
  };
}

If there is a parity error, read _udr but discards it.

Version

Arduino AVR Boards 1.8.6

Last Update

March 21, 2023

inserted by FC2 system