serial interface not working without sketch upload

I have a frustrating and irksome problem with an Arduino Due board (model DUE R3-E).

The symptom is that, after rebooting the Linux host computer that powers the board (via the USB programming port), no data is received by the host over the serial interface.

To narrow the problem down, I wrote a simple sketch that prints the micros() timestamp every second and also toggles the LED on pin 13 at the same time. From this, I can tell from the blinking of the LED that the sketch really is running even when no data is received by the host. Now, if I re-upload the same sketch (using "arduino ... --upload ..." then suddenly the host can receive data over the serial interface and the host/board combo works fine from then on.

Is there something I need to do to bring the serial connection to life after a cold start? There must be something that "arduino ... --upload ...", or the bootloader, does to the board that I am not doing to it. I don't want to start up the arduino program or upload the sketch with the command line to handle this because the host computer does not normally have a keyboard or monitor attached to it.

I have searched far and wide but can't find any mention of this problem. More detail below.

Any ideas on where to look would be greatly appreciated.

The host computer is running standard Ubuntu 16.04 (x86_64) with minor changes:

  • I added my user to 'tty' and 'dialout' groups and logged out/in (in fact, rebooted several times).
  • I purged the "modemmanager" package to stop it from trying to open /dev/ttyACM0 when the board is plugged in.

The full sketch code is:

    void setup()
        Serial.setTimeout(10 /* ms */);
        pinMode(13, OUTPUT);

   void loop()
        unsigned const timestamp = micros();
        static unsigned last = timestamp;

        if (timestamp >= last + 1000000) {
            static bool led = false;
            digitalWrite(13, led ? HIGH : LOW);
            led = !led;

            Serial.println("hello " + String(timestamp));

            last = timestamp;

The program on the host computer that attempts to read from the serial port does the following:

  • open() device with flags O_RDWR | O_NOCTTY | O_NONBLOCK
  • retry the open() in case of EBUSY, after an interval of 1 second
  • reset the board by clearing DTR for 0.125 seconds and then setting it back again
  • set termios attributes: c_iflag=0, c_oflag=0, c_cflag=CS8 | CREAD | CLOCAL, c_lflag=0, 115200 baud, VMIN=1, VTIME=0

For what it is worth, the retry-in-case-of-EBUSY seems to be needed for the first 15 or so seconds after unplugging and reinserting the USB cable into the host computer (without rebooting it). I have checked with "fuser /dev/ttyACM0" that no other process has the device open during this period, so it is not the "modemmanager problem" again, but I am also curious what is going on here.