Do I really need while (!Serial){};

I notice quite a few sketches use this just after Serial.begin()

void setup(){
  Serial.begin(115200);      // USB serial interrupts already in place 
  while (!Serial){}; 
  Serial.println("Hello"); 
  }

I've been playing in Arduino-land for over 10 years and have a wide variety of Arduino boards and man, many skethes, but I've never used while (!Serial).

As far as I know this has not caused me any problems. I understand what this command aims to do, but is it really important / necessary?

It depends what Arduino board you are using, and if you want to use Serial in your sketch.

2 Likes

It is needed only if you have an Arduino board that uses the serial port to communicate directly with the USB on your computer.

If it is in and you don't need it then the code will in effect skip over it. If it is not there and you do need it then there will be a delay in starting up and you are likely to miss any serial communication you get in the first few seconds.

1 Like

On avr the bool operator on the class

Is always true. It’s likely the optimizer will inline the function and see it’s doing nothing so the code might not even be in the final binary

1 Like

So it should useful on Uno R4 but not on Uno R3, or the other way around ?
But TBH I don't notice any difference

So it may do nothing under any circumstances?

The Arduino Micro has a USB-AVR that may not be USB initialized when setup() runs and take a little bit to begin serial.
Before the Micro was released, we didn't have that line.

Not needed on the R3 at all.

On the R4 however it is not recommended at all, and often causes problems when I have used it. At best it will not cause problems and at worst it will actually prevent ser serial port from starting up. The state of the firmware on the R4 is a bit flaky to say the least. A simple one second delay after the serial begin call always works for me.

If the bool operator on the HardwareSerial class is overloaded and just returns true as for the common avr based (UNO, Nano, Mega) based arduino then I’m saying it’s likely the compiler will generate for your
while (!Serial) {}
The equivalent (inlining the function)
while (!true) {}
And the optimizer knows that !true is false and thus the while will never run so this operation having no side effect and being useless will just be thrown away and not make it in your binary code at all for this target platform. It’s really just like if you had not written it in the first place

So it’s a good common practice to have it anyway so that you get portable code for platforms needing it.

2 Likes

interesting, so the consensus is ... it's a good idea.

Curiously I saw this variation recently too ....

void setup(){
  while (!Serial){}; 
  Serial.begin(115200); 
  Serial.println("Hello"); 
  }

which implies the Serial object exists even before Serial.begin
I'm not sure if this variant is any better, or no difference, or a dud :slight_smile:?

Yes the Serial instance does exist when you hit the setup() function.

for example for avr, the Serial ports are conditionally declared in the HardwareSerial.h class

and being instantiated at the end of the HardwareSerial0 class definition for Serial

(the others being in HardwareSerial1.cpp, HardwareSerial2.cpp and HardwareSerial3.cpp)

so it's technically OK to call a function on that instance.

In the case of a CDC implementation, for example on a SAMD platform, waiting for the Serial line to become available before initialising it seems to make sense (the baud rate is irrelevant) and is taken into account in the operator bool

OK, so then it makes sense to do the while (!Serial){}; as first line under setup

BTW what is correct term for Serial, is it an "instance" or an "object" ?

TIA

in Object Oriented programming instances and object are often synonymous. You could say Serial is an object (pretty generic then), or qualify this a bit more and say it's an instance of the HardwareSerial class.

basically instantiating a class gives you an object (and by extension of the verb, also an instance).

1 Like

gotcha, thanks

If you don't begin Serial.... see what calls to Serial get compiled.

to me, what you suggest implies a bug if it compiles which it won't.

Then which way around is best?

#1 ...

void setup(){
  Serial.begin(115200); 
  while (!Serial){}; 
  Serial.println("Hello"); 
  }

OR #2 ...

void setup(){
  while (!Serial){}; 
  Serial.begin(115200); 
  Serial.println("Hello"); 
  }

Whatever serial begin does, it puts about a 3K bump on the hex file.

OTOH I was given to believe unused code gets optimized out.

#1 not #2.

1 Like

Serial contains a bunch of “virtual methods” that cannot be detected to be unused.
It’s annoying, and an example of how C++ features can cause unexpected bloat.

2 Likes

I would say it depends on the architecture.

On the boards with native USB, the bool operator overload which is called when you do while (!Serial) ; or while (!SerialUSB); indicates whether or not the USB CDC serial connection is open and on other boards it just returns true as already discussed.

have a look at what begin() does when you are using CDC, Serial_ is the subclass of HardwareSerial

and this is the begin() content

âžś We can't say this is where all the mysterious set up of the Serial line (SerialUSB) happens....

@westfw

Perhaps, you meant
Serial contains a bunch of “virtual methods” that can{not} be detected to be unused{, and therefore cannot be excluded by the compiler}.
It’s annoying, and an example of how C++ features can cause unexpected bloat.

You may consider that to be just "wordsmithing", but I think it more clearly expresses the problem being described?