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

License

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
  Copyright (c) 2019 garretlab.
  Added source code explanation by garretlab.
*/

/*
  HardwareSerial_private.h - Hardware serial library for Wiring
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  Modified 23 November 2006 by David A. Mellis
  Modified 28 September 2010 by Mark Sproul
  Modified 14 August 2012 by Alarus
*/

Last Update

July 31, 2025

inserted by FC2 system