Software Serial Research and Questions

I have been doing a lot of googling in and out side of Arduino.cc in regards to the software serial. Unfortunately, I'm not getting solid warm-fuzzy information.

First question, what software serial libraries are out there?

Does the current Arduino built-in library for SoftwareSerial contain blocking code or is that from a past version?

The latter I was warned on, but some of my results show this may be from an older version or may still apply.

It appears there was a SoftwareSerial from Arduino then a NewSoftSerial was developed to overcome some limitations and issues of Arduino's version. Then NewSoftSerial was adopted and renamed as SoftwareSerial and is now what you get when you load Software Serial from the library manager. I think this is true but the question still applies, does the current Arduino built-in library for SoftwareSerial contain blocking code or is it 100% interrupt driven and the blocking is gone.

If the last of that is true, then back to question 1, what other libraries are out there? Are they any better? Do they have blocking issues?

I think this is some pretty good information on the topic: https://arduino.stackexchange.com/a/34130

I think this is true but the question still applies, does the current Arduino built-in library for SoftwareSerial contain blocking code or is it 100% interrupt driven and the blocking is gone.

From my experience dealing with the programming/operations of SoftUART, the serialEvent() routine is not attached with SoftUART. serialEvent() is a routine (subroutine or ISR?) which is automatically called upon when the Receiver Section of the HardUART has received a character.

GolamMostafa: serialEvent() is a routine (subroutine or ISR?) which is automatically called upon when the Receiver Section of the HardUART has received a character.

At least in Arduino AVR Boards, it's actually pretty stupid: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/main.cpp#L47

if (serialEventRun) serialEventRun();

https://github.com/arduino/ArduinoCore-avr/blob/6e235622edb1b882401c77c171b0e738a093fd5b/cores/arduino/HardwareSerial.cpp#L64-L68

void serialEventRun(void)
{
#if defined(HAVE_HWSERIAL0)
  if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
#endif

So it's the equivalent code of this:

void loop() {
  if(Serial.available()) {
    serialEvent();
  }
}

I'd much rather put those few lines of code in my sketch when I need them and not have the overhead of a function call on every single loop when I don't. When practical, I prefer to be able to follow the program code rather than having some special function called out of nowhere. IIRC at some point in the distant past serialEvent() either was called or was planned to be called from an interrupt. I forget the details.

void loop() {
if(Serial.available()) {
serialEvent();
}
}

Very nice derivation; I would not know it before. (Thanks+.)

In Arduino HardUART, the receiver section is interrupt driven. So, I follow the first principle – I always write codes for the serialEvent() function and keep waiting in the loop() for the interrupt signal. As I know that the serialEvent() function will be called upon when the receiver is ready with a character, I do not execute the Serial.available(); function in the serialEvent() routine. I read the character from the FIFO, save it in the user array, and then check the received character if it is an end-of-string marker; if so, I go for processing.

void setup()
{
    //intialize evrything as needed
}

void loop()
{
   //wait for receiver interrupt

}

void serialEvent()
{
   dataArray[index] = Serial.read();
   if (dataArray[index] == end-of-string)
   {
      //do string processing
   }
   index++;
}

GolamMostafa:
and keep waiting in the loop() for the interrupt signal. As I know that the serialEvent() function will be called upon when the receiver is ready with a character

It’s not an interrupt. It will only be called after loop() returns:

int main(void)
{
 init();

 initVariant();

#if defined(USBCON)
 USBDevice.attach();
#endif
 
 setup();
    
 for (;;) {
 loop();
 if (serialEventRun) serialEventRun();
 }
        
 return 0;
}

If you have blocking code in your loop then serialEvent() will be blocked.

GolamMostafa:
I do not execute the Serial.available(); function in the serialEvent() routine.

Makes sense as that function will only be called when there are characters available.

adwsystems: First question, what software serial libraries are out there?

As well as the standard SoftwareSerial there are also AltSoftSerial and NeoSWSerial. I believe both of them are better than the standard one.

...R Serial Input Basics - simple reliable ways to receive data.

It's not an interrupt. It will only be called after loop() returns:

This is where my confusion is as to calling the serialEvent() function -- a simple subroutine or an ISR?

The MCU has been waiting in the loop() function without executing any instructions. Then, how does it enter into the serialEvent() routine unless it is interrupted! From this understanding, I have been always considering serialEvent() -- an ISR.

Examine the code I posted in my last two replies carefully. I think it will be clear.

pert: Examine the code I posted in my last two replies carefully. I think it will be clear.

I have also said much the same thing in Serial Input Basics

...R

@GolamMostafa, I was under the same impression once upon a time. Then finally someone showed me the programming in main().

int main(void)
{
    init();

    initVariant();

#if defined(USBCON)
    USBDevice.attach();
#endif

    setup();
    
    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }
        
    return 0;
}

That also explains how setup() is used. As you can see loop() is just another subroutine and after loop() has executed it checks to see if serialEvent exists and should be executed; otherwise it returns to the top of loop().

While this is a good discussion on the hardware serial port, it does not address the question at hand. Robin2 mentions two libraries back in post #6, anyone know of any other libraries?

Robin2 mentions two libraries back in post #6, anyone know of any other libraries?

See link in reply #1.

pert: I think this is some pretty good information on the topic: https://arduino.stackexchange.com/a/34130

Looks like all four options are available through the Arduino IDE and/or library manager. Yes?

It also appears that only the hardware option has a serialEvent(). Yes? If so, this would be another reason to stick with serial.Available().

adwsystems: It also appears that only the hardware option has a serialEvent().

Ignore serialEvent(). You get identical functionality with

if (Serial.available > 0) {
   // do something
}

...R

Ignore serialEvent(). You get identical functionality with

For practical reasons, we do ignore many things; but, it is difficult to ignore serialEvent() function when the principle says that the arrival of a character in the receiver interrupts the MCU; in response, the MCU calls upon the serilaEvent() routine (subroutine or ISR?). Program codes written following this principle work well!

serialEvent() is not interrupt driven, it is a subroutine called at a fixed point in the sequence unchangeable without customizing the main.cpp file provided with the Arduino IDE.

If the program was:

loop() { ...all your loop stuff if (serial.Available()) { serial stuff } }

The you are correct there is no difference between that and

serialEvent() { serial stuff }

loop() { ...all your loop stuff }

in terms of the sequence of execution. Both are loop() then serial.

BUT if the program is loop() { ...some of your loop stuff if (serial.Available()) { serial stuff } ...rest of your loop stuff }

Then there is a big difference in the sequence of execution. The latest is some loop() then serial then more loop(). If it is critical for the serial to be checked between the two halves then serialEvent() cannot be used.

Personally, I prefer to have my ISR say ISR. Such as

ISR (PCINT0_vect) // Pins D8 to D13
 {
  unsigned long current_time;
  current_time = millis();
 }

Notice that serialEvent() does not include the keyword ISR. Instead I have to remember when, where, how it is called because the function call does not appear anywhere in my .INO file and is not marked as an ISR.

That is not my point. My point is that only the hardware serial has serialEvent(). All other option only have serial.Available().

Notice that serialEvent() does not include the keyword ISR. Instead I have to remember when, where, how it is called because the function call does not appear anywhere in my .INO file and is not marked as an ISR.

Just for the shake or argument, I can ask the question: From where does data come into the variable when we execute the instruction byte x = Serial.read();? The data comes from the FIFO buffer which is not seen by the user; but, it is seen by the Serial.Read(); function.

ISR is a keyword that we must use while declaring user-defined ISR; for a system-initiated ISR? like serialEvent() use of ISR is prohibited.

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

void loop() 
{
  //waiting for interrupt?
}

void serialEvent()  //receives character (s) from Serial Monitor.
{
  byte x = Serial.read();
  Serial.write(x);
}

GolamMostafa: but, it is difficult to ignore serialEvent()

Not the least bit difficult. I never use it.

I just use the code from Serial Input Basics

...R

Not the least bit difficult. I never use it.

You took the full advantage of your liberty which we also deserve to enjoy! :)

GolamMostafa, your sketch does not work for this reason you think. You are so sure serialEvent() is an ISR try this:

In your example sketch Add set pin 13 to output and low In loop() add for(); (now loop will never end) In serialEvent() add digitalWrite(13, HIGH); then type in the serial monitor and let me know is the LED comes on.