Serial1/2 on Due outputs nothing online, cpu halts when buffer full

Hello fellas - boy do I have a tricky one for you.

I have an Arduino Due here and I'm desiring to print out "hey boss" over & over again on Serial2.
I have an oscilloscope connected to TX2 (Pin 16).

Unfortunately my Serial2.println("hey boss") statements are not wiggling the output pin voltage, and (get this) if I do enough prints it will fill the buffer and the CPU halts.

I can tell this because i have Serial.print() in the same loop.

      Serial2.begin(9600);
      while (true) {
      
        Serial2.println("hey boss");
        Serial.println("hey boss");
        callback();
      }

callback() is doing I2C comms to an OLED display.

In my terminal I get this:

hey bows
hey bows
hey bows
hey bows
hey bows
hey bows
hey bows
hey bows
hey bows
hey bows
hey bows
hey bows

AAaaand then it stops. Its like the pin is constipated and it just won't output its volts. Who has any ideas?

Yep darn tricky without all the sketch !
And just as tricky is to see how it made "hey boss" into "hey bows"

Your board needs an updates spellchucker.

hah! good point. Yeah problem is the sketch is absolutely enormous. Like many many pages of stuff working together.

But I have made headway. If you use Serial1.begin(x) inside an object constructor things wont work.
I have a motor controller class which talks over serial, right. i figured hey why not put Serial1.begin(9600) in the controller's constructor?

Well it got me thinking. Object instantiation in the main context of the sketch - that must be magic time where magic things happen.

I merely put Serial1.begin() and Serial2.begin() in the setup() block and now stuff goes.

So yeah sorry for the no code, but I think I made up for it by getting to the root of the issue.

Quick followup:

You can indeed do subsequent Serial1.end() and Serial1.begin() statements in your code whereever you want. It seems that specifically, in the constructor, its a bad idea.

Thanks for the follow up.
Tips like that are always useful to others.
Karma added

:slight_smile: thank you dude. i appreciate. eats karma mm

I haven't determined if its Also don't call Serial.end() (the main serial device) in your code because its tied to the reset pins of your arduino. uh-oh spaghettio!

Actually I'm going to revoke my advice before about calling Serial.end() then Serial.begin() subsequent times in your sketch.

I've done it in an arduino nano. The point is actually to make the serial line bi-directional by using software serial (neoswserial) to TX out the RX pin. Using some real basic flow control to stop conflicts.

#include "NeoSWSerial.h"
//see if we can send data out of the RX pin of an active serial port.
//if not, use second arduino pin
NeoSWSerial ss((uint8_t)1, (uint8_t)0); //transmitting out the RX port.  (Nano: D0=RX, D1=TX). Constructor: rx,tx

void setup() {
  Serial.begin(115200);
  delay(50);
  Serial.println("BOOT");
  delay(200);

}
int t = 0;
int cl=0;
void loop() {
  // put your main code here, to run repeatedly:
  String r = Serial.readStringUntil('\n'); //blocks

  if (r.length() > 0 ) {
    Serial.print(cl);
    Serial.print("    ");
    Serial.print(t);
    Serial.println("  hey boss you said:" + r);
  }

  t++;
  cl++;
  if (t == 10 ) {
    t = 0;
    Serial.end();
    pinMode(0,OUTPUT);
    for (int i = 0; i < 10; i++) {
      digitalWrite(0, i % 2 == 0);
      delay(400);
    }
    pinMode(0,INPUT);
    Serial.begin(115200);
  }


}

why not put Serial1.begin(9600) in the controller's constructor?

Global constructors happen BEFORE the arduino core code starts, so the chip hardware is not initialized far enough for begin() to work.

Here's a blind guess: maybe you're doing the callback or otherwise doing other printing to the Serial1 or Serial2 from inside an interrupt?

As I recall, a year or two ago the Due hardware serial code was updated to use interrupts for transmitting. Normally that's a very good thing, since your print can go into the transmit buffer and the rest of your program gets to run without having to wait for the data to actually transmit. But if if the transmit buffer fills up, then Serial1.print needs to wait for the interrupt to actually transmit some of the data, so it can put the rest into that buffer.

However, if you print too much from within some interrupt and those buffers fill up, the serial transmit interrupt probably can't run because whatever interrupt your code is using is still running. So the Serial1.print waits forever for more room in the transmit buffer.

Just a completely blind guess to try to fit "AAaaand then it stops. Its like the pin is constipated". Maybe constipated is Serial1.print waiting for more room in that buffer?