Don't put any members after these buffers, since only the first 32 bytes of this struct can be accessed quickly using the ldd instruction

In HardwareSerial.h file there is a set of following line. What does it say? I did not understand.

Is that saying, that only 32 bytes can be accessed in buffer? or What? Could some one explain me this?

    // Don't put any members after these buffers, since only the first
    // 32 bytes of this struct can be accessed quickly using the ldd
    // instruction.
    unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
    unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];

I have sent 100's of bytes over serial without issue. Reread what was written and you may see that there is not an indication of byte limit but a statement that the first 32 bytes can be accessed quickly; what ever that means.

And really that tiny code snippet does not say much.

gcjr will be along in a minute, basically.

these are buffers used by interrupt service routines

on the write side, the following indicates that an arduino program will be blocked if the buffer is full until space becomes available

// If the output buffer is full, there's nothing for it other than to
// wait for the interrupt handler to empty it a bit

i believe on the receive side, data will be lost if the buffers are filled if the arduino program doesn't not check/read the serial interface often enough (32 bytes takes ~32 msec at 9600 bps)

this line of code from HardwareSerial::_rx_complete_irq suggests that by using the mod operator (%) the compiler will optimize the code to simply mask (0x1f) the buffer index to minimize processing time w/in the ISR

  rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;

@mustaq_ahm Are you referring to the AVR library: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial.h#L110
There is a 'ldd' instruction and maybe some things are faster. However in this situation I think that text is totally nonsense.

@gcjr In HardwareSerial.h of the AVR branch, the buffer is set to 64 bytes. For microcontrollers with little RAM, it will be 16 bytes. Two blocks of 16 bytes make a block of 32 bytes and maybe that can be optimized for certain instructions. If you have a Arduino board with a ATmega processor with less then 1kbyte, then it is still trivial if that optimization can be noticed. Even the ATmega8 has 1024 bytes of RAM.

The LDD (Load Indirect with Displacement) instruction is a variant of the LD (Load Indirect) instruction. It uses the Y register as a pointer and a six-bit displacement to offset the address. The displacement is a value from 0 to 63. I think what they are trying to say is that if you have a 'struct' of 64 bytes or fewer you can load any byte of the struct with one LDD instruction after loading the Y pointer only once.

This has nothing to do with the buffer arrays since the byte to be fetched is not known at compile time.

The 16-bit opcode is:
10q0 qq0d dddd 0qqq
d bits are the register to load
q bits are the displacement value

2 Likes

john, thanks for the explanation

More extensively, the structure looks like this:

    volatile tx_buffer_index_t _tx_buffer_head;
    volatile tx_buffer_index_t _tx_buffer_tail;

    // Don't put any members after these buffers, since only the first
    // 32 bytes of this struct can be accessed quickly using the ldd
    // instruction.
    unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
    unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];

    int HypothethicalNewVariable;

The comment means that the HypothethicalNewVariable I added would be slower to access than the variables before the buffers, because of the limitations of LDD that John explained.

It's pretty stupid; the Arduino Serial code isn't very well optimized ANYWAY, and the extra cycles to access some new variables in the "wrong" place are pretty meaningless in the grand scheme of things.

Still, it'd be better to add new variables BEFORE the buffers, if you have to add new variables (say, to support HW flow control or RS485 or something.)