I'm having a really weird issue with my project right now. I have an Atmega2560 using hardware serial, and the software on the other side is doing full duplex read/write at 500kbps. If I change it to be single duplex, everything works fine. But the second I try to run everything truly full duplex, I start to have some data transfer over from the transmit stream to receive stream on the device (characters that its trying to write, that it somehow ends up reading again).

I've simplified things as much as possible- disabling buffering on the arduino side, using mutexes on the client software side (to prevent overlapping read/write commands, despite the fact the underlying driver will do whatever it wants).

So, there's obviously a few potential problems here, but it has to boil down to:

a) Client software/drivers misbehaving

b) Hardware serial implementation misbehaving on the device.

I really want to rule out B, and from all my digging around, it really comes down to one question:

Is there any possible way that data written to the UDR register could somehow be read out again? I understand this register is actually 2 different registers, and just splits out reads and writes. But is there any possible way at all this data could be read again? Like, is it possible to even write to UDR and read that byte ever again? I'd really like to rule that out before I start unnecessarily tracing ISRs and all that garbage.

Here's what I've boiled the hardware serial code down to. Interrupt driven on read and direct write on write:

void MarlinSerial::write(uint8_t c) {
  while (!TEST(M_UCSRxA, M_UDREx));

  M_UDRx = c;

ISR(M_USARTx_RX_vect) {
  const unsigned char c = M_UDRx;

UPDATE: I'm an idiot. Found a buffer overrun way downstream in the device code. It just so happened that the temp response buffer for one routine butted up against the receive buffer, so it delightfully just over-ran into there. I'm happily chugging away now with 2 totally async command streams, total about 400kbps.

  • 1
    Not an answer, but are you checking the flag bit that indicates that there is data available, before you try to read the data register? If that is not indicating that there is data available, it may not be well defined what you would obtain by reading it. Commented Jun 2, 2017 at 1:39
  • 2
    If the bytes you write to the USART came back from it all by themselves, that would be a very serious hardware bug. Hardware bugs do happen, see the Errata section of the datasheet, but that one would be too egregious to go unnoticed. Commented Jun 2, 2017 at 8:06
  • I am checking the flag before doing a write, im using interrupts for the read so I shouldn't have to check any flags. As far as hardware bugs, it's a cheap board, supposedly using the same chips as the Arduino 2560, but they could be knockoffs or something, or just bad circuit design. Commented Jun 2, 2017 at 14:38

1 Answer 1


Is there any possible way that data written to the UDR register could somehow be read out again?

No, there is no possibility. The datasheet says:

The USART Transmit Data Buffer Register and USART Receive Data Buffer Registers share the same I/O address referred to as USART Data Register or UDRn. The Transmit Data Buffer Register (TXB) will be the destination for data written to the UDRn Register location. Reading the UDRn Register location will return the contents of the Receive Data Buffer Register (RXB).

Further on it says:

The transmit buffer can only be written when the UDREn Flag in the UCSRnA Register is set. Data written to UDRn when the UDREn Flag is not set, will be ignored by the USART Transmitter. When data is written to the transmit buffer, and the Transmitter is enabled, the Transmitter will load the data into the Transmit Shift Register when the Shift Register is empty. Then the data will be serially transmitted on the TxDn pin.

And for reception it says:

The receive buffer consists of a two level FIFO. The FIFO will change its state whenever the receive buffer is accessed. Due to this behavior of the receive buffer, do not use Read-Modify-Write instructions (SBI and CBI) on this location. Be careful when using bit test instructions (SBIC and SBIS), since these also will change the state of the FIFO.

So the only thing it is possible to read is data that has been received via the RX pin (and then once and once only). All written data (assuming there is room in the TX buffer) is sent out of the TX pin.

If you are getting TX data appearing in the RX buffer then somewhere there must be some kind of connection between the TX and RX pins - either in software at the remote end (the remote device echoing everything it receives, which is perfectly possible depending on what the remote device is), or though a fault in the cabling or circuit design.

  • Damn it all. Believe it or not, that rules out the "easy" answer to my problem. The board is an Elegoo Mega 2560- Should have the same USB chip and everything, but it was cheap as dirt and I definitely would not rule out a bad circuit design somehow allowing cross talk between the lines. The client side software is run on OSX, and just uses the standard open/ioctl/read/write access to the TTY. So if there's something wrong on the client side, it has to be something with the USB serial drivers (not even sure what drivers its uses for this USB UART). Commented Jun 2, 2017 at 13:34
  • Just tried a different computer, running Linux this time, and got rid of ALL other USB devices besides this one, still the exact same issue =\ So it's not looking like its the client drivers fault... Commented Jun 2, 2017 at 14:28
  • @ColinGodsey: Are you sure echo is not enabled on the Unix side? Commented Jun 2, 2017 at 14:42
  • @EdgarBonet Yea, no echoing. If I simplify the test to just "call and response" (no actual simultaneous r/w), it works fine. Even running a CRC on the other end, I can push about 400kbps of data with 0 errors. It just becomes an issue when I start reading while writing and vice versa. Commented Jun 2, 2017 at 15:38
  • arg, see note above. was just some downstream buffer overrun issues Commented Jun 2, 2017 at 15:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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