UNO USART Receive Shift Register and interrupts shut off

Hello,

first something to the background of my question.

In my project I'm controlling a LED stripe (with WS2811 Controller) with an UNO from a handy app over a Serial Bluetooth communication.
Because I learned, that while controlling the stripe, the interrupts has to be off, but for the communication, the interuppts has to be on, I splitted both processes from each other.

I implemented a handshake, so that the handy could send a request while the controlling of the stripe is still activ (and interrupts are off). If the app wants to send a new colour or program order, it only sends the char 'R' as a request.

I assumend that this one char would always reach the Receive Shift Register respectively the receive buffer of the USART, regardless to the fact whether the interrupts are off or on and I can look for it, when the stripe controlling is done, to switch over to the communication process.

But is that corretly or am I just lucky that it works? I can't really answer that question by myself when reading the chapter in the datasheet 24.8. Data Reception – The USART Receiver. :confused:

Eventough this periode of controlling the LED stripe with the interrupts being shut off is only about 369 µs, I'm still unsure whether it is theoretically possible that the char could get lost, if it arrives right in this moment? This would lead to a hang up of my communication sequence.

What datasheet are you reading?

I suspect there is a deal of luck in what you are doing. I believe the USART will receive a single character while interrupts are off but (I believe) that character will not be passed to the Serial Input Buffer until interrupts resume. And based on that I believe that a second character would be lost. And if the data flow gets mixed up it might not be the 'R' that is received and processed.

A more reliable method might be for the Arduino to send an 'R' when it is ready for more data.

I know nothing about the LED controller you are using or whether it really does need interrupts to be OFF for a long period of time. That would seem to be very poor programming.

...R

Thanks for the answer. You are the right one to answer, because my sketch is based very much on your thread Serial Input Basics - Programming Questions - Arduino Forum


What datasheet are you reading?

The datasheet "Atmel-42735B-ATmega328/P_Datasheet_Complete-11/2016" from the link in the store http://www.atmel.com/Images/doc8161.pdf


I suspect there is a deal of luck in what you are doing. I believe the USART will receive a single character while interrupts are off but (I believe) that character will not be passed to the Serial Input Buffer until interrupts resume.

On side 233 starts the chapter "24.8. Data Reception – The USART Receiver".
There is written: "The USART Receiver is enabled by writing the Receive Enable (RXEN) bit in the UCSRnB Register to '1'."
Than in chapter 24.8.1. is written, "The Receiver starts data reception when it detects a valid start bit. Each bit that follows the start bit will be sampled ... and shifted into the Receive Shift Register until the first stop bit of a frame is received. ... When the first stop bit is received, i.e., a complete serial frame is present in the Receive Shift Register, the contents of the Shift Register will be moved into the receive buffer."
This sounds to me like at least one frame does go right into the buffer, without anything else but with the initialisation of the USART with "Serial.begin()" in "void setup()". But I'm not sure about it and that's the reason why I'm asking in this forum.


And based on that I believe that a second character would be lost. And if the data flow gets mixed up it might not be the 'R' that is received and processed.

But my handy app does only send the 'R'. That was my thought, that this one sign survives whatever happens because the USART receiver is always ready to receive just by hardware once it is activated.


A more reliable method might be for the Arduino to send an 'R' when it is ready for more data.

This could also be a way. What I wouldn't like, is that I should have to send periodically a "ready", instead of that the handy app sends a request, if it really has something to say.


I know nothing about the LED controller you are using or whether it really does need interrupts to be OFF for a long period of time.

The LED controller is from Adafruit NeoPixel and the library, the advice not to use interrupts when controlling it and the time calculations I'm using are from Nick Gammon GitHub - nickgammon/NeoPixels_SPI: Arduino library for NeoPixels


That would seem to be very poor programming.

"Eijeijei!" (German expression), somebody may get into trouble for this! :sweat_smile:


I didn't want to mention my project again, because I did it before in this forum at another place. I was afraid, it would look like boasting, but maybe for more information about the background of my questions, here's again the link GitHub - orje/LEDviaApp_UNO: Control a LED stripe with the Arduino UNO over a handy app, programmed with the Quantum Leaps' QP™-nano active object framework, its QM™ modeling tool and the MIT App Inventor 2
I would like to get a definitive answer, whether one sign will arrive the receive buffer and stay there until I sample it with Serial.read() or Serial.available(), regardless of the state of the interrupts.

many thanks

orje:
This sounds to me like at least one frame does go right into the buffer,

That datasheet doesn't know anything about Arduinos. It is talking about a buffer within the USART. The Arduino responds to the interrupt generated by the USART to move the byte from the USART buffer to the Arduino Serial Input Buffer. Obviously that can only happen when interrupts are enabled.

...R

That datasheet doesn't know anything about Arduinos.

I agree with you in terms of the USB communication through the Atmega16U2 on the board.


But my communication between the ATmega328P on the board and the handy app over the Bluetooth HC-06 module goes right through to the intern UART serial communication of the microcontroller connected to the board pins 0 (RX) and 1 (TX).
For that reason, the RX and TX LEDs on the board don't flash, when the datas are being transmitted or received (to be seen in my short video on github/youtube). This is explained in the "DOCUMENTATION" tab from the UNO in the store Arduino Uno Rev3 — Arduino Official Store.


By the way. There is another mysterious fact in the datasheet regarding the function of the Receiver: There is a Data OverRun flag. In the sheet on page 235 in chapter "24.8.4. Receiver Error Flags" is written, "A Data OverRun occurs when the receive buffer is full (two characters), a new character is waiting in the Receive Shift Register, and a new start bit is detected." This sounds like the buffer can even take 2 frames/charactrers.


But this is not my first interest. This is still, whether at least one char arrives the buffer without any interrupt.

orje:
I agree with you in terms of the USB communication through the Atmega16U2 on the board.

The Atmega 328 datasheet has nothing whatever to do with the Atmega 16U2 that is on the Arduino board.

I still think you are confusing the Atmega microprocessors with the Arduino software that uses them.

This is still, whether at least one char arrives the buffer without any interrupt.

I can only answer that question after you tell me what buffer your are referring to.

...R

Why on earth would the tens of microseconds it takes to handle a serial interrupt make any difference whatsoever to the blinking of a bunch of LEDs? That makes no sense whatsoever....

Regards,
Ray L.

Why on earth would the tens of microseconds it takes to handle a serial interrupt make any difference whatsoever to the blinking of a bunch of LEDs? That makes no sense whatsoever....

You should read up on the tight timing requirements of the WS2811 data interface. It usually requires specifically-tuned write routines, written in assembler. Some of the most recent research has relaxed the timings somewhat.

I would like to get a definitive answer, whether one sign char will arrive the receive buffer and stay there until I sample it with Serial.read() or Serial.available(), regardless of the state of the interrupts.

Yes, one two1 received characters will stay in the USART Data Register until the pending RX char interrupt is serviced (by the RX char ISR) after enabling the interrupts. A second third character can begin, as long as the first two characters are read from the USART data register before the second third character's STOP bit is received.

The ISR copies the character from the USART data register into the Serial input buffer, where it safely remains until your code calls Serial.read(). Because the input buffer only has room for 64 characters, you must read some of those characters sometime before the 65th character arrives. This is not a problem in your scenario.

Serial.available() has no effect on the USART or the input buffer.

Cheers,
/dev


1 See westfw's excellent correction below.

-dev:
Yes, one received character will stay in the USART Data Register until the pending RX char interrupt is serviced (by the RX char ISR) after enabling the interrupts.

I think that's what I said in Reply #1 but I was not believed.

...R

Thanks to all, especially to /dev.

This answer "saves my day".
Because of this nicety of the hardware, my communication between the UNO and the handy app is "waterproofed".

@Robin2
you wrote:

Robin2:
I suspect there is a deal of luck in what you are doing. I believe the USART will receive a single character while interrupts are off but (I believe) that character will not be passed to the Serial Input Buffer until interrupts resume.

Excuse me, but your answer wasn't that clear to me, then the answer of /dev. I hope you don't mind.

orje:
Excuse me, but your answer wasn't that clear to me, then the answer of /dev. I hope you don't mind.

And Reply #3 ?

...R

The uart on the AVR can receive and buffer two characters without being serviced. One is buffer, one sits in the receiver shift register. A third character is discarded, and should cause the overrun flag to be set.

Here's a small sketch demonstrating this:

#include <util/delay.h>

void setup() {
  Serial.begin(115200);
}

void printWhatsThere()
{
  while (Serial.available()) {
    Serial.write(Serial.read());
  }
}

void loop() {
  Serial.println("Disabling interrupts");
  Serial.flush();   // wait for pending output
  cli();
  _delay_ms(5000);  // busy-loop delay, not depending on interrupts
  sei();
  Serial.print("Interrupts re-enabled.  Pending input: ");
  printWhatsThere();
  Serial.println();
}
Disabling interrupts

(type 1234 in Serial Monitor)

Interrupts re-enabled.  Pending input: 12

Disabling interrupts


(type 5678 in Serial Monitor)

Interrupts re-enabled.  Pending input: 56

Disabling interrupts
Interrupts re-enabled.  Pending input:
Disabling interrupts

@Robin2
I think, that this was really the misunderstanding between us:

I still think you are confusing the Atmega microprocessors with the Arduino software ...

I was talking about the hardware and you were talking about the software.
But to me, what really is important, that the question is answered. Other people will benefit from it.
Do you agree?

In the interests of global peace I will refrain from comment,

I am glad that you have a solution.

...R

@westfw
Thanks for that code to try